在llvm中没有生成基本块终止符

时间:2013-04-08 09:32:15

标签: llvm llvm-ir

我对llvm很新,只在这里做了在线教程:http://llvm.org/docs/tutorial/LangImpl1.html 现在我想做自己的小语言并遇到一些问题。 我想解析一下:

(def i 1)

它应该做两件事:

  1. 定义一个返回1
  2. 的新函数
  3. 返回一个值,以便它可以用作表达式
  4. 该函数被正确创建,但我将它用作表达式时遇到问题。 AST看起来像这样:

    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 )会返回ret语句,但它不会插入到条目中。

1 个答案:

答案 0 :(得分:9)

有时候提出一个问题并稍稍休息有助于很好地解决问题。我更改了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 ) );
}