0
votes

I am attempting to write some compiler and use LLVM to generate intermediate code. Unfortunately, LLVM documentation is not very great and even somewhat confusing.

At the moment I have lexer,grammar and AST implemented. I was also following some examples found on Internet. My current AST works as follows: it has the abstract base class Tree*, from which other trees inherit (so, like one for variable definition, one for statement list, one for binary expression etc.).

I am trying to implement the variable definition, so for the input

class Test{
   int main() 
   {
     int x;
   } 
}

I want LLVM output to be:

; ModuleID = "Test"

define i32 @main() {
entry:
   %x = alloca i32
   return i32 0
}

However, right now I can get %x = alloca i32 part to the part where main function is created, but the actual output is missing the %x = alloca i32. So, the output I'm getting is as follows:

; ModuleID = "Test"

define i32 @main() {
entry:
   return i32 0
}

my Codegen() for variable declaration is shown bellow (symbol table for now is just a list, I am trying to keep things as simple as possible at the moment):

llvm::Value *decafStmtList::Codegen() {

string name = SyandTy.back(); // Just a name of a variable
string type = SyandTy.front(); // and its type in string format
Type* typeVal = getLLVMType(decafType(str2DecafType(type))); // get LLVM::*Type representation
llvm::AllocaInst *Alloca = Builder.CreateAlloca(typeVal, 0, name.c_str());
Value *V = Alloca;
return Alloca;//Builder.CreateLoad(V, name.c_str());
} 

The part where I am generating my @main is as follows: Note: I have commented out the print_int function (this is the function I will use later to print things, but for now I don't need it). If I'll uncomment the print_int function, TheFunction will not pass verifier(TheFunction) -> complains about module being broken and parameters not matching the signature.

Function *gen_main_def(llvm::Value *RetVal, Function *print_int) {
  if (RetVal == 0) {
    throw runtime_error("something went horribly wrong\n");
  }
  // create the top-level definition for main
  FunctionType *FT = FunctionType::get(IntegerType::get(getGlobalContext(), 32), false);
  Function *TheFunction = Function::Create(FT, Function::ExternalLinkage, "main", TheModule);
  if (TheFunction == 0) {
    throw runtime_error("empty function block"); 
  }
  // Create a new basic block which contains a sequence of LLVM instructions
  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
  // All subsequent calls to IRBuilder will place instructions in this location
  Builder.SetInsertPoint(BB);

  /*
  Function *CalleeF = TheModule->getFunction(print_int->getName());
  if (CalleeF == 0) {
    throw runtime_error("could not find the function print_int\n");
  }*/
  // print the value of the expression and we are done
 // Value *CallF = Builder.CreateCall(CalleeF, RetVal, "calltmp");



 // Finish off the function.
 // return 0 from main, which is EXIT_SUCCESS
  Builder.CreateRet(ConstantInt::get(getGlobalContext(), APInt(32, 0)));
  return TheFunction;
}

If someone knows why my Alloca object is not being generated, please help me out - any hints will be greatly appreciated.

Thank you

EDIT:

Codegen is called from the grammar:

start: program

program: extern_list decafclass
{ 


    ProgramAST *prog = new ProgramAST((decafStmtList *)$1, (ClassAST *)$2); 
    if (printAST) {
        cout << getString(prog) << endl;
    }
     Value *RetVal = prog->Codegen();
     delete $1; // get rid of abstract syntax tree
     delete $2; // get rid of abstract syntax tree

     // we create an implicit print_int function call to print
     // out the value of the expression.

     Function *print_int = gen_print_int_def();
     Function *TheFunction = gen_main_def(RetVal, print_int);
     verifyFunction(*TheFunction);
}

EDIT: I figured it out, basically the createAlloca has to be called after the basicblock when generating main;

1

1 Answers

0
votes

There are two weird things here:

  1. All you do is call Builder.CreateRet... I don't see how there could be any code in main unless you call something that creates the corresponding instructions. In particular, you never seem to call the CodeGen part.

  2. You pass a size of zero to CreateAlloc. I think the size should be one for a single variable.

Also, make sure that you don't call any LLVM optimization passes after generating your code. Those passes would optimize the value away (it's never used, thus dead code).