Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InstructionBuilder.SDiv creates UDiv instead of SDiv #224

Open
PennyMew opened this issue Sep 15, 2022 · 1 comment
Open

InstructionBuilder.SDiv creates UDiv instead of SDiv #224

PennyMew opened this issue Sep 15, 2022 · 1 comment
Labels

Comments

@PennyMew
Copy link

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 );

@smaillet smaillet added the bug label Oct 14, 2022
@smaillet
Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants