@@ -12,10 +12,12 @@ using LLD_jll: lld
1212using StaticTools
1313using StaticTools: @symbolcall , @c_str , println
1414using Core: MethodTable
15-
15+ using Base: BinaryPlatforms. Platform, BinaryPlatforms. HostPlatform, BinaryPlatforms. arch, BinaryPlatforms. os_str, BinaryPlatforms. libc_str
16+ using Base: BinaryPlatforms. platform_dlext
1617export 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
1819export @device_override , @print_and_throw
20+ export StaticTarget
1921
2022include (" interpreter.jl" )
2123include (" target.jl" )
@@ -32,6 +34,7 @@ compile_executable(f::Function, types::Tuple, path::String, [name::String=string
3234 filename::String=name,
3335 cflags=``, # Specify libraries you would like to link against, and other compiler options here
3436 also_expose=[],
37+ target::StaticTarget=StaticTarget(),
3538 method_table=StaticCompiler.method_table,
3639 kwargs...
3740)
@@ -96,16 +99,16 @@ Hello, world!
9699```
97100"""
98101function 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 (),
100103 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... )
103105end
104106
105107function compile_executable (funcs:: Union{Array,Tuple} , path:: String = " ./" , name= fix_name (first (first (funcs)));
106108 filename = name,
107109 demangle = true ,
108110 cflags = ` ` ,
111+ target:: StaticTarget = StaticTarget (),
109112 kwargs...
110113 )
111114
@@ -114,12 +117,12 @@ function compile_executable(funcs::Union{Array,Tuple}, path::String="./", name=f
114117 isexecutableargtype = tt == Tuple{} || tt == Tuple{Int, Ptr{Ptr{UInt8}}}
115118 isexecutableargtype || @warn " input type signature $types should be either `()` or `(Int, Ptr{Ptr{UInt8}})` for standard executables"
116119
117- rt = last (only (native_code_typed (f, tt; kwargs... )))
120+ rt = last (only (static_code_typed (f, tt; target, kwargs... )))
118121 isconcretetype (rt) || error (" `$f$types ` did not infer to a concrete type. Got `$rt `" )
119122 nativetype = isprimitivetype (rt) || isa (rt, Ptr)
120123 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!"
121124
122- generate_executable (funcs, path, name, filename; demangle, cflags, kwargs... )
125+ generate_executable (funcs, path, name, filename; demangle, cflags, target, kwargs... )
123126 joinpath (abspath (path), filename)
124127end
125128
@@ -129,13 +132,15 @@ compile_shlib(f::Function, types::Tuple, [path::String="./"], [name::String=stri
129132 filename::String=name,
130133 cflags=``,
131134 method_table=StaticCompiler.method_table,
135+ target::StaticTarget=StaticTarget(),
132136 kwargs...)
133137
134138compile_shlib(funcs::Array, [path::String="./"];
135139 filename="libfoo",
136140 demangle=true,
137141 cflags=``,
138142 method_table=StaticCompiler.method_table,
143+ target::StaticTarget=StaticTarget(),
139144 kwargs...)
140145```
141146As `compile_executable`, but compiling to a standalone `.dylib`/`.so` shared library.
@@ -169,33 +174,35 @@ julia> ccall(("test", "test.dylib"), Float64, (Int64,), 100_000)
169174"""
170175function compile_shlib (f:: Function , types= (), path:: String = " ./" , name= fix_name (f);
171176 filename= name,
177+ target:: StaticTarget = StaticTarget (),
172178 kwargs...
173179 )
174- compile_shlib (((f, types),), path; filename, kwargs... )
180+ compile_shlib (((f, types),), path; filename, target, kwargs... )
175181end
176182# As above, but taking an array of functions and returning a single shlib
177183function compile_shlib (funcs:: Union{Array,Tuple} , path:: String = " ./" ;
178184 filename = " libfoo" ,
179185 demangle = true ,
180186 cflags = ` ` ,
187+ target:: StaticTarget = StaticTarget (),
181188 kwargs...
182189 )
183190 for func in funcs
184191 f, types = func
185192 tt = Base. to_tuple_type (types)
186193 isconcretetype (tt) || error (" input type signature `$types ` is not concrete" )
187194
188- rt = last (only (native_code_typed (f, tt)))
195+ rt = last (only (static_code_typed (f, tt; target, kwargs ... )))
189196 isconcretetype (rt) || error (" `$f$types ` did not infer to a concrete type. Got `$rt `" )
190197 nativetype = isprimitivetype (rt) || isa (rt, Ptr)
191198 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!"
192199 end
193200
194- generate_shlib (funcs, true , path, filename; demangle, cflags, kwargs... )
201+ generate_shlib (funcs, path, filename; demangle, cflags, target , kwargs... )
195202
196203 joinpath (abspath (path), filename * " ." * Libdl. dlext)
197204end
198-
205+
199206
200207"""
201208```julia
@@ -281,14 +288,18 @@ generate_executable(f, tt, args...; kwargs...) = generate_executable(((f, tt),),
281288function generate_executable (funcs:: Union{Array,Tuple} , path= tempname (), name= fix_name (first (first (funcs))), filename= name;
282289 demangle = true ,
283290 cflags = ` ` ,
291+ target:: StaticTarget = StaticTarget (),
284292 kwargs...
285293 )
286- lib_path = joinpath (path, " $filename .$(Libdl. dlext) " )
287294 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... )
290296 # 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+
292303 # Compile!
293304 if Sys. isapple ()
294305 # Apple no longer uses _start, so we can just specify a custom entry
318329
319330"""
320331```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...)
323334```
324335Low level interface for compiling a shared object / dynamically loaded library
325336 (`.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)
3563675.2564961094956075
357368```
358369"""
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... )
361372end
362373# 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" ;
364375 demangle = true ,
365376 cflags = ` ` ,
377+ target:: StaticTarget = StaticTarget (),
366378 kwargs...
367379 )
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
368385
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... )
372387 # 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
374393 # Compile!
375394 run (` $cc -shared $cflags $obj_path -o $lib_path ` )
376395
377396 path, name
378397end
379398
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... )
383402end
384403
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... )
387406 GPUCompiler. code_typed (job; kwargs... )
388407end
389408
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... )
393412end
394413
395414# 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... )
397416 if ! demangle
398417 name = " julia_" * name
399418 end
400- job, kwargs = native_job (f, tt, true ; name, kwargs... )
419+ job, kwargs = static_job (f, tt; name, target , kwargs... )
401420 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 )
403422 locate_pointers_and_runtime_calls (m)
404423 m
405424 end
406425 return m
407426end
408427
409428# 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... )
411430 f,tt = funcs[1 ]
412431 mod = GPUCompiler. JuliaContext () do context
413432 name_f = fix_name (f)
414433 if ! demangle
415434 name_f = " julia_" * name_f
416435 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 )
419438 if length (funcs) > 1
420439 for func in funcs[2 : end ]
421440 f,tt = func
422441 name_f = fix_name (f)
423442 if ! demangle
424443 name_f = " julia_" * name_f
425444 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 )
428447 link! (mod,tmod)
429448 end
430449 end
458477
459478"""
460479```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 (),
463482 demangle = true,
464483 strip_llvm = false,
465484 strip_asm = true,
@@ -471,7 +490,7 @@ a tuple type `tt` characterizing the types of the arguments for which the
471490function will be compiled.
472491
473492`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()
475494The defaults compile to the native target.
476495
477496If `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
481500julia> fib(n) = n <= 1 ? n : fib(n - 1) + fib(n - 2)
482501fib (generic function with 1 method)
483502
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")
485504("./test", "fib", IdDict{Any, String}())
486505
487506shell> tree \$ path
498517
499518"""
500519```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 (),
503522 demangle =false,
504523 strip_llvm = false,
505524 strip_asm = true,
@@ -511,21 +530,22 @@ Low level interface for compiling object code (`.o`) for an array of Tuples
511530which will be compiled.
512531
513532`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()
515534The defaults compile to the native target.
516535"""
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" ;
518537 demangle = true ,
519538 strip_llvm = false ,
520539 strip_asm = true ,
521540 opt_level = 3 ,
541+ target:: StaticTarget = StaticTarget (),
522542 kwargs... )
523543 f, tt = funcs[1 ]
524544 mkpath (path)
525545 obj_path = joinpath (path, " $filenamebase .o" )
526- mod = native_llvm_module (funcs; demangle, kwargs... )
546+ mod = static_llvm_module (funcs; demangle, kwargs... )
527547 obj = GPUCompiler. JuliaContext () do ctx
528- fakejob, _ = native_job (f, tt, external; kwargs... )
548+ fakejob, _ = static_job (f, tt; target, kwargs... )
529549 obj, _ = GPUCompiler. emit_asm (fakejob, mod; strip= strip_asm, validate= false , format= LLVM. API. LLVMObjectFile)
530550 obj
531551 end
0 commit comments