Skip to content

Instantly share code, notes, and snippets.

@nanase
Created August 14, 2015 20:32
Show Gist options
  • Save nanase/cbfb230bb320a80db0fa to your computer and use it in GitHub Desktop.
Save nanase/cbfb230bb320a80db0fa to your computer and use it in GitHub Desktop.
LLVMSharpを使って、LLVMからC#のコードを動的に呼び出す処理をすこし整理したもの。
using System;
using System.Runtime.InteropServices;
using LLVMSharp;
namespace LLVMSharp_Test
{
class Program
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ActType();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void FuncType();
public static void Act()
{
Console.WriteLine("[C#] Hello world! : {0}", 42);
}
private static void InitializeJIT(out LLVMExecutionEngineRef engine, LLVMModuleRef module, out IntPtr error)
{
LLVM.LinkInMCJIT();
LLVM.InitializeX86Target();
LLVM.InitializeX86TargetInfo();
LLVM.InitializeX86TargetMC();
LLVM.InitializeX86AsmPrinter();
if (Environment.OSVersion.Platform == PlatformID.Win32NT) // On Windows, LLVM currently (3.6) does not support PE/COFF
LLVM.SetTarget(module, 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, module, out options, optionsSize, out error);
}
public static void Main(string[] args)
{
ActType act_ref = Act;
IntPtr act_pointer = Marshal.GetFunctionPointerForDelegate(act_ref);
LLVMExecutionEngineRef engine;
IntPtr error;
var context = LLVM.ContextCreate();
var module = LLVM.ModuleCreateWithNameInContext("LLVMTest", context);
var builder = LLVM.CreateBuilderInContext(context);
InitializeJIT(out engine, module, out error);
var False = new LLVMBool(0);
var int32Type = LLVM.Int32TypeInContext(context);
var voidType = LLVM.VoidTypeInContext(context);
var voidFuncType = LLVM.FunctionType(voidType, new LLVMTypeRef[0], False);
var pointerType = LLVM.PointerType(voidFuncType, 0);
LLVMTypeRef[] param_types = { voidType };
var ret_type = LLVM.FunctionType(voidType, out param_types[0], 0, False);
var entry_func = LLVM.AddFunction(module, "func", ret_type);
{
var entry = LLVM.AppendBasicBlock(entry_func, "entry");
LLVM.PositionBuilderAtEnd(builder, entry);
var ptr = LLVM.BuildAlloca(builder, pointerType, "");
LLVM.BuildStore(builder,
LLVM.ConstIntToPtr(LLVM.ConstInt(int32Type, (ulong)act_pointer.ToInt32(), False), pointerType),
ptr);
var act_func = LLVM.BuildLoad(builder, ptr, "");
LLVMValueRef[] act_func_vals = { LLVM.ConstInt(int32Type, 0, False) };
LLVM.BuildCall(builder, act_func, out act_func_vals[0], 0, "");
LLVM.BuildRetVoid(builder);
}
LLVM.VerifyModule(module, LLVMVerifierFailureAction.LLVMAbortProcessAction, out error);
LLVM.DumpModule(module);
var funcMethod = (FuncType)Marshal.GetDelegateForFunctionPointer(LLVM.GetPointerToGlobal(engine, entry_func), typeof(FuncType));
funcMethod();
LLVM.DisposeMessage(error);
LLVM.DisposeBuilder(builder);
LLVM.DisposeExecutionEngine(engine);
Console.ReadLine();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment