Created
August 14, 2015 20:17
-
-
Save nanase/42e480a17f7fdd6dcb23 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); | |
var False = new LLVMBool(0); | |
var True = new LLVMBool(1); | |
var context = LLVM.ContextCreate(); | |
LLVMExecutionEngineRef engine; | |
IntPtr error; | |
var module = LLVM.ModuleCreateWithNameInContext("LLVMTest", context); | |
var builder = LLVM.CreateBuilderInContext(context); | |
InitializeJIT(out engine, module, out error); | |
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 v1 = LLVM.BuildAlloca(builder, int32Type, "1"); | |
LLVM.SetAlignment(v1, 4); | |
var func = LLVM.BuildAlloca(builder, pointerType, "func"); | |
LLVM.SetAlignment(func, 8); | |
LLVM.BuildStore(builder, LLVM.ConstInt(int32Type, 0, False), v1); | |
var store = LLVM.BuildStore(builder, | |
LLVM.ConstIntToPtr(LLVM.ConstInt(int32Type, (ulong)act_pointer.ToInt32(), False), pointerType), | |
func); | |
LLVM.SetAlignment(store, 8); | |
var v2 = LLVM.BuildLoad(builder, func, "2"); | |
LLVM.SetAlignment(v2, 8); | |
LLVMValueRef[] act_func_vals = { LLVM.ConstInt(int32Type, 42, False) }; | |
LLVM.BuildCall(builder, v2, out act_func_vals[0], 0, ""); | |
LLVM.BuildRetVoid(builder); | |
} | |
// { | |
// var passManager = LLVM.CreatePassManager (); | |
// var pmbuilder = LLVM.PassManagerBuilderCreate (); | |
// LLVM.PassManagerBuilderSetOptLevel (pmbuilder, 0); | |
// LLVM.PassManagerBuilderSetSizeLevel (pmbuilder, 0); | |
// LLVM.PassManagerBuilderSetDisableUnitAtATime (pmbuilder, False); | |
// LLVM.PassManagerBuilderSetDisableUnrollLoops (pmbuilder, False); | |
// LLVM.PassManagerBuilderPopulateModulePassManager (pmbuilder, passManager); | |
// LLVM.RunPassManager (passManager, module); | |
// LLVM.PassManagerBuilderDispose (pmbuilder); | |
// } | |
// | |
LLVM.VerifyModule(module, LLVMVerifierFailureAction.LLVMAbortProcessAction, out error); | |
LLVM.DisposeMessage(error); | |
LLVM.DumpModule(module); | |
var funcMethod = (FuncType)Marshal.GetDelegateForFunctionPointer(LLVM.GetPointerToGlobal(engine, entry_func), typeof(FuncType)); | |
{ | |
funcMethod(); | |
} | |
if (LLVM.WriteBitcodeToFile(module, "func.bc") != 0) | |
Console.WriteLine("error writing bitcode to file, skipping"); | |
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