生成 while 的 llvm ir 时出现分段错误

问题描述 投票:0回答:0

我想在我的玩具 C 编译器中支持编译。 我的想法是: 在支持 while 之前支持 do-while。然后使用 do-while AST 构造一个 while AST。这样我就可以简化while的codegen函数了

while (Cond) {
statements;
}
===>
if (!Cond)
   br afterwhile
do {
statements;
} while (Cond);
afterwhile:
...

这里是 do-while 和 while 的 AST 代码:

// DoWhile
class DoWhileExprAST : public ExprAST {
    std::unique_ptr<CodeBlocks> LoopBody;
    std::unique_ptr<ExprAST> Cond;
    friend class WhileExprAST;

public:
    DoWhileExprAST(std::unique_ptr<CodeBlocks> LoopBody, std::unique_ptr<ExprAST> Cond) :
                LoopBody(std::move(LoopBody)), Cond(std::move(Cond)) {}

    Value *codegen() override;
};

// While : Convert to DoWhile when Paring
class WhileExprAST : public ExprAST {
    std::unique_ptr<DoWhileExprAST> DoWhile;

public:
    WhileExprAST(std::unique_ptr<DoWhileExprAST> DoWhile) : DoWhile(std::move(DoWhile)) {}

    Value *codegen() override;
};

这里有两个codegen函数:

Value *DoWhileExprAST::codegen() {
    Function *TheFunction = Builder->GetInsertBlock()->getParent();

    // Create blocks for the loop and after.  Insert the 'loop' block at the
    // end of the function.
    BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "loop", TheFunction);
    BasicBlock *AfterBB = BasicBlock::Create(*TheContext, "afterloop");

    Builder->CreateBr(LoopBB);

    // Emit then value.
    Builder->SetInsertPoint(LoopBB);

    Value *LoopBodyV = LoopBody->codegen();
    if (!LoopBodyV)
        return nullptr;

    // emit the cond.
    Value *CondV = Cond->codegen();

    CondV = Builder->CreateICmpNE(CondV,
                                  ConstantInt::get(CondV->getType(), 0), "loopcond");

    Builder->CreateCondBr(CondV, LoopBB, AfterBB);

    TheFunction->insert(TheFunction->end(), AfterBB);
    Builder->SetInsertPoint(AfterBB);

    // loop expr always return 0
    return Constant::getNullValue(IntegerType::getInt64Ty(*TheContext));
}

Value *WhileExprAST::codegen() {
    Function *TheFunction = Builder->GetInsertBlock()->getParent();

    BasicBlock *FistTestBB = BasicBlock::Create(*TheContext, "test", TheFunction);
    BasicBlock *DoWhileLoop = BasicBlock::Create(*TheContext, "dowhile");
    BasicBlock *AfterWhile = BasicBlock::Create(*TheContext, "afterwhile");

    Builder->CreateBr(FistTestBB);

    Builder->SetInsertPoint(FistTestBB);

    Value *CondV = DoWhile->Cond->codegen();

    CondV = Builder->CreateICmpNE(CondV,
                                  ConstantInt::get(CondV->getType(), 0), "testcond");

    Builder->CreateCondBr(CondV, DoWhileLoop, AfterWhile);

    TheFunction->insert(TheFunction->end(), DoWhileLoop);
    Builder->SetInsertPoint(DoWhileLoop);

    DoWhile->codegen();

    TheFunction->insert(TheFunction->end(), AfterWhile);
    Builder->SetInsertPoint(AfterWhile);

    // loop expr always return 0
    return Constant::getNullValue(IntegerType::getInt64Ty(*TheContext));
}

当我编译这段代码时,我得到了一个 Segmentation fault (core dumped):

int testLoop (int n) {
    int add = 0;
    while (n != 0) {
        add = add + n;
        --n;
    }
    return add;
}

红外编码:

define i64 @testLoop(i64 %n) {
entry:
  %add = alloca i64, align 8
  %return = alloca i64, align 8
  %n1 = alloca i64, align 8
  store i64 %n, ptr %n1, align 4
  store i64 0, ptr %add, align 4
  br label %test

test:                                             ; preds = %entry
  %n2 = load i64, ptr %n1, align 4
  %netmp = icmp ne i64 %n2, 0
  %ext64 = sext i1 %netmp to i64
  %testcond = icmp ne i64 %ext64, 0
  br i1 %testcond, label %dowhile, label %afterwhile

dowhile:                                          ; preds = %test
  br label %loop

loop:                                             ; preds = %loop, %dowhile
  %add3 = load i64, ptr %add, align 4
  %n4 = load i64, ptr %n1, align 4
  %addtmp = add i64 %add3, %n4
  store i64 %addtmp, ptr %add, align 4
  %n5 = load i64, ptr %n1, align 4
  %selfsub = sub i64 %n5, 1
  store i64 %selfsub, ptr %n1, align 4
  %n6 = load i64, ptr %n1, align 4
  %netmp7 = icmp ne i64 %n6, 0
  %ext648 = sext i1 %netmp7 to i64
  %loopcond = icmp ne i64 %ext648, 0
  br i1 %loopcond, label %loop, label %afterloop

afterloop:                                        ; preds = %loop

afterwhile:                                       ; preds = %test
  %add9 = load i64, ptr %add, align 4
  store i64 %add9, ptr %return, align 4
  %0 = load i64, ptr %return, align 4
  ret i64 %0
}

Segmentation fault (core dumped)

我不知道是什么导致了这个错误。我很困惑,我只想知道问题出在哪里。

compiler-construction llvm
© www.soinside.com 2019 - 2024. All rights reserved.