Created
August 14, 2015 20:32
-
-
Save nanase/cbfb230bb320a80db0fa to your computer and use it in GitHub Desktop.
LLVMSharpを使って、LLVMからC#のコードを動的に呼び出す処理をすこし整理したもの。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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