; Declare the string constant as a global constant. ; run the following command to run this LLVM assembly program: ; sh run-llvm-code.sh helloworld.ll @LC0=internalconstant [13xi8] c"hello world\0A\00" ; note how the newline character is inserted into the string
; External declaration of the puts function declarei32@puts(i8*)
; Definition of main function definei32@main() { ; Convert [13 x i8]* to i8* ; this is because the function puts takes a char* which is an i8* in LLVM %cast=getelementptr [13xi8], [13xi8]* @LC0,i80,i80 ; read up on getelementptr: http://llvm.org/docs/GetElementPtr.html
; Call puts function to write out the char* string to stdout. calli32@puts(i8* %cast) reti320 }
CMake 项目中嵌入 LLVM 库
Clion 使用 CMake 作为项目的构建工具,使用 CMake 引用 LLVM 非常方便。
1 2 3 4 5 6 7 8 9 10 11
# llvm settings. set(LLVM_DIR /Users/pandaos/llvm-project/build/lib/cmake/llvm) # 默认安装则不用设置 LLVM_DIR find_package(LLVM REQUIRED CONFIG) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) add_executable(llvm_test main.cpp) # llvm_test 是 project name # Link against LLVM libraries target_link_libraries(llvm_test ${llvm_libs})# llvm_test 是 project name
// this global variable contains all the generated code static llvm::Module *TheModule; static llvm::LLVMContext TheContext; // this is the method used to construct the LLVM intermediate code (IR) static llvm::IRBuilder<> Builder(TheContext);
intmain(){ TheModule = new llvm::Module("test1", TheContext); // ...... TheModule->print(llvm::errs(), nullptr); // standard error return0; }
TheModule 里面有所有生成的代码,用下面这种方法可以打印
1 2
TheModule->print(llvm::outs(), nullptr); // standard output TheModule->print(llvm::errs(), nullptr); // standard error
llvm::AllocaInst *Alloca; // unlike CreateEntryBlockAlloca the following will // create the alloca instr at the current insertion point // rather than at the start of the block Alloca = llvm::Builder.CreateAlloca(llvm::IntegerType::get(TheContext, 32), 0, "variable_name");
// Create a new basic block which contains a sequence of LLVM instructions llvm::BasicBlock *BB = llvm::BasicBlock::Create(TheContext, "entry", func); // insert "entry" into symbol table (not used in HW3 but useful in HW4) // All subsequent calls to IRBuilder will place instructions in this location Builder.SetInsertPoint(BB);
Builder.SetInsertPoint 很重要,设置 Builder 代码插入位置。
为参数创建对应的局部变量并添加到符号表,这样就可以用符号的形式访问参数。
1 2 3 4 5 6 7
for (auto &Arg : func->args()) { llvm::AllocaInst *Alloca = CreateEntryBlockAlloca(func, Arg.getName()); // Store the initial value into the alloca. Builder.CreateStore(&Arg, Alloca); // Add to symbol table syms.enter_symtbl(Arg.getName(), Alloca); }
一些辅助函数
1 2 3 4 5 6 7 8
llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); // gives you a link to the current basic block
llvm::Function *func = Builder.GetInsertBlock()->getParent(); // gives you a pointer to the function definition
func->getReturnType() // gives you the return type of the function
插入 return 语句
1 2 3 4
// sometimes the return statement is deep inside the method // so it is useful to retrieve the function we are in without // passing it down to all the AST nodes below the method declaration Builder.CreateRet(llvm::Value*)
函数调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14
llvm::Function *call; // assign this to the pointer to the function to call, // usually loaded from the symbol table
std::vector<llvm::Value *> args; // argvals are the values in the method call, // e.g. foo(1) would have a vector of size one with value of 1 with type i32.