dotnet / LLVMSharp

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

Crash on GetElementType #221

Open 0x410c opened 7 months ago

0x410c commented 7 months ago
LLVMContextRef context = LLVMContextRef.Create();
string ir = File.ReadAllText("helper_module.ir");
nint mem = Marshal.StringToHGlobalAnsi(ir);
var memBuf = LLVM.CreateMemoryBufferWithMemoryRangeCopy((sbyte*)mem, (nuint)ir.Length, (sbyte*)Marshal.StringToHGlobalAnsi("helper_module"));
context.TryParseIR(memBuf,out _helperModule,out string msg);
 _helperModule.TryVerify(LLVMVerifierFailureAction.LLVMPrintMessageAction, out string message);
 var opcodeNewarr = LLVM.GetNamedFunction(_helperModule, (sbyte*)Marshal.StringToHGlobalAnsi("a"));
 var to1 = LLVM.TypeOf(opcodeNewarr);
var to1e = LLVM.GetElementType(to1);

ir:

; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable
define i32 @a(){
  ret i32 1
}

i am trying to get return type of the function, but getting on var to1e = LLVM.GetElementType(to1);

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

i am using version 16 of llvmsharp

davidelettieri commented 3 months ago

Not an expert but I investigated a bit your issue and I think it may be related with opaque pointers (https://releases.llvm.org/16.0.0/docs/OpaquePointers.html). Even if it's not, the migration instructions contains some suggestions that can be applied to your case.

The type your are getting in the line

var to1 = LLVM.TypeOf(opcodeNewarr);

is a PointerType, you can check this using LLVM.GetTypeKind() function. From the linked docs we know that GetElementType is not supported anymore

In order to support opaque pointers, two types of changes tend to be necessary. The first is the removal of all calls to PointerType::getElementType() and Type::getPointerElementType().

Since the function defined in the ir is a global function and there is a getValueType() function for globals we can try to use that one. I think getValueType() on llvm can be translated to LLVM.GlobalGetValueType() in LLVMSharp

LLVMContextRef context = LLVMContextRef.Create();
LLVMModuleRef _helperModule;
string ir = File.ReadAllText("helper_module.ir");
nint mem = Marshal.StringToHGlobalAnsi(ir);
var memBuf = LLVM.CreateMemoryBufferWithMemoryRangeCopy((sbyte*)mem, (nuint)ir.Length, (sbyte*)Marshal.StringToHGlobalAnsi("helper_module"));
context.TryParseIR(memBuf, out _helperModule, out string msg);
_helperModule.TryVerify(LLVMVerifierFailureAction.LLVMPrintMessageAction, out string message);
var func = LLVM.GetNamedFunction(_helperModule, (sbyte*)Marshal.StringToHGlobalAnsi("a"));
var funcType = LLVM.GlobalGetValueType(func);
var returnType = LLVM.GetReturnType(funcType);

var funcTypeKind = LLVM.GetTypeKind(funcType);
var returnTypeKind = LLVM.GetTypeKind(returnType);

This code is not failing anymore.

0x410c commented 3 months ago

wont be able to confirm, dropped llvm usage in the project :sweat_smile:

davidelettieri commented 3 months ago

It's fine, it was an exercise for me to check the issue. Hopefully someone else might find it useful.

Should the issue be closed?