|
| 1 | +export OrcJIT, OrcModule, OrcTargetAddress |
| 2 | +export JITEventListener, GDBRegistrationListener, IntelJITEventListener, |
| 3 | + OProfileJITEventListener, PerfJITEventListener |
| 4 | +export dispose, errormsg, compile!, remove!, add!, |
| 5 | + mangle, address, addressin, create_stub!, set_stub!, |
| 6 | + register!, unregister!, callback! |
| 7 | +export JITTargetMachine |
| 8 | + |
| 9 | +@checked struct OrcJIT |
| 10 | + ref::API.LLVMOrcJITStackRef |
| 11 | +end |
| 12 | + |
| 13 | +Base.unsafe_convert(::Type{API.LLVMOrcJITStackRef}, orc::OrcJIT) = orc.ref |
| 14 | + |
| 15 | +""" |
| 16 | + OrcJIT(::TargetMachine) |
| 17 | +
|
| 18 | +Creates a OrcJIT stack based on the provided target machine. |
| 19 | +
|
| 20 | +!!! warning |
| 21 | + Takes ownership of the provided target machine. |
| 22 | +""" |
| 23 | +function OrcJIT(tm::TargetMachine) |
| 24 | + OrcJIT(API.LLVMOrcCreateInstance(tm)) |
| 25 | +end |
| 26 | + |
| 27 | +function dispose(orc::OrcJIT) |
| 28 | + API.LLVMOrcDisposeInstance(orc) |
| 29 | +end |
| 30 | + |
| 31 | +function errormsg(orc::OrcJIT) |
| 32 | + # The error message is owned by `orc`, and will |
| 33 | + # be disposed along-side the OrcJIT. |
| 34 | + unsafe_string(LLVM.API.LLVMOrcGetErrorMsg(orc)) |
| 35 | +end |
| 36 | + |
| 37 | +struct OrcModule |
| 38 | + handle::API.LLVMOrcModuleHandle |
| 39 | +end |
| 40 | +Base.convert(::Type{API.LLVMOrcModuleHandle}, mod::OrcModule) = mod.handle |
| 41 | + |
| 42 | +function compile!(orc::OrcJIT, mod::Module, resolver = C_NULL, ctx = C_NULL; lazy=false) |
| 43 | + r_mod = Ref{API.LLVMOrcModuleHandle}() |
| 44 | + if lazy |
| 45 | + API.LLVMOrcAddLazilyCompiledIR(orc, r_mod, mod, resolver, ctx) |
| 46 | + else |
| 47 | + API.LLVMOrcAddEagerlyCompiledIR(orc, r_mod, mod, resolver, ctx) |
| 48 | + end |
| 49 | + OrcModule(r_mod[]) |
| 50 | +end |
| 51 | + |
| 52 | +function Base.delete!(orc::OrcJIT, mod::OrcModule) |
| 53 | + LLVM.API.LLVMOrcRemoveModule(orc, mod) |
| 54 | +end |
| 55 | + |
| 56 | +function add!(orc::OrcJIT, obj::MemoryBuffer, resolver = C_NULL, ctx = C_NULL) |
| 57 | + r_mod = Ref{API.LLVMOrcModuleHandle}() |
| 58 | + API.LLVMOrcAddObjectFile(orc, r_mod, obj, resolver, ctx) |
| 59 | + return OrcModule(r_mod[]) |
| 60 | +end |
| 61 | + |
| 62 | +function mangle(orc::OrcJIT, name) |
| 63 | + r_symbol = Ref{Cstring}() |
| 64 | + LLVM.API.LLVMOrcGetMangledSymbol(orc, r_symbol, name) |
| 65 | + symbol = unsafe_string(r_symbol[]) |
| 66 | + LLVM.API.LLVMOrcDisposeMangledSymbol(r_symbol[]) |
| 67 | + return symbol |
| 68 | +end |
| 69 | + |
| 70 | +struct OrcTargetAddress |
| 71 | + ptr::API.LLVMOrcTargetAddress |
| 72 | +end |
| 73 | +Base.convert(::Type{API.LLVMOrcTargetAddress}, addr::OrcTargetAddress) = addr.ptr |
| 74 | + |
| 75 | +Base.pointer(addr::OrcTargetAddress) = reinterpret(Ptr{Cvoid}, addr.ptr % UInt) # LLVMOrcTargetAddress is UInt64 even on 32-bit |
| 76 | + |
| 77 | +OrcTargetAddress(ptr::Ptr{Cvoid}) = OrcTargetAddress(reinterpret(UInt, ptr)) |
| 78 | + |
| 79 | +function create_stub!(orc::OrcJIT, name, initial) |
| 80 | + LLVM.API.LLVMOrcCreateIndirectStub(orc, name, initial) |
| 81 | +end |
| 82 | + |
| 83 | +function set_stub!(orc::OrcJIT, name, new) |
| 84 | + LLVM.API.LLVMOrcSetIndirectStubPointer(orc, name, new) |
| 85 | +end |
| 86 | + |
| 87 | +function address(orc::OrcJIT, name) |
| 88 | + r_address = Ref{API.LLVMOrcTargetAddress}() |
| 89 | + API.LLVMOrcGetSymbolAddress(orc, r_address, name) |
| 90 | + OrcTargetAddress(r_address[]) |
| 91 | +end |
| 92 | + |
| 93 | +function addressin(orc::OrcJIT, mod::OrcModule, name) |
| 94 | + r_address = Ref{API.LLVMOrcTargetAddress}() |
| 95 | + API.LLVMOrcGetSymbolAddressIn(orc, r_address, mod, name) |
| 96 | + OrcTargetAddress(r_address[]) |
| 97 | +end |
| 98 | + |
| 99 | +function callback!(orc::OrcJIT, callback, ctx) |
| 100 | + r_address = Ref{API.LLVMOrcTargetAddress}() |
| 101 | + LLVM.API.LLVMOrcLazyCompileCallback(orc, r_address, callback, ctx) |
| 102 | + return OrcTargetAddress(r_address[]) |
| 103 | +end |
| 104 | + |
| 105 | +@checked struct JITEventListener |
| 106 | + ref::API.LLVMJITEventListenerRef |
| 107 | +end |
| 108 | +Base.unsafe_convert(::Type{API.LLVMJITEventListenerRef}, listener::JITEventListener) = listener.ref |
| 109 | + |
| 110 | +function register!(orc::OrcJIT, listener::JITEventListener) |
| 111 | + LLVM.API.LLVMOrcRegisterJITEventListener(orc, listener) |
| 112 | +end |
| 113 | + |
| 114 | +function unregister!(orc::OrcJIT, listener::JITEventListener) |
| 115 | + LLVM.API.LLVMOrcUnregisterJITEventListener(orc, listener) |
| 116 | +end |
| 117 | + |
| 118 | +GDBRegistrationListener() = JITEventListener(LLVM.API.LLVMCreateGDBRegistrationListener()) |
| 119 | +IntelJITEventListener() = JITEventListener(LLVM.API.LLVMCreateIntelJITEventListener()) |
| 120 | +OProfileJITEventListener() = JITEventListener(LLVM.API.LLVMCreateOProfileJITEventListener()) |
| 121 | +PerfJITEventListener() = JITEventListener(LLVM.API.LLVMCreatePerfJITEventListener()) |
| 122 | + |
| 123 | +function JITTargetMachine(;triple = LLVM.triple(), |
| 124 | + cpu = "", features = "", |
| 125 | + optlevel = LLVM.API.LLVMCodeGenLevelDefault) |
| 126 | + |
| 127 | + # Force ELF on windows, |
| 128 | + # Note: Without this call to normalize Orc get's confused |
| 129 | + # and chooses the x86_64 SysV ABI on Win x64 |
| 130 | + triple = LLVM.normalize(triple) |
| 131 | + if Sys.iswindows() |
| 132 | + triple *= "-elf" |
| 133 | + end |
| 134 | + target = LLVM.Target(triple=triple) |
| 135 | + @debug "Configuring OrcJIT with" triple cpu features optlevel |
| 136 | + |
| 137 | + tm = TargetMachine(target, triple, cpu, features, |
| 138 | + optlevel, |
| 139 | + LLVM.API.LLVMRelocStatic, # Generate simpler code for JIT |
| 140 | + LLVM.API.LLVMCodeModelJITDefault, # Required to init TM as JIT |
| 141 | + ) |
| 142 | + return tm |
| 143 | +end |
0 commit comments