dotnet / LLVMSharp

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

Unable To Find Entry Point in DLL 'libLLVM' #205

Closed moff181 closed 1 year ago

moff181 commented 1 year ago

Hi.

I'm using LLVMSharp 5.0, and I've been able to replicate on LibLLVM 5.01, 6.01, and 7.01 (from nuget).

I'm seeing the following error: System.EntryPointNotFoundException: 'Unable to find an entry point named 'LLVMInitializeAllTargetInfos' in DLL 'libLLVM'.'

My code is:

            LLVM.InitializeAllTargetInfos();
            LLVM.InitializeAllTargets();
            LLVM.InitializeAllTargetMCs();
            LLVM.InitializeAllAsmParsers();
            LLVM.InitializeAllAsmPrinters();

            LLVM.GetTargetFromTriple("x86_64-pc-windows", out LLVMTargetRef target, out string error);

I'm trying to retrieve the target so that I can get the target data.

Going through the first block and commenting out, each of them caused the same error (with the entry point name changed).

I'm not seeing this for any other LLVM methods, including GetTargetFromTriple.

Updating beyond LibLLVM 7.01 causes the following error: System.DllNotFoundException: 'Unable to load DLL 'libLLVM': The specified module could not be found. (Exception from HRESULT: 0x8007007E)'

Thanks.

moff181 commented 1 year ago

Going down to LLVMSharp 3.8.0 and libLLVM 3.9.1 fixed the issue

geoff-m commented 1 year ago

According to dumpbin, the function names (like LLVMInitializeAllTargetInfos) are actually suffixed with an underscore (like LLVMInitializeAllTargetInfos_). However, attempting to import the function with underscore-suffixed name still failed similarly. I was able to get past those linkage errors by specifying the ordinal (also obtained from dumpbin) instead of the name, like below.

[DllImport("libLLVM", EntryPoint = "#530", CallingConvention = CallingConvention.Cdecl)]
public static extern void LLVMInitializeAllTargetInfos();

[DllImport("libLLVM", EntryPoint = "#532", CallingConvention = CallingConvention.Cdecl)]
public static extern void LLVMInitializeAllTargets();

[DllImport("libLLVM", EntryPoint = "#531", CallingConvention = CallingConvention.Cdecl)]
public static extern void LLVMInitializeAllTargetMCs();

[DllImport("libLLVM", EntryPoint = "#527", CallingConvention = CallingConvention.Cdecl)]
public static extern void LLVMInitializeAllAsmParsers();

[DllImport("libLLVM", EntryPoint = "#528", CallingConvention = CallingConvention.Cdecl)]
public static extern void LLVMInitializeAllAsmPrinters();

But calling these function still doesn't seem to work. After doing so, I get either an error that no LLVM targets are registered (if I "run" my tests), or an SEHException at LLVMInitializeAllTargets: "(0x80004005): External component has thrown an exception." (if I "debug" my tests).

geoff-m commented 1 year ago

Downgrading LLVMSharp gave me all sorts of problems, so I just uninstalled and made my own wrapper for the functions I needed.

tannergooding commented 1 year ago

LLVM requires you to exactly match versions or all kinds of bugs and other bad behaviors can occur. They likewise take breaking changes each and every release, which can lead to another class of issues.

It's likewise worth noting LLVMSharp 5.0 is a very old build and had many known bugs. LLVMSharp 8.0.0-beta and newer are recommended for use instead. The newer versions of the bindings are 1-to-1 and blittable and don't have the same sorts of issues or other regressions that you could otherwise run into. Because of this even though they are marked beta, they are effectively more stable than 5.0.0 and prior.

A new stable version is planned, but there needs to be some more validation on the latest bits before that can happen.