Object used to incrementally build up our IR .
The equivalent of a file-pointer when reading/writing a file.
Inserting Instructions at End of a block
SetInsertPoint (BasicBlock * TheBB)
Getting Current Basic Block
GetInsertBlock ()
Creating Instructions
Using the Create*()
methods of the IRBuilder object
Takes an optional Twine
argument that gives the register a custom name like iftmp
. which is the twine for this instruction: %iftmp = phi i32 [ 1, %then ], [ %mult, %else]
Refer to the https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html docs for help building instructions.
CreateLoad
Creates a LLVM load instruction
CreateSub
Creates a LLVM sub instruction
CreateFSub
Creates a LLVM fsub instruction
CreateAlloca
CreateStore
Getting Types
Using the get*()
methods of the IRBuilder object
Example:
Value * IRCodegenVisitor :: codegen ( const ExprIntegerIR & expr ) {
return ConstantInt :: getSigned (( Type :: getInt32Ty ( * context)),
expr.val);
};
Getting Function Types
Using the FunctionType::get
Requires parameters for:
returntype
paramater types
whether the function is Variadic
FunctionType :: get (returnType, paramTypes, false /* doesn't have variadic args */ );
Creating Struct Types
StructType * treeType = StructType :: create ( * context, StringRef ( "Tree" ));
Creating Multiple Structs
The best way to do this is to define all the structs initially like Preprocessor Directives and then define their bodies later.
void IRCodegenVisitor :: codegenClasses (
const std :: vector < std :: unique_ptr < ClassIR >> &class es ) {
// create (opaque) struct types for each of the classes
for ( auto & currClass : classes) {
StructType :: create ( * context, StringRef (currClass->className));
}
// fill in struct bodies
for ( auto & currClass : classes) {
std ::vector < Type *> bodyTypes;
for ( auto & field : currClass->fields) {
// add field type
bodyTypes. push_back (field-> codegen ( * this ));
}
// get opaque class struct type from module symbol table
StructType * classType =
module-> getTypeByName ( StringRef (currClass->className));
classType-> setBody ( ArrayRef < Type * >(bodyTypes));
}
Creating Globals
module-> getOrInsertGlobal (globalVarName, globalVarType);
...
GlobalVariable * globalVar = module-> getNamedGlobal (globalVarName);
globalVar-> setInitializer (initValue);
Or, use the LLVM Namespace GlobalVariable
Value * ptr = builder-> CreateGEP (baseType, basePtr, arrayofIndices);