0

コンパイラを作成し、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 を呼び出す必要があります。

4

1 に答える 1

0

ここには2つの奇妙なことがあります:

  1. Builder.CreateRet を呼び出すだけです... 対応する命令を作成する何かを呼び出さない限り、main にコードが存在する可能性はありません。特に、CodeGen 部分を呼び出すことはないようです。

  2. CreateAlloc にゼロのサイズを渡します。サイズは、単一の変数に対して 1 にする必要があると思います。

また、コードの生成後に LLVM 最適化パスを呼び出さないようにしてください。これらのパスは値を最適化します (決して使用されないため、デッド コードです)。

于 2012-11-13T00:04:47.343 に答える