2013-04-08 6 views
6

Sono abbastanza nuovo a llvm e ho fatto solo il tutorial online qui: http://llvm.org/docs/tutorial/LangImpl1.html Ora volevo fare il mio piccolo linguaggio e ho avuto un piccolo problema. Voglio analizzare questo:no Terminatore di blocco di base generato in llvm

(def i 1) 

Si dovrebbe fare due cose:

  1. definire una nuova funzione che restituisce 1
  2. restituire un valore in modo che possa essere utilizzato come espressione

La funzione viene creata correttamente, ma ho un problema con l'utilizzo come espressione. l'AST si presenta così:

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 

Il Codice per la creazione di codice per la funzione è simile al seguente:

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

E la DefExprAST in questo modo:

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

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

Il verifyFunction dà la errore seguente:

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

E infatti, la funzione generata non ha una voce ret. Il suo vuoto:

define double @0() { 
entry: 
} 

Ma RetVal sia correttamente riempito con un doppio e Builder.CreateRet(RetVal) dà di nuovo la dichiarazione ret ma non viene inserita nella voce.

risposta

8

A volte formulare una domanda e prendersi una pausa aiuta a risolvere molto bene i problemi. Ho modificato lo DefExprAST::Codegen per ricordare il blocco Parent e impostarlo come punto di inserimento per il valore restituito.

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

    Builder.SetInsertPoint(Parent); 

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