dotnet / LLVMSharp

LLVM bindings for .NET Standard written in C# using ClangSharp
MIT License
846 stars 97 forks source link

CreateConstPtrToInt causes "Use of instruction is not an instruction!" #166

Closed andyjansson closed 3 years ago

andyjansson commented 3 years ago

Hi,

I recently converted to LLVMSharp from UbiquitiDotNET/Llvm.NET as the latter has become stagnant and LLVMSharp has seemingly picked up steam again. The conversion went well and everything worked fine, save for one issue. I've distilled the issue to the snippet below. The lines which are commented out are kept for context, but aren't necessary to trigger the error:

var funcType = LLVMTypeRef.CreateFunction(
    LLVMTypeRef.Int32,
    Enumerable.Empty<LLVMTypeRef>().ToArray());

var function = module.AddFunction("main", funcType);

var block = function.AppendBasicBlock("entry");
builder.PositionAtEnd(block);

// create value
var value = LLVMValueRef.CreateConstInt(LLVMTypeRef.Int32, 5);

// create a pointer to the value
var valuePtr = builder.BuildAlloca(LLVMTypeRef.Int32);
builder.BuildStore(value, valuePtr);

// cast the pointer to an int
var valuePtrAsInt = LLVMValueRef.CreateConstPtrToInt(valuePtr, LLVMTypeRef.Int64); // <-- offending line

// convert the int back to a pointer
// var intToValuePtr = LLVMValueRef.CreateConstIntToPtr(valuePtrAsInt, valuePtr.TypeOf);

// load the value
// var loadedValue = builder.BuildLoad(intToValuePtr);
var loadedValue = builder.BuildLoad(valuePtr);

builder.BuildRet(loadedValue);
function.VerifyFunction(LLVMVerifierFailureAction.LLVMPrintMessageAction);

Prints the following error:

Use of instruction is not an instruction!
  %0 = alloca i32

CreateConstPtrToInt(...) causes the compilation to fail. It works fine without it. The equivalent code in Llvm.NET also worked fine.

Any advice as to what I am doing wrong here?

tannergooding commented 3 years ago

Could you indicate which version of LLVMSharp this was tested with?

If this was with the new v12.0.0-beta, could you also try against v11.0.0 and see if it reproduces please?

andyjansson commented 3 years ago

I should've included that in my original post, apologies. I've tested with 10.0.0-beta, 11.0.0-beta and 12.0.0-beta1. All exhibit the same behavior. UbiquitiDotNET/Llvm.NET, which I converted from, is LLVM 10.

tannergooding commented 3 years ago

I'll give this a look in a bit and see if I can repro.

andyjansson commented 3 years ago

Great, thanks. To provide some additional context, the reason for the CreateConstPtrToInt(...) is because I'm implementing variant types. These consist of a tag and a pointer. I convert the pointer to an integer to make the element type invisible to LLVM since different tags can point to different types of data. In the future I hope to use opaque pointers for this instead.

andyjansson commented 3 years ago

Any update on this?

tannergooding commented 3 years ago

It looks like this strictly requires the LHS to be Constant: https://llvm.org/doxygen/classllvm_1_1Constant.html and https://llvm.org/doxygen/IR_2Core_8cpp_source.html#l01755.

While LLVMBuildAlloca returns an Instruction: https://llvm.org/doxygen/classllvm_1_1AllocaInst.html and https://llvm.org/doxygen/IR_2Core_8cpp_source.html#l03527

CreatePtrToInt on the other hand accepts any value and should work here.

andyjansson commented 3 years ago

Hi,

I found LLVMBuilderRef.BuildPtrToInt and that fixed my issue. Thanks for your help!