コンパイラを作成し、LLVM を使用して中間コードを生成しようとしています。残念ながら、LLVM のドキュメントはあまり良くなく、多少混乱することさえあります。
現時点では、lexer、grammar、および AST を実装しています。また、インターネットで見つかったいくつかの例に従っていました。私の現在の AST は次のように動作します: 抽象基本クラス Tree* があり、そこから他のツリーが継承されます (つまり、変数定義用、ステートメント リスト用、バイナリ式用など)。
私は変数定義を実装しようとしているので、入力のために
class Test{
int main()
{
int x;
}
}
LLVM出力を次のようにしたい:
; ModuleID = "Test"
define i32 @main() {
entry:
%x = alloca i32
return i32 0
}
ただ、今のところmain関数を作成した部分に%x=alloca i32の部分を取得できるのですが、実際の出力では%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 は verifier(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);
}
編集:私はそれを理解しました。基本的には、メインを生成するときに、basicblock の後に createAlloca を呼び出す必要があります。