Skip to content

Commit 63a4d22

Browse files
authored
Merge pull request #1 from brenhinkeller/master
Use .bc extension for LLVM bitcode, some docs
2 parents 7f64774 + 1959603 commit 63a4d22

1 file changed

Lines changed: 91 additions & 18 deletions

File tree

src/StaticCompiler.jl

Lines changed: 91 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ export native_code_llvm, native_code_typed, native_llvm_module
1515
1616
!!! Warning: this will fail on programs that heap allocate any memory, or have dynamic dispatch !!!
1717
18-
Statically compile the method of a function `f` specialized to arguments of the type given by `types`.
18+
Statically compile the method of a function `f` specialized to arguments of the type given by `types`.
1919
20-
This will create a directory at the specified path with a shared object file (i.e. a `.so` or `.dylib`),
21-
and will save a `LazyStaticCompiledFunction` object in the same directory with the extension `.cjl`. This
22-
`LazyStaticCompiledFunction` can be deserialized with `load_function(path)`. Once it is instantiated in
23-
a julia session, it will be of type `StaticCompiledFunction` and may be called with arguments of type
20+
This will create a directory at the specified path with a shared object file (i.e. a `.so` or `.dylib`),
21+
and will save a `LazyStaticCompiledFunction` object in the same directory with the extension `.cjl`. This
22+
`LazyStaticCompiledFunction` can be deserialized with `load_function(path)`. Once it is instantiated in
23+
a julia session, it will be of type `StaticCompiledFunction` and may be called with arguments of type
2424
`types` as if it were a function with a single method (the method determined by `types`).
2525
26-
`compile` will return an already instantiated `StaticCompiledFunction` object and `obj_path` which is the
26+
`compile` will return an already instantiated `StaticCompiledFunction` object and `obj_path` which is the
2727
location of the directory containing the compilation artifacts.
2828
29-
Example:
29+
### Examples:
3030
3131
Define and compile a `fib` function:
3232
```julia
@@ -67,7 +67,7 @@ function compile(f, _tt, path::String = tempname(); name = GPUCompiler.safe_nam
6767
# Keep an eye on https://github.com/JuliaLang/julia/pull/43747 for this
6868

6969
f_wrap!(out::Ref, args::Ref{<:Tuple}) = (out[] = f(args[]...); nothing)
70-
70+
7171
generate_shlib(f_wrap!, Tuple{RefValue{rt}, RefValue{tt}}, path, name; kwargs...)
7272

7373
lf = LazyStaticCompiledFunction{rt, tt}(Symbol(f), path, name)
@@ -137,28 +137,65 @@ function native_job(@nospecialize(func), @nospecialize(types); kernel::Bool=fals
137137
GPUCompiler.CompilerJob(target, source, params), kwargs
138138
end
139139

140+
141+
"""
142+
```julia
143+
generate_shlib(f, tt, path::String, name::String; kwargs...)
144+
```
145+
Low level interface for compiling a shared object / dynamically loaded library
146+
(`.so` / `.dylib`) for function `f` given a tuple type `tt` characterizing
147+
the types of the arguments for which the function will be compiled.
148+
149+
See also `StaticCompiler.generate_shlib_fptr`.
150+
151+
### Examples
152+
```julia
153+
julia> function test(n)
154+
r = 0.0
155+
for i=1:n
156+
r += log(sqrt(i))
157+
end
158+
return r/n
159+
end
160+
test (generic function with 1 method)
161+
162+
julia> path, name = StaticCompiler.generate_shlib(test, Tuple{Int64}, "./test")
163+
("./test", "test")
164+
165+
shell> tree \$path
166+
./test
167+
|-- obj.bc
168+
`-- obj.dylib
169+
170+
0 directories, 2 files
171+
172+
julia> test(100_000)
173+
5.256496109495593
174+
175+
julia> ccall(StaticCompiler.generate_shlib_fptr(path, name), Float64, (Int64,), 100_000)
176+
5.256496109495593
177+
```
178+
"""
140179
function generate_shlib(f, tt, path::String = tempname(), name = GPUCompiler.safe_name(repr(f)); kwargs...)
141180
mkpath(path)
142-
obj_path = joinpath(path, "obj")
181+
obj_path = joinpath(path, "obj.bc")
143182
lib_path = joinpath(path, "obj.$(Libdl.dlext)")
144183
open(obj_path, "w") do io
145184
job, kwargs = native_job(f, tt; name, kwargs...)
146185
obj, _ = GPUCompiler.codegen(:obj, job; strip=true, only_entry=false, validate=false)
147-
186+
148187
write(io, obj)
149188
flush(io)
150-
try
151-
clang() do exe
152-
run(pipeline(`$exe -shared -o $lib_path $obj_path`, stderr=devnull)) #get rid of devnull when debugging
153-
end
154-
catch e;
155-
# if Clang_jll fails, check if gcc is available
156-
run(`cc -shared -o $lib_path $obj_path`)
157-
end
189+
190+
# Pick a Clang
191+
cc = Sys.isapple() ? `cc` : clang()
192+
# Compile!
193+
run(`$cc -shared -o $lib_path $obj_path`)
158194
end
159195
path, name
160196
end
161197

198+
162199
function generate_shlib_fptr(f, tt, path::String=tempname(), name = GPUCompiler.safe_name(repr(f)); temp::Bool=true, kwargs...)
163200
generate_shlib(f, tt, path, name; kwargs...)
164201
lib_path = joinpath(abspath(path), "obj.$(Libdl.dlext)")
@@ -171,6 +208,42 @@ function generate_shlib_fptr(f, tt, path::String=tempname(), name = GPUCompiler.
171208
fptr
172209
end
173210

211+
"""
212+
```julia
213+
generate_shlib_fptr(path::String, name)
214+
```
215+
Low level interface for obtaining a function pointer by `dlopen`ing a shared
216+
library given the `path` and `name` of a `.so`/`.dylib` already compiled by
217+
`generate_shlib`.
218+
219+
See also `StaticCompiler.enerate_shlib`.
220+
221+
### Examples
222+
```julia
223+
julia> function test(n)
224+
r = 0.0
225+
for i=1:n
226+
r += log(sqrt(i))
227+
end
228+
return r/n
229+
end
230+
test (generic function with 1 method)
231+
232+
julia> path, name = StaticCompiler.generate_shlib(test, Tuple{Int64}, "./test");
233+
234+
julia> test_ptr = StaticCompiler.generate_shlib_fptr(path, name)
235+
Ptr{Nothing} @0x000000015209f600
236+
237+
julia> ccall(test_ptr, Float64, (Int64,), 100_000)
238+
5.256496109495593
239+
240+
julia> @ccall \$test_ptr(100_000::Int64)::Float64 # Equivalently
241+
5.256496109495593
242+
243+
julia> test(100_000)
244+
5.256496109495593
245+
```
246+
"""
174247
function generate_shlib_fptr(path::String, name)
175248
lib_path = joinpath(abspath(path), "obj.$(Libdl.dlext)")
176249
ptr = Libdl.dlopen(lib_path, Libdl.RTLD_LOCAL)

0 commit comments

Comments
 (0)