我正在尝试编写一些编译器并使用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);
}
编辑:我想通了,基本上在生成main时必须在basicblock之后调用createAlloca;
答案 0 :(得分:0)
这里有两件奇怪的事情:
你所做的只是调用Builder.CreateRet ...除非你调用创建相应指令的东西,否则我看不到main中是否有任何代码。特别是,您似乎永远不会调用CodeGen部分。
您将大小为零传递给CreateAlloc。我认为单个变量的大小应该是一个。
此外,请确保在生成代码后不要调用任何LLVM优化过程。这些传递将优化价值(它从未使用过,因此死代码)。