Skip to content

Commit 3485deb

Browse files
authored
Merge pull request #208 from maleadt/vc/orc_resolver
[ORC] Implement a reasonable default resolver and throw errors on undefinded symbols
2 parents 2fdef9e + 5ffcaa9 commit 3485deb

File tree

4 files changed

+388
-119
lines changed

4 files changed

+388
-119
lines changed

COVERAGE.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ ORC JIT
11541154
Support
11551155
-------
11561156

1157-
- [ ] LLVMLoadLibraryPermanently
1158-
- [ ] LLVMParseCommandLineOptions
1159-
- [ ] LLVMSearchForAddressOfSymbol
1160-
- [ ] LLVMAddSymbol
1157+
- [x] LLVMLoadLibraryPermanently
1158+
- [x] LLVMParseCommandLineOptions
1159+
- [x] LLVMSearchForAddressOfSymbol
1160+
- [x] LLVMAddSymbol

src/orc.jl

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ export JITTargetMachine
1111
end
1212

1313
Base.unsafe_convert(::Type{API.LLVMOrcJITStackRef}, orc::OrcJIT) = orc.ref
14+
Base.unsafe_convert(::Type{Ptr{Cvoid}}, orc::OrcJIT) = Base.unsafe_convert(Ptr{Cvoid}, orc.ref)
15+
16+
OrcJIT(ref::Ptr{Cvoid}) = OrcJIT(Base.unsafe_convert(API.LLVMOrcJITStackRef, ref))
1417

1518
"""
1619
OrcJIT(::TargetMachine)
@@ -28,6 +31,15 @@ function dispose(orc::OrcJIT)
2831
API.LLVMOrcDisposeInstance(orc)
2932
end
3033

34+
function OrcJIT(f::Core.Function, tm::TargetMachine)
35+
orc = OrcJIT(tm)
36+
try
37+
f(orc)
38+
finally
39+
dispose(orc)
40+
end
41+
end
42+
3143
function errormsg(orc::OrcJIT)
3244
# The error message is owned by `orc`, and will
3345
# be disposed along-side the OrcJIT.
@@ -39,12 +51,52 @@ struct OrcModule
3951
end
4052
Base.convert(::Type{API.LLVMOrcModuleHandle}, mod::OrcModule) = mod.handle
4153

42-
function compile!(orc::OrcJIT, mod::Module, resolver = C_NULL, ctx = C_NULL; lazy=false)
54+
"""
55+
resolver(name, ctx)
56+
57+
Lookup the symbol `name`. Iff `ctx` is passed to this function it should be a
58+
pointer to the OrcJIT we are compiling for.
59+
"""
60+
function resolver(name, ctx)
61+
name = unsafe_string(name)
62+
## Step 0: Should have already resolved it iff it was in the
63+
## same module
64+
## Step 1: See if it's something known to the execution engine
65+
ptr = C_NULL
66+
if ctx != C_NULL
67+
orc = OrcJIT(ctx)
68+
ptr = pointer(address(orc, name))
69+
end
70+
71+
## Step 2: Search the program symbols
72+
if ptr == C_NULL
73+
#
74+
# SearchForAddressOfSymbol expects an unmangled 'C' symbol name.
75+
# Iff we are on Darwin, strip the leading '_' off.
76+
@static if Sys.isapple()
77+
if name[1] == '_'
78+
name = name[2:end]
79+
end
80+
end
81+
ptr = LLVM.find_symbol(name)
82+
end
83+
84+
## Step 4: Lookup in libatomic
85+
# TODO: Do we need to do this?
86+
87+
if ptr == C_NULL
88+
error("OrcJIT: Symbol `$name` lookup failed. Aborting!")
89+
end
90+
91+
return UInt64(reinterpret(UInt, ptr))
92+
end
93+
94+
function compile!(orc::OrcJIT, mod::Module, resolver = @cfunction(resolver, UInt64, (Cstring, Ptr{Cvoid})), resolver_ctx = orc; lazy=false)
4395
r_mod = Ref{API.LLVMOrcModuleHandle}()
4496
if lazy
45-
API.LLVMOrcAddLazilyCompiledIR(orc, r_mod, mod, resolver, ctx)
97+
API.LLVMOrcAddLazilyCompiledIR(orc, r_mod, mod, resolver, resolver_ctx)
4698
else
47-
API.LLVMOrcAddEagerlyCompiledIR(orc, r_mod, mod, resolver, ctx)
99+
API.LLVMOrcAddEagerlyCompiledIR(orc, r_mod, mod, resolver, resolver_ctx)
48100
end
49101
OrcModule(r_mod[])
50102
end
@@ -53,9 +105,9 @@ function Base.delete!(orc::OrcJIT, mod::OrcModule)
53105
LLVM.API.LLVMOrcRemoveModule(orc, mod)
54106
end
55107

56-
function add!(orc::OrcJIT, obj::MemoryBuffer, resolver = C_NULL, ctx = C_NULL)
108+
function add!(orc::OrcJIT, obj::MemoryBuffer, resolver = @cfunction(resolver, UInt64, (Cstring, Ptr{Cvoid})), resolver_ctx = orc)
57109
r_mod = Ref{API.LLVMOrcModuleHandle}()
58-
API.LLVMOrcAddObjectFile(orc, r_mod, obj, resolver, ctx)
110+
API.LLVMOrcAddObjectFile(orc, r_mod, obj, resolver, resolver_ctx)
59111
return OrcModule(r_mod[])
60112
end
61113

@@ -98,7 +150,7 @@ end
98150

99151
function callback!(orc::OrcJIT, callback, ctx)
100152
r_address = Ref{API.LLVMOrcTargetAddress}()
101-
LLVM.API.LLVMOrcLazyCompileCallback(orc, r_address, callback, ctx)
153+
API.LLVMOrcCreateLazyCompileCallback(orc, r_address, callback, ctx)
102154
return OrcTargetAddress(r_address[])
103155
end
104156

src/support.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,26 @@ function clopts(opts...)
44
args = ["", opts...]
55
API.LLVMParseCommandLineOptions(length(args), args, C_NULL)
66
end
7+
8+
"""
9+
add_symbol(name, ptr)
10+
11+
Permanently add the symbol `name` with the value `ptr`. These symbols are searched
12+
before any libraries.
13+
"""
14+
add_symbol(name, ptr) = LLVM.API.LLVMAddSymbol(name, ptr)
15+
16+
"""
17+
load_library_permantly(path)
18+
19+
This function permanently loads the dynamic library at the given path.
20+
It is safe to call this function multiple times for the same library.
21+
"""
22+
load_library_permantly(path) = LLVM.API.LLVMLoadLibraryPermanently(path)
23+
24+
"""
25+
find_symbol(name)
26+
27+
Search the global symbols for `name` and return the pointer to it.
28+
"""
29+
find_symbol(name) = LLVM.API.LLVMSearchForAddressOfSymbol(name)

0 commit comments

Comments
 (0)