In this recipe you, will learn how to generate IR code for a function.
Do the following steps:
Codegen()
function for the function call can be defined as follows:Value *FunctionCallAST::Codegen() { Function *CalleeF = Module_Ob->getFunction(Function_Callee); std::vector<Value*>ArgsV; for(unsigned i = 0, e = Function_Arguments.size(); i != e; ++i) { ArgsV.push_back(Function_Arguments[i]->Codegen()); if(ArgsV.back() == 0) return 0; } return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); }
Once we have the function to call, we recursively call the Codegen()
function for each argument that is to be passed in and create an LLVM call instruction.
Codegen()
function for a function call has been defined, it's time to define the Codegen()
functions for declarations and function definitions.The Codegen()
function for function declarations can be defined as follows:
Function *FunctionDeclAST::Codegen() { std::vector<Type*>Integers(Arguments.size(), Type::getInt32Ty(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getInt32Ty(getGlobalContext()), Integers, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Func_Name, Module_Ob); if(F->getName() != Func_Name) { F->eraseFromParent(); F = Module_Ob->getFunction(Func_Name); if(!F->empty()) return 0; if(F->arg_size() != Arguments.size()) return 0; } unsigned Idx = 0; for(Function::arg_iterator Arg_It = F->arg_begin(); Idx != Arguments.size(); ++Arg_It, ++Idx) { Arg_It->setName(Arguments[Idx]); Named_Values[Arguments[Idx]] = Arg_It; } return F; }
The Codegen()
function for function definition can be defined as follows:
Function *FunctionDefnAST::Codegen() { Named_Values.clear(); Function *TheFunction = Func_Decl->Codegen(); if(TheFunction == 0) return 0; BasicBlock *BB = BasicBlock::Create(getGlobalContext(),"entry", TheFunction); Builder.SetInsertPoint(BB); if(Value *RetVal = Body->Codegen()) { Builder.CreateRet(RetVal); verifyFunction(*TheFunction); return TheFunction; } TheFunction->eraseFromParent(); return 0; }
Codegen()
functions can be called in the wrappers written to parse top-level expressions as follows:static void HandleDefn() { if (FunctionDefnAST *F = func_defn_parser()) { if(Function* LF = F->Codegen()) { } } else { next_token(); } } static void HandleTopExpression() { if(FunctionDefnAST *F = top_level_parser()) { if(Function *LF = F->Codegen()) { } } else { next_token(); } }
So, after parsing successfully, the respective Codegen()
functions are called to generate the LLVM IR. The dump()
function is called to print the generated IR.
The Codegen()
functions use LLVM inbuilt function calls to generate IR. The header files to include for this purpose are llvm/IR/Verifier.h
, llvm/IR/DerivedTypes.h
, llvm/IR/IRBuilder.h
, and llvm/IR/LLVMContext.h
, llvm/IR/Module.h
.
llvm-config
tool can be used as follows:llvm-config --cxxflags --ldflags --system-libs --libs core.
toy
program is recompiled with additional flags as follows:$ clang++ -O3 toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -o toy
toy
compiler is now run on example
code, it will generate LLVM IR as follows:$ ./toy example define i32 @foo (i32 %x, i32 %y) { entry: %multmp = muli32 %y, 16 %addtmp = add i32 %x, %multmp reti32 %addtmp }
Another example2
file has a function call.$ cat example2
:
foo(5, 6);
Its LLVM IR will be dumped as follows:
$ ./toy example2 define i32 @1 () { entry: %calltmp = call i32@foo(i32 5, i32 6) reti32 %calltmp }
Codegen()
functions for C++ in Clang, refer to http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/3.149.27.72