2013-04-08 4 views
6

ich bin ziemlich neu zu llvm und habe nur das Online-Tutorial hier: http://llvm.org/docs/tutorial/LangImpl1.html Jetzt wollte ich meine eigene kleine Sprache tun und bekam ein kleines Problem. Ich möchte dies analysieren:nein Basic Block Terminator generiert in llvm

(def i 1) 

Es sollte zwei Dinge tun:

  1. Definieren Sie eine neue Funktion, die 1
  2. Rückgabe Gibt einen Wert, so dass es als Ausdruck verwendet werden kann

Die Funktion wird korrekt erstellt, aber ich habe ein Problem mit der Verwendung als Ausdruck. die AST sieht wie folgt aus:

FunctionAST // the whole statement 
    - Prototype // is an nameless statement 
    - Body // contains the definition expression 
    - DefExprAST 
     - Body // contains the Function definition 
     - FunctionAST 
      - Prototype // named i 
      - Body // the value 1 

Der Code für die Code-Erzeugung für die Funktion wie folgt aussieht:

Function *FunctionAST::Codegen() { 
    NamedValues.clear(); 

    Function *TheFunction = Proto->Codegen(); 
    if (TheFunction == 0) return 0; 

    BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); 
    Builder.SetInsertPoint(BB); 

    if (Value *RetVal = Body->Codegen()) { 
    Builder.CreateRet(RetVal); 

    verifyFunction(*TheFunction); 

    return TheFunction; 
    } 
    return 0; 
} 

Und die DefExprAST wie folgt aus:

Value *DefExprAST::Codegen() { 
    if (Body->Codegen() == 0) return 0; 

    return ConstantFP::get(getGlobalContext(), APFloat(0.0)); 
} 

Die verifyFunction gibt die Folgefehler:

Basic Block in function '' does not have terminator! 
label %entry 
LLVM ERROR: Broken module, no Basic Block terminator! 

Und tatsächlich hat die generierte Funktion keinen ret-Eintrag. Seine leer:

define double @0() { 
entry: 
} 

Aber RetVal korrekt mit einem Doppel-und Builder.CreateRet(RetVal) gibt wieder die ret-Anweisung gefüllt ist, aber es nicht in den Eintrag bekommt eingefügt.

Antwort

8

Manchmal hilft die Formulierung einer Frage und eine kleine Pause, Probleme sehr gut zu lösen. Ich habe die DefExprAST::Codegen geändert, um den übergeordneten Block zu speichern und ihn als Einfügepunkt für den Rückgabewert festzulegen.

Value *DefExprAST::Codegen() { 
    BasicBlock *Parent = Builder.GetInsertBlock(); 
    if (Body->Codegen() == 0) return 0; 

    Builder.SetInsertPoint(Parent); 

    return ConstantFP::get(getGlobalContext(), APFloat(0.0)); 
}