Skip to content

Commit 8c46be1

Browse files
committed
Refactor code to make it more amenable to cross compilation
Also cleanup some of it
1 parent 34ef8bb commit 8c46be1

File tree

3 files changed

+111
-82
lines changed

3 files changed

+111
-82
lines changed

src/StaticCompiler.jl

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ using LLD_jll: lld
1212
using StaticTools
1313
using StaticTools: @symbolcall, @c_str, println
1414
using Core: MethodTable
15+
using Base:BinaryPlatforms.Platform, BinaryPlatforms.HostPlatform, BinaryPlatforms.arch, BinaryPlatforms.os, BinaryPlatforms.libc_str
1516

1617
export load_function, compile_shlib, compile_executable
17-
export native_code_llvm, native_code_typed, native_llvm_module, native_code_native
18+
export static_code_llvm, static_code_typed, static_llvm_module, static_code_native
1819
export @device_override, @print_and_throw
1920

2021
include("interpreter.jl")
@@ -32,6 +33,7 @@ compile_executable(f::Function, types::Tuple, path::String, [name::String=string
3233
filename::String=name,
3334
cflags=``, # Specify libraries you would like to link against, and other compiler options here
3435
also_expose=[],
36+
target::StaticTarget=StaticTarget(),
3537
method_table=StaticCompiler.method_table,
3638
kwargs...
3739
)
@@ -96,16 +98,16 @@ Hello, world!
9698
```
9799
"""
98100
function compile_executable(f::Function, types=(), path::String="./", name=fix_name(f);
99-
also_expose=Tuple{Function, Tuple{DataType}}[],
101+
also_expose=Tuple{Function, Tuple{DataType}}[], target::StaticTarget=StaticTarget(),
100102
kwargs...)
101-
102-
compile_executable(vcat([(f, types)], also_expose), path, name; kwargs...)
103+
compile_executable(vcat([(f, types)], also_expose), path, name; target, kwargs...)
103104
end
104105

105106
function compile_executable(funcs::Union{Array,Tuple}, path::String="./", name=fix_name(first(first(funcs)));
106107
filename = name,
107108
demangle = true,
108109
cflags = ``,
110+
target::StaticTarget=StaticTarget(),
109111
kwargs...
110112
)
111113

@@ -114,12 +116,12 @@ function compile_executable(funcs::Union{Array,Tuple}, path::String="./", name=f
114116
isexecutableargtype = tt == Tuple{} || tt == Tuple{Int, Ptr{Ptr{UInt8}}}
115117
isexecutableargtype || @warn "input type signature $types should be either `()` or `(Int, Ptr{Ptr{UInt8}})` for standard executables"
116118

117-
rt = last(only(native_code_typed(f, tt; kwargs...)))
119+
rt = last(only(static_code_typed(f, tt; target, kwargs...)))
118120
isconcretetype(rt) || error("`$f$types` did not infer to a concrete type. Got `$rt`")
119121
nativetype = isprimitivetype(rt) || isa(rt, Ptr)
120122
nativetype || @warn "Return type `$rt` of `$f$types` does not appear to be a native type. Consider returning only a single value of a native machine type (i.e., a single float, int/uint, bool, or pointer). \n\nIgnoring this warning may result in Undefined Behavior!"
121123

122-
generate_executable(funcs, path, name, filename; demangle, cflags, kwargs...)
124+
generate_executable(funcs, path, name, filename; demangle, cflags, target, kwargs...)
123125
joinpath(abspath(path), filename)
124126
end
125127

@@ -129,13 +131,15 @@ compile_shlib(f::Function, types::Tuple, [path::String="./"], [name::String=stri
129131
filename::String=name,
130132
cflags=``,
131133
method_table=StaticCompiler.method_table,
134+
target::StaticTarget=StaticTarget(),
132135
kwargs...)
133136
134137
compile_shlib(funcs::Array, [path::String="./"];
135138
filename="libfoo",
136139
demangle=true,
137140
cflags=``,
138141
method_table=StaticCompiler.method_table,
142+
target::StaticTarget=StaticTarget(),
139143
kwargs...)
140144
```
141145
As `compile_executable`, but compiling to a standalone `.dylib`/`.so` shared library.
@@ -169,33 +173,35 @@ julia> ccall(("test", "test.dylib"), Float64, (Int64,), 100_000)
169173
"""
170174
function compile_shlib(f::Function, types=(), path::String="./", name=fix_name(f);
171175
filename=name,
176+
target::StaticTarget=StaticTarget(),
172177
kwargs...
173178
)
174-
compile_shlib(((f, types),), path; filename, kwargs...)
179+
compile_shlib(((f, types),), path; filename, target, kwargs...)
175180
end
176181
# As above, but taking an array of functions and returning a single shlib
177182
function compile_shlib(funcs::Union{Array,Tuple}, path::String="./";
178183
filename = "libfoo",
179184
demangle = true,
180185
cflags = ``,
186+
target::StaticTarget=StaticTarget(),
181187
kwargs...
182188
)
183189
for func in funcs
184190
f, types = func
185191
tt = Base.to_tuple_type(types)
186192
isconcretetype(tt) || error("input type signature `$types` is not concrete")
187193

188-
rt = last(only(native_code_typed(f, tt)))
194+
rt = last(only(static_code_typed(f, tt; target, kwargs...)))
189195
isconcretetype(rt) || error("`$f$types` did not infer to a concrete type. Got `$rt`")
190196
nativetype = isprimitivetype(rt) || isa(rt, Ptr)
191197
nativetype || @warn "Return type `$rt` of `$f$types` does not appear to be a native type. Consider returning only a single value of a native machine type (i.e., a single float, int/uint, bool, or pointer). \n\nIgnoring this warning may result in Undefined Behavior!"
192198
end
193199

194-
generate_shlib(funcs, true, path, filename; demangle, cflags, kwargs...)
200+
generate_shlib(funcs, path, filename; demangle, cflags, target, kwargs...)
195201

196202
joinpath(abspath(path), filename * "." * Libdl.dlext)
197203
end
198-
204+
199205

200206
"""
201207
```julia
@@ -281,12 +287,11 @@ generate_executable(f, tt, args...; kwargs...) = generate_executable(((f, tt),),
281287
function generate_executable(funcs::Union{Array,Tuple}, path=tempname(), name=fix_name(first(first(funcs))), filename=name;
282288
demangle = true,
283289
cflags = ``,
290+
target::StaticTarget=StaticTarget(),
284291
kwargs...
285292
)
286-
lib_path = joinpath(path, "$filename.$(Libdl.dlext)")
287293
exec_path = joinpath(path, filename)
288-
external = true
289-
_, obj_path = generate_obj(funcs, external, path, filename; demangle, kwargs...)
294+
_, obj_path = generate_obj(funcs, path, filename; demangle, target, kwargs...)
290295
# Pick a compiler
291296
cc = Sys.isapple() ? `cc` : clang()
292297
# Compile!
@@ -318,8 +323,8 @@ end
318323

319324
"""
320325
```julia
321-
generate_shlib(f::Function, tt, [external::Bool=true], [path::String], [name], [filename]; kwargs...)
322-
generate_shlib(funcs::Array, [external::Bool=true], [path::String], [filename::String]; demangle=true, kwargs...)
326+
generate_shlib(f::Function, tt, [path::String], [name], [filename]; kwargs...)
327+
generate_shlib(funcs::Array, [path::String], [filename::String]; demangle=true, target::StaticTarget=StaticTarget(), kwargs...)
323328
```
324329
Low level interface for compiling a shared object / dynamically loaded library
325330
(`.so` / `.dylib`) for function `f` given a tuple type `tt` characterizing
@@ -356,19 +361,20 @@ julia> ccall(("test", "example/test.dylib"), Float64, (Int64,), 100_000)
356361
5.2564961094956075
357362
```
358363
"""
359-
function generate_shlib(f::Function, tt, external::Bool=true, path::String=tempname(), name=fix_name(f), filename=name; kwargs...)
360-
generate_shlib(((f, tt),), external, path, filename; kwargs...)
364+
function generate_shlib(f::Function, tt, path::String=tempname(), name=fix_name(f), filename=name; target=StaticTarget(), kwargs...)
365+
generate_shlib(((f, tt),), path, filename; target, kwargs...)
361366
end
362367
# As above, but taking an array of functions and returning a single shlib
363-
function generate_shlib(funcs::Union{Array,Tuple}, external::Bool=true, path::String=tempname(), filename::String="libfoo";
368+
function generate_shlib(funcs::Union{Array,Tuple}, path::String=tempname(), filename::String="libfoo";
364369
demangle = true,
365370
cflags = ``,
371+
target::StaticTarget=StaticTarget(),
366372
kwargs...
367373
)
368374

369375
lib_path = joinpath(path, "$filename.$(Libdl.dlext)")
370376

371-
_, obj_path = generate_obj(funcs, external, path, filename; demangle, kwargs...)
377+
_, obj_path = generate_obj(funcs, path, filename; target, demangle, kwargs...)
372378
# Pick a Clang
373379
cc = Sys.isapple() ? `cc` : clang()
374380
# Compile!
@@ -377,27 +383,27 @@ function generate_shlib(funcs::Union{Array,Tuple}, external::Bool=true, path::St
377383
path, name
378384
end
379385

380-
function native_code_llvm(@nospecialize(func), @nospecialize(types); kwargs...)
381-
job, kwargs = native_job(func, types, true; kwargs...)
386+
function static_code_llvm(@nospecialize(func), @nospecialize(types); target::StaticTarget=StaticTarget(), kwargs...)
387+
job, kwargs = static_job(func, types; target, kwargs...)
382388
GPUCompiler.code_llvm(stdout, job; kwargs...)
383389
end
384390

385-
function native_code_typed(@nospecialize(func), @nospecialize(types); kwargs...)
386-
job, kwargs = native_job(func, types, true; kwargs...)
391+
function static_code_typed(@nospecialize(func), @nospecialize(types); target::StaticTarget=StaticTarget(), kwargs...)
392+
job, kwargs = static_job(func, types; target, kwargs...)
387393
GPUCompiler.code_typed(job; kwargs...)
388394
end
389395

390-
function native_code_native(@nospecialize(f), @nospecialize(tt), fname=fix_name(f); kwargs...)
391-
job, kwargs = native_job(f, tt, true; fname, kwargs...)
396+
function static_code_native(@nospecialize(f), @nospecialize(tt), fname=fix_name(f); target::StaticTarget=StaticTarget(), kwargs...)
397+
job, kwargs = static_job(f, tt; fname, target, kwargs...)
392398
GPUCompiler.code_native(stdout, job; kwargs...)
393399
end
394400

395401
# Return an LLVM module
396-
function native_llvm_module(f, tt, name=fix_name(f); demangle, kwargs...)
402+
function static_llvm_module(f, tt, name=fix_name(f); demangle, target::StaticTarget=StaticTarget(), kwargs...)
397403
if !demangle
398404
name = "julia_"*name
399405
end
400-
job, kwargs = native_job(f, tt, true; name, kwargs...)
406+
job, kwargs = static_job(f, tt; name, target, kwargs...)
401407
m = GPUCompiler.JuliaContext() do context
402408
m, _ = GPUCompiler.codegen(:llvm, job; strip=true, only_entry=false, validate=false)
403409
locate_pointers_and_runtime_calls(m)
@@ -407,14 +413,14 @@ function native_llvm_module(f, tt, name=fix_name(f); demangle, kwargs...)
407413
end
408414

409415
#Return an LLVM module for multiple functions
410-
function native_llvm_module(funcs::Union{Array,Tuple}; demangle=true, kwargs...)
416+
function static_llvm_module(funcs::Union{Array,Tuple}; demangle=true, target::StaticTarget=StaticTarget(), kwargs...)
411417
f,tt = funcs[1]
412418
mod = GPUCompiler.JuliaContext() do context
413419
name_f = fix_name(f)
414420
if !demangle
415421
name_f = "julia_"*name_f
416422
end
417-
job, kwargs = native_job(f, tt, true; name = name_f, kwargs...)
423+
job, kwargs = static_job(f, tt; name = name_f, target, kwargs...)
418424
mod,_ = GPUCompiler.codegen(:llvm, job; strip=true, only_entry=false, validate=false)
419425
if length(funcs) > 1
420426
for func in funcs[2:end]
@@ -423,7 +429,7 @@ function native_llvm_module(funcs::Union{Array,Tuple}; demangle=true, kwargs...)
423429
if !demangle
424430
name_f = "julia_"*name_f
425431
end
426-
job, kwargs = native_job(f, tt, true; name = name_f, kwargs...)
432+
job, kwargs = static_job(f, tt; name = name_f, target, kwargs...)
427433
tmod,_ = GPUCompiler.codegen(:llvm, job; strip=true, only_entry=false, validate=false)
428434
link!(mod,tmod)
429435
end
@@ -458,7 +464,7 @@ end
458464

459465
"""
460466
```julia
461-
generate_obj(f, tt, external::Bool, path::String = tempname(), filenamebase::String="obj";
467+
generate_obj(f, tt, path::String = tempname(), filenamebase::String="obj";
462468
target = (),
463469
demangle = true,
464470
strip_llvm = false,
@@ -498,7 +504,7 @@ end
498504

499505
"""
500506
```julia
501-
generate_obj(funcs::Union{Array,Tuple}, external::Bool, path::String = tempname(), filenamebase::String="obj";
507+
generate_obj(funcs::Union{Array,Tuple}, path::String = tempname(), filenamebase::String="obj";
502508
target = (),
503509
demangle =false,
504510
strip_llvm = false,
@@ -514,18 +520,19 @@ which will be compiled.
514520
This is a named tuple with fields `triple`, `cpu`, and `features` (each of these are strings).
515521
The defaults compile to the native target.
516522
"""
517-
function generate_obj(funcs::Union{Array,Tuple}, external::Bool, path::String = tempname(), filenamebase::String="obj";
523+
function generate_obj(funcs::Union{Array,Tuple}, path::String = tempname(), filenamebase::String="obj";
518524
demangle = true,
519525
strip_llvm = false,
520526
strip_asm = true,
521527
opt_level = 3,
528+
target::StaticTarget=StaticTarget(),
522529
kwargs...)
523530
f, tt = funcs[1]
524531
mkpath(path)
525532
obj_path = joinpath(path, "$filenamebase.o")
526-
mod = native_llvm_module(funcs; demangle, kwargs...)
533+
mod = static_llvm_module(funcs; demangle, kwargs...)
527534
obj = GPUCompiler.JuliaContext() do ctx
528-
fakejob, _ = native_job(f, tt, external; kwargs...)
535+
fakejob, _ = static_job(f, tt; target, kwargs...)
529536
obj, _ = GPUCompiler.emit_asm(fakejob, mod; strip=strip_asm, validate=false, format=LLVM.API.LLVMObjectFile)
530537
obj
531538
end

0 commit comments

Comments
 (0)