Why does an extra instruction appear during code generation of a condition (br) and a loop and how to get rid of it?
Here is an example of my source code, a fictional programming language…
alg hello1 (int a)
begin
int x = 0;
until (x < 10)
PRINT("qwerty");
end
x = x+2;
end
alg
begin
hello1(10);
end
Here is an example of code-generated code…
; ModuleID = 'main'
source_filename = "main"
@0 = private unnamed_addr constant [7 x i8] c"qwerty\00", align 1
@1 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
define internal void @hello1(i64 %a) {
entry:
%0 = alloca i64
store i64 %a, i64* %0
%1 = alloca i64
store i64 0, i64* %1
%2 = load i64, i64* %1
%cmptmp = icmp ult i64 %2, 10
%3 = icmp ne i1 %cmptmp, false
br i1 %3, label %forloop, label %forcont
%4 = load i64, i64* %1; <- These structures were not inserted correctly, how could they even appear?
%5 = load i64, i64* %1; <-----------
forloop: ; preds = %forloop, %entry
%printfCall = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @1, i32 0, i32 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @0, i32 0, i32 0))
%cmptmp1 = icmp ult i64 %4, 10
%6 = icmp ne i1 %cmptmp1, false
br i1 %6, label %forloop, label %forcont
; <----Here everything is correct, for example
forcont: ; preds = %forloop, %entry
%addtmp = add i64 %5, 2
store i64 %addtmp, i64* %1
}
declare i32 @printf(i8*, ...)
define void @main() {
entry:
call void @hello1(i64 10)
}
This is how I described the code generation procedure for a conditional construct and a regular block…
llvm::Value *NIfStatement::codeGen(CodeGenContext &context)
{
cout << "Generating if statement" << endl;
Value *condValue = this->condition.codeGen(context);
if (!condValue)
return nullptr;
condValue = CastToBoolean(context, condValue);
Function *theFunction = context.builder.GetInsertBlock()->getParent(); // the function where if statement is in
BasicBlock *thenBB = BasicBlock::Create(context.llvmContext, "then", theFunction);
BasicBlock *falseBB = BasicBlock::Create(context.llvmContext, "else");
BasicBlock *mergeBB = BasicBlock::Create(context.llvmContext, "ifcont");
if (this->falseBlock)
{
context.builder.CreateCondBr(condValue, thenBB, falseBB);
}
else
{
context.builder.CreateCondBr(condValue, thenBB, mergeBB);
}
context.builder.SetInsertPoint(thenBB);
context.pushBlock(thenBB);
this->trueBlock.codeGen(context);
context.popBlock();
thenBB = context.builder.GetInsertBlock();
if (thenBB->getTerminator() == nullptr)
{ //
context.builder.CreateBr(mergeBB);
}
if (this->falseBlock)
{
theFunction->getBasicBlockList().push_back(falseBB); //
context.builder.SetInsertPoint(falseBB); //
context.pushBlock(thenBB);
this->falseBlock->codeGen(context);
context.popBlock();
context.builder.CreateBr(mergeBB);
}
theFunction->getBasicBlockList().push_back(mergeBB); //
context.builder.SetInsertPoint(mergeBB); //
return nullptr;
}
llvm::Value *NBlock::codeGen(CodeGenContext &context)
{
cout << "Generating block" << endl;
Value *last = nullptr;
for (auto it = this->statements.begin(); it != this->statements.end(); it++)
{
last = (*it)->codeGen(context);
}
return last;
}
Please tell me how to fix this bug?