UbiquityDotNET/Llvm.NET

InstructionBuilder.SDiv creates UDiv instead of SDiv

Opened this issue · 1 comments

InstructionBuilder.SDiv creates UDiv instead of SDiv.

Here's some example code to demonstrate the issue.

public void SDivBug()
{
    Context context = new Context();
    BitcodeModule module = context.CreateBitcodeModule();
    
    // We're going to create the LLVM equivalent of this C function:
    //      int test(int x)
    //      {
    //          return x / -3;
    //      }

    IFunctionType function_type = context.GetFunctionType(context.Int32Type, new ITypeRef[]{context.Int32Type});
    IrFunction function = module.CreateFunction("test", function_type);
    BasicBlock block = function.AppendBasicBlock("entry");
    InstructionBuilder builder = new InstructionBuilder(block);
    Value lhs = function.Parameters[0];
    Value rhs = context.CreateConstant(-3);

    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    Value sdiv = builder.SDiv(lhs, rhs); // <== Creating SDiv
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    builder.Return(sdiv);

    if (!module.Verify(out string msg))
    {
        Console.WriteLine("module.Verify gave error: {0}", msg);
    }
    else
    {
        Console.WriteLine("module.Verify was okay");
    }

    Console.WriteLine(module.WriteToString());
}

Running this gives the following output:

module.Verify was okay

define i32 @test(i32 %0) {
entry:
  %1 = udiv i32 %0, -3
  ret i32 %1
}

Note that we have udiv instead of sdiv.

It looks like the following part of the InstructionBuilder code is selecting the wrong op builder:

/// <summary>Creates an integer unsigned division operator</summary>
/// <param name="lhs">left hand side operand</param>
/// <param name="rhs">right hand side operand</param>
/// <returns><see cref="Value"/> for the instruction</returns>
public Value UDiv( Value lhs, Value rhs ) => BuildBinOp( LLVMBuildUDiv, lhs, rhs );
/// <summary>Creates an integer signed division operator</summary>
/// <param name="lhs">left hand side operand</param>
/// <param name="rhs">right hand side operand</param>
/// <returns><see cref="Value"/> for the instruction</returns>
public Value SDiv( Value lhs, Value rhs ) => BuildBinOp( LLVMBuildUDiv, lhs, rhs );

I can confirm that is a bug, (and an easy enough fix) were you planning on submitting a PR to fix it?