-
Notifications
You must be signed in to change notification settings - Fork 91
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
Problem with AddGlobalMapping usage #22
Comments
Calling into managed code is not as straight forward as you'd like. I've pasted a working example that calls into a static delegate sort of like you wanted. The interesting function is ReversePInvoke -- you'll have to keep changing this depending on your parameters. I've logged issue #23 to make it automatic in LLVMSharp -- I have all the code, it's in a private repo for another project, but it makes more sense to put it here since it'll be useful to more number of people. Anyway, here it is. namespace LLVMSharpIntroForReversePInvoke
{
using System;
using System.Runtime.InteropServices;
using LLVMSharp;
class Program
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int Add(int a, int b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void PrintSumDelegate(int a, int b, int sum);
[AllowReversePInvokeCalls]
public static void PrintSum(int a, int b, int sum)
{
Console.WriteLine("Sum for {0}+{1} is: {2}", a, b, sum);
}
private static LLVMValueRef ReversePInvoke(LLVMBuilderRef builder, LLVMTypeRef callTargetTypeRef, LLVMValueRef delegateAddressParameter, out LLVMValueRef args, uint numArgs)
{
var ptrType = LLVM.PointerType(callTargetTypeRef, 0);
var delegateAddress = LLVM.BuildAlloca(builder, LLVM.Int64Type(), "delegate.value");
var alloca = LLVM.BuildAlloca(builder, ptrType, "delegate.addr");
LLVM.BuildStore(builder, delegateAddressParameter, delegateAddress);
LLVM.BuildStore(builder, LLVM.BuildIntToPtr(builder, LLVM.BuildLoad(builder, delegateAddress, "delegate.addr.load"), ptrType, "delegate.funcptr"), alloca);
return LLVM.BuildCall(builder, LLVM.BuildLoad(builder, alloca, "delegate"), out args, numArgs, string.Empty);
}
static void Main(string[] args)
{
LLVMBool False = new LLVMBool(0);
LLVMBool True = new LLVMBool(1);
LLVMModuleRef mod = LLVM.ModuleCreateWithName("LLVMSharpIntro");
LLVMTypeRef[] param_types = { LLVM.Int32Type(), LLVM.Int32Type() };
LLVMTypeRef ret_type = LLVM.FunctionType(LLVM.Int32Type(), out param_types[0], 2, False);
LLVMValueRef sum = LLVM.AddFunction(mod, "sum", ret_type);
LLVMBasicBlockRef entry = LLVM.AppendBasicBlock(sum, "entry");
LLVMBuilderRef builder = LLVM.CreateBuilder();
LLVM.PositionBuilderAtEnd(builder, entry);
var sumValue = LLVM.BuildAdd(builder, LLVM.GetParam(sum, 0), LLVM.GetParam(sum, 1), "tmp");
LLVMTypeRef[] argTypesToPrintSum = new LLVMTypeRef[3];
argTypesToPrintSum[0] = LLVM.Int32Type();
argTypesToPrintSum[1] = LLVM.Int32Type();
argTypesToPrintSum[2] = LLVM.Int32Type();
LLVMValueRef[] argsToPrintSum = new LLVMValueRef[3];
argsToPrintSum[0] = LLVM.GetParam(sum, 0);
argsToPrintSum[1] = LLVM.GetParam(sum, 1);
argsToPrintSum[2] = sumValue;
var callTargetType = LLVM.FunctionType(LLVM.VoidType(), out argTypesToPrintSum[0], 3, False);
ReversePInvoke(builder, callTargetType, LLVM.ConstInt(LLVM.Int64Type(), (ulong)Marshal.GetFunctionPointerForDelegate(new PrintSumDelegate(PrintSum)).ToInt64(), True), out argsToPrintSum[0], 3);
LLVM.BuildRet(builder, sumValue);
LLVM.DumpModule(mod);
IntPtr error;
LLVM.VerifyModule(mod, LLVMVerifierFailureAction.LLVMAbortProcessAction, out error);
LLVM.DisposeMessage(error);
LLVMExecutionEngineRef engine;
LLVM.LinkInMCJIT();
LLVM.InitializeX86Target();
LLVM.InitializeX86TargetInfo();
LLVM.InitializeX86TargetMC();
LLVM.InitializeX86AsmPrinter();
var platform = Environment.OSVersion.Platform;
if (platform == PlatformID.Win32NT) // On Windows, LLVM currently (3.6) does not support PE/COFF
{
LLVM.SetTarget(mod, Marshal.PtrToStringAnsi(LLVM.GetDefaultTargetTriple()) + "-elf");
}
var options = new LLVMMCJITCompilerOptions();
var optionsSize = (4 * sizeof(int)) + IntPtr.Size; // LLVMMCJITCompilerOptions has 4 ints and a pointer
LLVM.InitializeMCJITCompilerOptions(out options, optionsSize);
LLVM.CreateMCJITCompilerForModule(out engine, mod, out options, optionsSize, out error);
var addMethod = (Add)Marshal.GetDelegateForFunctionPointer(LLVM.GetPointerToGlobal(engine, sum), typeof(Add));
int result = addMethod(10, 10);
Console.WriteLine("Result of sum is: " + result);
if (LLVM.WriteBitcodeToFile(mod, "sum.bc") != 0)
{
Console.WriteLine("error writing bitcode to file, skipping");
}
LLVM.DumpModule(mod);
LLVM.DisposeBuilder(builder);
LLVM.DisposeExecutionEngine(engine);
Console.ReadKey();
}
}
} |
@rflechner I think your issue is likely resolved at this point. I'm going to close this issue in a day. |
yes, everything works. thanks a lot for your help. |
Np. |
For those who try this today the signature has changed a bit ` static LLVMBool False = new LLVMBool(0);
` |
Hi,
I would like to call a C# function from LLVM bytecode.
To understand the mecanism, I created a "Display" function and I tried to use AddGlobalMapping.
But I have a problem with function resolution at runtime.
My program outputs:
My small program is:
Did I missed something ?
Thank you.
Romain.
The text was updated successfully, but these errors were encountered: