@@ -12,10 +12,12 @@ using LLD_jll: lld
12
12
using StaticTools
13
13
using StaticTools: @symbolcall , @c_str , println
14
14
using Core: MethodTable
15
-
15
+ using Base: BinaryPlatforms. Platform, BinaryPlatforms. HostPlatform, BinaryPlatforms. arch, BinaryPlatforms. os_str, BinaryPlatforms. libc_str
16
+ using Base: BinaryPlatforms. platform_dlext
16
17
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
18
19
export @device_override , @print_and_throw
20
+ export StaticTarget
19
21
20
22
include (" interpreter.jl" )
21
23
include (" target.jl" )
@@ -32,6 +34,7 @@ compile_executable(f::Function, types::Tuple, path::String, [name::String=string
32
34
filename::String=name,
33
35
cflags=``, # Specify libraries you would like to link against, and other compiler options here
34
36
also_expose=[],
37
+ target::StaticTarget=StaticTarget(),
35
38
method_table=StaticCompiler.method_table,
36
39
kwargs...
37
40
)
@@ -96,16 +99,16 @@ Hello, world!
96
99
```
97
100
"""
98
101
function compile_executable (f:: Function , types= (), path:: String = " ./" , name= fix_name (f);
99
- also_expose= Tuple{Function, Tuple{DataType}}[],
102
+ also_expose= Tuple{Function, Tuple{DataType}}[], target :: StaticTarget = StaticTarget (),
100
103
kwargs... )
101
-
102
- compile_executable (vcat ([(f, types)], also_expose), path, name; kwargs... )
104
+ compile_executable (vcat ([(f, types)], also_expose), path, name; target, kwargs... )
103
105
end
104
106
105
107
function compile_executable (funcs:: Union{Array,Tuple} , path:: String = " ./" , name= fix_name (first (first (funcs)));
106
108
filename = name,
107
109
demangle = true ,
108
110
cflags = ` ` ,
111
+ target:: StaticTarget = StaticTarget (),
109
112
kwargs...
110
113
)
111
114
@@ -114,12 +117,12 @@ function compile_executable(funcs::Union{Array,Tuple}, path::String="./", name=f
114
117
isexecutableargtype = tt == Tuple{} || tt == Tuple{Int, Ptr{Ptr{UInt8}}}
115
118
isexecutableargtype || @warn " input type signature $types should be either `()` or `(Int, Ptr{Ptr{UInt8}})` for standard executables"
116
119
117
- rt = last (only (native_code_typed (f, tt; kwargs... )))
120
+ rt = last (only (static_code_typed (f, tt; target, kwargs... )))
118
121
isconcretetype (rt) || error (" `$f$types ` did not infer to a concrete type. Got `$rt `" )
119
122
nativetype = isprimitivetype (rt) || isa (rt, Ptr)
120
123
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\n Ignoring this warning may result in Undefined Behavior!"
121
124
122
- generate_executable (funcs, path, name, filename; demangle, cflags, kwargs... )
125
+ generate_executable (funcs, path, name, filename; demangle, cflags, target, kwargs... )
123
126
joinpath (abspath (path), filename)
124
127
end
125
128
@@ -129,13 +132,15 @@ compile_shlib(f::Function, types::Tuple, [path::String="./"], [name::String=stri
129
132
filename::String=name,
130
133
cflags=``,
131
134
method_table=StaticCompiler.method_table,
135
+ target::StaticTarget=StaticTarget(),
132
136
kwargs...)
133
137
134
138
compile_shlib(funcs::Array, [path::String="./"];
135
139
filename="libfoo",
136
140
demangle=true,
137
141
cflags=``,
138
142
method_table=StaticCompiler.method_table,
143
+ target::StaticTarget=StaticTarget(),
139
144
kwargs...)
140
145
```
141
146
As `compile_executable`, but compiling to a standalone `.dylib`/`.so` shared library.
@@ -169,33 +174,35 @@ julia> ccall(("test", "test.dylib"), Float64, (Int64,), 100_000)
169
174
"""
170
175
function compile_shlib (f:: Function , types= (), path:: String = " ./" , name= fix_name (f);
171
176
filename= name,
177
+ target:: StaticTarget = StaticTarget (),
172
178
kwargs...
173
179
)
174
- compile_shlib (((f, types),), path; filename, kwargs... )
180
+ compile_shlib (((f, types),), path; filename, target, kwargs... )
175
181
end
176
182
# As above, but taking an array of functions and returning a single shlib
177
183
function compile_shlib (funcs:: Union{Array,Tuple} , path:: String = " ./" ;
178
184
filename = " libfoo" ,
179
185
demangle = true ,
180
186
cflags = ` ` ,
187
+ target:: StaticTarget = StaticTarget (),
181
188
kwargs...
182
189
)
183
190
for func in funcs
184
191
f, types = func
185
192
tt = Base. to_tuple_type (types)
186
193
isconcretetype (tt) || error (" input type signature `$types ` is not concrete" )
187
194
188
- rt = last (only (native_code_typed (f, tt)))
195
+ rt = last (only (static_code_typed (f, tt; target, kwargs ... )))
189
196
isconcretetype (rt) || error (" `$f$types ` did not infer to a concrete type. Got `$rt `" )
190
197
nativetype = isprimitivetype (rt) || isa (rt, Ptr)
191
198
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\n Ignoring this warning may result in Undefined Behavior!"
192
199
end
193
200
194
- generate_shlib (funcs, true , path, filename; demangle, cflags, kwargs... )
201
+ generate_shlib (funcs, path, filename; demangle, cflags, target , kwargs... )
195
202
196
203
joinpath (abspath (path), filename * " ." * Libdl. dlext)
197
204
end
198
-
205
+
199
206
200
207
"""
201
208
```julia
@@ -281,14 +288,18 @@ generate_executable(f, tt, args...; kwargs...) = generate_executable(((f, tt),),
281
288
function generate_executable (funcs:: Union{Array,Tuple} , path= tempname (), name= fix_name (first (first (funcs))), filename= name;
282
289
demangle = true ,
283
290
cflags = ` ` ,
291
+ target:: StaticTarget = StaticTarget (),
284
292
kwargs...
285
293
)
286
- lib_path = joinpath (path, " $filename .$(Libdl. dlext) " )
287
294
exec_path = joinpath (path, filename)
288
- external = true
289
- _, obj_path = generate_obj (funcs, external, path, filename; demangle, kwargs... )
295
+ _, obj_path = generate_obj (funcs, path, filename; demangle, target, kwargs... )
290
296
# Pick a compiler
291
- cc = Sys. isapple () ? ` cc` : clang ()
297
+ if ! isnothing (target. compiler)
298
+ cc = ` $(target. compiler) `
299
+ else
300
+ cc = Sys. isapple () ? ` cc` : clang ()
301
+ end
302
+
292
303
# Compile!
293
304
if Sys. isapple ()
294
305
# Apple no longer uses _start, so we can just specify a custom entry
318
329
319
330
"""
320
331
```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...)
332
+ generate_shlib(f::Function, tt, [path::String], [name], [filename]; kwargs...)
333
+ generate_shlib(funcs::Array, [path::String], [filename::String]; demangle=true, target::StaticTarget=StaticTarget() , kwargs...)
323
334
```
324
335
Low level interface for compiling a shared object / dynamically loaded library
325
336
(`.so` / `.dylib`) for function `f` given a tuple type `tt` characterizing
@@ -356,75 +367,83 @@ julia> ccall(("test", "example/test.dylib"), Float64, (Int64,), 100_000)
356
367
5.2564961094956075
357
368
```
358
369
"""
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... )
370
+ function generate_shlib (f:: Function , tt, path:: String = tempname (), name= fix_name (f), filename= name; target = StaticTarget (), kwargs... )
371
+ generate_shlib (((f, tt),), path, filename; target, kwargs... )
361
372
end
362
373
# 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" ;
374
+ function generate_shlib (funcs:: Union{Array,Tuple} , path:: String = tempname (), filename:: String = " libfoo" ;
364
375
demangle = true ,
365
376
cflags = ` ` ,
377
+ target:: StaticTarget = StaticTarget (),
366
378
kwargs...
367
379
)
380
+ if ! isnothing (target. platform)
381
+ lib_path = joinpath (path, " $filename .$(platform_dlext (target. platform)) " )
382
+ else
383
+ lib_path = joinpath (path, " $filename .$(Libdl. dlext) " )
384
+ end
368
385
369
- lib_path = joinpath (path, " $filename .$(Libdl. dlext) " )
370
-
371
- _, obj_path = generate_obj (funcs, external, path, filename; demangle, kwargs... )
386
+ _, obj_path = generate_obj (funcs, path, filename; target, demangle, kwargs... )
372
387
# Pick a Clang
373
- cc = Sys. isapple () ? ` cc` : clang ()
388
+ if ! isnothing (target. compiler)
389
+ cc = ` $(target. compiler) `
390
+ else
391
+ cc = Sys. isapple () ? ` cc` : clang ()
392
+ end
374
393
# Compile!
375
394
run (` $cc -shared $cflags $obj_path -o $lib_path ` )
376
395
377
396
path, name
378
397
end
379
398
380
- function native_code_llvm (@nospecialize (func), @nospecialize (types); kwargs... )
381
- job, kwargs = native_job (func, types, true ; kwargs... )
382
- GPUCompiler. code_llvm (stdout , job; kwargs... )
399
+ function static_code_llvm (@nospecialize (func), @nospecialize (types); target :: StaticTarget = StaticTarget (), kwargs... )
400
+ job, kwargs = static_job (func, types; target, kwargs... )
401
+ GPUCompiler. code_llvm (stdout , job; libraries = false , kwargs... )
383
402
end
384
403
385
- function native_code_typed (@nospecialize (func), @nospecialize (types); kwargs... )
386
- job, kwargs = native_job (func, types, true ; kwargs... )
404
+ function static_code_typed (@nospecialize (func), @nospecialize (types); target :: StaticTarget = StaticTarget (), kwargs... )
405
+ job, kwargs = static_job (func, types; target, kwargs... )
387
406
GPUCompiler. code_typed (job; kwargs... )
388
407
end
389
408
390
- function native_code_native (@nospecialize (f), @nospecialize (tt), fname= fix_name (f); kwargs... )
391
- job, kwargs = native_job (f, tt, true ; fname, kwargs... )
392
- GPUCompiler. code_native (stdout , job; kwargs... )
409
+ function static_code_native (@nospecialize (f), @nospecialize (tt), fname= fix_name (f); target :: StaticTarget = StaticTarget (), kwargs... )
410
+ job, kwargs = static_job (f, tt; fname, target , kwargs... )
411
+ GPUCompiler. code_native (stdout , job; libraries = false , kwargs... )
393
412
end
394
413
395
414
# Return an LLVM module
396
- function native_llvm_module (f, tt, name= fix_name (f); demangle, kwargs... )
415
+ function static_llvm_module (f, tt, name= fix_name (f); demangle= true , target :: StaticTarget = StaticTarget () , kwargs... )
397
416
if ! demangle
398
417
name = " julia_" * name
399
418
end
400
- job, kwargs = native_job (f, tt, true ; name, kwargs... )
419
+ job, kwargs = static_job (f, tt; name, target , kwargs... )
401
420
m = GPUCompiler. JuliaContext () do context
402
- m, _ = GPUCompiler. codegen (:llvm , job; strip= true , only_entry= false , validate= false )
421
+ m, _ = GPUCompiler. codegen (:llvm , job; strip= true , only_entry= false , validate= false , libraries = false )
403
422
locate_pointers_and_runtime_calls (m)
404
423
m
405
424
end
406
425
return m
407
426
end
408
427
409
428
# Return an LLVM module for multiple functions
410
- function native_llvm_module (funcs:: Union{Array,Tuple} ; demangle= true , kwargs... )
429
+ function static_llvm_module (funcs:: Union{Array,Tuple} ; demangle= true , target :: StaticTarget = StaticTarget () , kwargs... )
411
430
f,tt = funcs[1 ]
412
431
mod = GPUCompiler. JuliaContext () do context
413
432
name_f = fix_name (f)
414
433
if ! demangle
415
434
name_f = " julia_" * name_f
416
435
end
417
- job, kwargs = native_job (f, tt, true ; name = name_f, kwargs... )
418
- mod,_ = GPUCompiler. codegen (:llvm , job; strip= true , only_entry= false , validate= false )
436
+ job, kwargs = static_job (f, tt; name = name_f, target , kwargs... )
437
+ mod,_ = GPUCompiler. codegen (:llvm , job; strip= true , only_entry= false , validate= false , libraries = false )
419
438
if length (funcs) > 1
420
439
for func in funcs[2 : end ]
421
440
f,tt = func
422
441
name_f = fix_name (f)
423
442
if ! demangle
424
443
name_f = " julia_" * name_f
425
444
end
426
- job, kwargs = native_job (f, tt, true ; name = name_f, kwargs... )
427
- tmod,_ = GPUCompiler. codegen (:llvm , job; strip= true , only_entry= false , validate= false )
445
+ job, kwargs = static_job (f, tt; name = name_f, target , kwargs... )
446
+ tmod,_ = GPUCompiler. codegen (:llvm , job; strip= true , only_entry= false , validate= false , libraries = false )
428
447
link! (mod,tmod)
429
448
end
430
449
end
458
477
459
478
"""
460
479
```julia
461
- generate_obj(f, tt, external::Bool, path::String = tempname(), filenamebase::String="obj";
462
- target = (),
480
+ generate_obj(f, tt, path::String = tempname(), filenamebase::String="obj";
481
+ target::StaticTarget=StaticTarget (),
463
482
demangle = true,
464
483
strip_llvm = false,
465
484
strip_asm = true,
@@ -471,7 +490,7 @@ a tuple type `tt` characterizing the types of the arguments for which the
471
490
function will be compiled.
472
491
473
492
`target` can be used to change the output target. This is useful for compiling to WebAssembly and embedded targets.
474
- This is a named tuple with fields `triple`, `cpu`, and `features` (each of these are strings).
493
+ This is a struct of the type StaticTarget()
475
494
The defaults compile to the native target.
476
495
477
496
If `demangle` is set to `false`, compiled function names are prepended with "julia_".
@@ -481,7 +500,7 @@ If `demangle` is set to `false`, compiled function names are prepended with "jul
481
500
julia> fib(n) = n <= 1 ? n : fib(n - 1) + fib(n - 2)
482
501
fib (generic function with 1 method)
483
502
484
- julia> path, name, table = StaticCompiler.generate_obj_for_compile (fib, Tuple{Int64}, "./test")
503
+ julia> path, name, table = StaticCompiler.generate_obj (fib, Tuple{Int64}, "./test")
485
504
("./test", "fib", IdDict{Any, String}())
486
505
487
506
shell> tree \$ path
498
517
499
518
"""
500
519
```julia
501
- generate_obj(funcs::Union{Array,Tuple}, external::Bool, path::String = tempname(), filenamebase::String="obj";
502
- target = (),
520
+ generate_obj(funcs::Union{Array,Tuple}, path::String = tempname(), filenamebase::String="obj";
521
+ target::StaticTarget=StaticTarget (),
503
522
demangle =false,
504
523
strip_llvm = false,
505
524
strip_asm = true,
@@ -511,21 +530,22 @@ Low level interface for compiling object code (`.o`) for an array of Tuples
511
530
which will be compiled.
512
531
513
532
`target` can be used to change the output target. This is useful for compiling to WebAssembly and embedded targets.
514
- This is a named tuple with fields `triple`, `cpu`, and `features` (each of these are strings).
533
+ This is a struct of the type StaticTarget()
515
534
The defaults compile to the native target.
516
535
"""
517
- function generate_obj (funcs:: Union{Array,Tuple} , external :: Bool , path:: String = tempname (), filenamebase:: String = " obj" ;
536
+ function generate_obj (funcs:: Union{Array,Tuple} , path:: String = tempname (), filenamebase:: String = " obj" ;
518
537
demangle = true ,
519
538
strip_llvm = false ,
520
539
strip_asm = true ,
521
540
opt_level = 3 ,
541
+ target:: StaticTarget = StaticTarget (),
522
542
kwargs... )
523
543
f, tt = funcs[1 ]
524
544
mkpath (path)
525
545
obj_path = joinpath (path, " $filenamebase .o" )
526
- mod = native_llvm_module (funcs; demangle, kwargs... )
546
+ mod = static_llvm_module (funcs; demangle, kwargs... )
527
547
obj = GPUCompiler. JuliaContext () do ctx
528
- fakejob, _ = native_job (f, tt, external; kwargs... )
548
+ fakejob, _ = static_job (f, tt; target, kwargs... )
529
549
obj, _ = GPUCompiler. emit_asm (fakejob, mod; strip= strip_asm, validate= false , format= LLVM. API. LLVMObjectFile)
530
550
obj
531
551
end
0 commit comments