2013-04-08 2 views
6

Я довольно новичок в llvm и только сделал онлайн-учебник здесь: http://llvm.org/docs/tutorial/LangImpl1.html Теперь я хотел сделать свой собственный маленький язык и получил небольшую проблему. Я хочу, чтобы разобрать это:no Базовый блок-терминатор, сгенерированный в llvm

(def i 1) 

Он должен сделать две вещи:

  1. Определить новую функцию, которая возвращает 1
  2. возвращает значение, так что он может быть использован в качестве выражения

Функция создается правильно, но у меня есть проблема с ее использованием в качестве выражения. АСТ выглядит следующим образом:

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 

Кодекс для Творения кода для функции выглядит следующим образом:

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

И в DefExprAST, как это:

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

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

verifyFunction дает следующая погрешность:

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

И действительно, сгенерированная функция не имеет записи ret. Его пустой:

define double @0() { 
entry: 
} 

Но RetVal правильно заполнены с двойной и Builder.CreateRet(RetVal) возвращает заявление в отставке, но не вставляются в сени.

ответ

8

Иногда формулировка вопроса и проведение небольшого перерыва помогает очень хорошо решать проблемы. Я изменил DefExprAST::Codegen, чтобы запомнить родительский блок и установить его как точку вставки для возвращаемого значения.

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

    Builder.SetInsertPoint(Parent); 

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