Adding if-else statement

Hi. Below is my code for adding an if-else statement. I’m checking if the argument is zero then print ‘The value is zero.’ However, I get segmentation fault. Can someone assist me in figuring out the issue? Thank you
F is function.
Argument *arg = &*F.arg_begin();

    Value *argValue = arg;



    // Create the if statement to check if the argument is zero

    BasicBlock *entryBB = &F.getEntryBlock();

    IRBuilder<> builder(entryBB, entryBB->getFirstInsertionPt());

    Value *zeroValue = ConstantInt::get(argValue->getType(), 0);

    Value *condition = builder.CreateICmpEQ(argValue, zeroValue, "isZero");



    // Split the block to create two new basic blocks for "if" and "else"

    BasicBlock *ifBB = BasicBlock::Create(F.getContext(), "if", &F);

    BasicBlock *elseBB = BasicBlock::Create(F.getContext(), "else", &F);



    // Set insertion point to the "if" block

    builder.SetInsertPoint(ifBB);



    builder.CreateCall(F.getParent()->getFunction("printf"),

                       {buildesr.CreateGlobalStringPtr("The value is zero.\n")});



    // Create the unconditional branch from "if" block to "else" block

    builder.CreateBr(elseBB);



    // Set insertion point to the "else" block

    builder.SetInsertPoint(elseBB);

I’m not seeing a conditional branch that consumes the ICmpEq and connects the entry block to the “if” and “else” blocks. I don’t know if that’s your immediate problem, but it is a problem.

Correct. The condition value must be consumed by a branch to the if or else block:
https://mapping-high-level-constructs-to-llvm-ir.readthedocs.io/en/latest/control-structures/if-then-else.html

I tried the following way but still got seg fault.
Argument *arg = &*F.arg_begin();
Value *argValue = arg;

    // Create the if statement to check if the argument is zero
    BasicBlock *entryBB = &F.getEntryBlock();
    IRBuilder<> builder(entryBB->getTerminator());

    Value *zeroValue = ConstantInt::get(argValue->getType(), 0);
    Value *condition = builder.CreateICmpEQ(argValue, zeroValue, "isZero");
    BasicBlock *ifBB = BasicBlock::Create(F.getContext(), "if.block", &F);
    BasicBlock *endBB = BasicBlock::Create(F.getContext(), "end.block");

    builder.CreateCondBr(condition, ifBB, endBB);

    // Set the insertion point to the if block
    builder.SetInsertPoint(ifBB);
    builder.CreateCall(F.getParent()->getFunction("printf"),
                       {builder.CreateGlobalStringPtr("The value is zero.\n")});
    builder.CreateBr(endBB);
    builder.SetInsertPoint(endBB);

You must have an llvm::Module. Can you invoke dump() on the module instance before the crash?

Here it’s
define dso_local void @foo(i32 noundef %0, i32 noundef %1) #0 {

%3 = alloca i32, align 4

%4 = alloca i32, align 4

%5 = alloca i32, align 4

store i32 %0, i32* %3, align 4

store i32 %1, i32* %4, align 4

store i32 5, i32* %5, align 4

%6 = icmp eq i32 %0, 0

ret void

7: ; No predecessors!

}

Last option is to run your program under gdb/lldb, let it crash, and invoke bt to see the backtrace.

1 Like

Your if/else blocks don’t show up here.

And the conditional branch. You didn’t show how the “ret void” was created.

I’m using this code.
Argument *arg = &*F.arg_begin();

   	     Value *argValue = arg;

          Value *zeroValue = ConstantInt::get(argValue->getType(), 0);

          Value *condition = builder.CreateICmpEQ(argValue, zeroValue, "isZero");



          // Create the if block

          BasicBlock *ifBB = BasicBlock::Create(F.getContext(), "if.block", &F);

          BasicBlock *endBB = BasicBlock::Create(F.getContext(), "end.block",&F);

         

          

          builder.CreateCondBr(condition, ifBB, endBB);

          builder.SetInsertPoint(ifBB);

          builder.CreateRet(ConstantInt::get(argValue->getType(), 0));

          

	      builder.SetInsertPoint(endBB);

	      builder.CreateRet(ConstantInt::get(argValue->getType(), 0));

And this is dump()
define dso_local i32 @main(i32 noundef %0, i8** noundef %1) #0 {

%3 = alloca i32, align 4

%4 = alloca i32, align 4

%5 = alloca i8**, align 8

store i32 0, i32* %3, align 4

store i32 %0, i32* %4, align 4

store i8** %1, i8*** %5, align 8

%6 = load i32, i32* %4, align 4

%7 = icmp eq i32 %0, 0

br i1 %7, label %9, label %10

call void @foo(i32 noundef %6, i32 noundef 6)

%8 = load i32, i32* %4, align 4

ret i32 %8

9: ; preds = %2

ret i32 0

10: ; preds = %2

ret i32 0

}

Now, the if/else blocks show up, but I’m getting seg fault again. (I’m adding if/else blocks before the call to function foo)

Please provide more details. Seg fault from the compiler? Or from the program you are trying to create? If it’s from the compiler, do you have a traceback? If you built the compiler with debug info, you should get a symbolic traceback and that will be very helpful in finding the problem.

Agree, more details would be useful here. @Syed_Kabir - if possible, you could even try to provide a MCVE in the spirit of Lukas Eder ( How to Create a Good MCVE (Minimal Complete Verifiable Example) – Java, SQL and jOOQ.). Those instructions are obviously for jOOQ rather than for LLVM, but the same general principle applies here.

For example: Do you have a GitHub repo/feature branch where the problem can be easily reproduced? If not, can you make one? (i.e. extract these relevant parts to a single .cc file and put it up in a public GitHub repo) That would probably help in better understanding the problem you’re facing, and who knows, maybe it’ll even help others (or even your future self) at some point.