0

我正在尝试编写一些编译器并使用 LLVM 生成中间代码。不幸的是,LLVM 文档不是很好,甚至有些混乱。

目前我已经实现了词法分析器、语法和 AST。我也在关注互联网上的一些例子。我当前的 AST 的工作方式如下:它具有抽象基类 Tree*,其他树从该类继承(例如,一个用于变量定义,一个用于语句列表,一个用于二进制表达式等)。

我正在尝试实现变量定义,因此对于输入

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

我希望 LLVM 输出为:

; ModuleID = "Test"

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

但是,现在我可以将 %x = alloca i32 部分添加到创建 main 函数的部分,但实际输出缺少 %x = alloca i32。所以,我得到的输出如下:

; ModuleID = "Test"

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

我的用于变量声明的 Codegen() 如下所示(符号表现在只是一个列表,我目前正努力使事情尽可能简单):

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());
} 

我生成@main 的部分如下: 注意:我已经注释掉了 print_int 函数(这是我稍后将用来打印东西的函数,但现在我不需要它)。如果我取消注释 print_int 函数,TheFunction 将不会通过验证器(TheFunction)-> 抱怨模块被破坏并且参数与签名不匹配。

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;
}

如果有人知道为什么我的 Alloca 对象没有生成,请帮助我 - 任何提示将不胜感激。

谢谢

编辑:

Codegen 从语法中调用:

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);
}

编辑:我想通了,基本上 createAlloca 必须在生成 main 时在 basicblock 之后调用;

4

1 回答 1

0

这里有两个奇怪的地方:

  1. 您所做的就是调用 Builder.CreateRet... 我看不出 main 中怎么会有任何代码,除非您调用创建相应指令的东西。特别是,您似乎从未调用过 CodeGen 部分。

  2. 您将零大小传递给 CreateAlloc。我认为大小应该是单个变量的大小。

此外,请确保在生成代码后不调用任何 LLVM 优化通道。这些通行证会优化价值(它从未使用过,因此是死代码)。

于 2012-11-13T00:04:47.343 回答