Skip to content

Commit 70d4065

Browse files
authored
Cleanup and more support for arrays of functions (reland) (#122)
* Cleanup and more support for arrays of functions * switch wasm back to generate_obj_for_compile
1 parent a076a62 commit 70d4065

1 file changed

Lines changed: 103 additions & 37 deletions

File tree

src/StaticCompiler.jl

Lines changed: 103 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function compile(f, _tt, path::String = tempname();
106106
rt = last(only(native_code_typed(f, tt, mixtape = mixtape)))
107107
isconcretetype(rt) || error("$f on $_tt did not infer to a concrete type. Got $rt")
108108
f_wrap!(out::Ref, args::Ref{<:Tuple}) = (out[] = f(args[]...); nothing)
109-
_, _, table = generate_obj(f_wrap!, Tuple{RefValue{rt}, RefValue{tt}}, false, path, name; mixtape = mixtape, opt_level, strip_llvm, strip_asm, filename, kwargs...)
109+
_, _, table = generate_obj_for_compile(f_wrap!, Tuple{RefValue{rt}, RefValue{tt}}, false, path, name; mixtape = mixtape, opt_level, strip_llvm, strip_asm, filename, kwargs...)
110110

111111
lf = LazyStaticCompiledFunction{rt, tt}(Symbol(f), path, name, filename, table)
112112
cjl_path = joinpath(path, "$filename.cjl")
@@ -117,7 +117,7 @@ end
117117

118118
"""
119119
```julia
120-
generate_obj(f, tt, path::String = tempname(), name = fix_name(repr(f)), filenamebase::String="obj";
120+
generate_obj_for_compile(f, tt, path::String = tempname(), name = fix_name(repr(f)), filenamebase::String="obj";
121121
\tmixtape = NoContext(),
122122
\tstrip_llvm = false,
123123
\tstrip_asm = true,
@@ -141,7 +141,7 @@ The defaults compile to the native target.
141141
julia> fib(n) = n <= 1 ? n : fib(n - 1) + fib(n - 2)
142142
fib (generic function with 1 method)
143143
144-
julia> path, name, table = StaticCompiler.generate_obj(fib, Tuple{Int64}, "./test")
144+
julia> path, name, table = StaticCompiler.generate_obj_for_compile(fib, Tuple{Int64}, "./test")
145145
("./test", "fib", IdDict{Any, String}())
146146
147147
shell> tree \$path
@@ -151,7 +151,7 @@ shell> tree \$path
151151
0 directories, 1 file
152152
```
153153
"""
154-
function generate_obj(f, tt, external = true, path::String = tempname(), name = fix_name(repr(f)), filenamebase::String="obj";
154+
function generate_obj_for_compile(f, tt, external = true, path::String = tempname(), name = fix_name(repr(f)), filenamebase::String="obj";
155155
mixtape = NoContext(),
156156
strip_llvm = false,
157157
strip_asm = true,
@@ -200,10 +200,13 @@ end
200200
compile_executable(f::Function, types::Tuple, path::String, [name::String=repr(f)];
201201
filename::String=name,
202202
cflags=``, # Specify libraries you would like to link against, and other compiler options here
203+
also_expose=[],
203204
kwargs...
204205
)
205206
```
206207
Attempt to compile a standalone executable that runs function `f` with a type signature given by the tuple of `types`.
208+
If there are extra methods you would like to protect from name mangling in the produced binary for whatever reason,
209+
you can provide them as a vector of tuples of functions and types, i.e. `[(f1, types1), (f2, types2), ...]`
207210
208211
### Examples
209212
```julia
@@ -261,11 +264,21 @@ Hello, world!
261264
```
262265
"""
263266
function compile_executable(f::Function, types=(), path::String="./", name=fix_name(repr(f));
267+
also_expose=[],
268+
filename=name,
269+
cflags=``,
270+
kwargs...)
271+
compile_executable(vcat([(f, types)], also_expose), path, name; filename, cflags, kwargs...)
272+
end
273+
274+
275+
function compile_executable(funcs::Array, path::String="./", name=fix_name(repr(funcs[1][1]));
264276
filename=name,
265277
cflags=``,
266278
kwargs...
267279
)
268280

281+
(f, types) = funcs[1]
269282
tt = Base.to_tuple_type(types)
270283
isexecutableargtype = tt == Tuple{} || tt == Tuple{Int, Ptr{Ptr{UInt8}}}
271284
isexecutableargtype || @warn "input type signature $types should be either `()` or `(Int, Ptr{Ptr{UInt8}})` for standard executables"
@@ -274,13 +287,11 @@ function compile_executable(f::Function, types=(), path::String="./", name=fix_n
274287
isconcretetype(rt) || error("`$f$types` did not infer to a concrete type. Got `$rt`")
275288
nativetype = isprimitivetype(rt) || isa(rt, Ptr)
276289
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!"
277-
278-
generate_executable(f, tt, path, name, filename; cflags=cflags, kwargs...)
279-
290+
291+
generate_executable(funcs, path, name, filename; cflags=cflags, kwargs...)
280292
joinpath(abspath(path), filename)
281293
end
282294

283-
284295
"""
285296
```julia
286297
compile_shlib(f::Function, types::Tuple, [path::String="./"], [name::String=repr(f)]; filename::String=name, cflags=``, kwargs...)
@@ -377,7 +388,7 @@ function compile_wasm(f::Function, types=();
377388
kwargs...
378389
)
379390
tt = Base.to_tuple_type(types)
380-
obj_path, name = generate_obj(f, tt, true, path, filename; target = (triple = "wasm32-unknown-wasi", cpu = "", features = ""), remove_julia_addrspaces = true, kwargs...)
391+
obj_path, name = generate_obj_for_compile(f, tt, true, path, filename; target = (triple = "wasm32-unknown-wasi", cpu = "", features = ""), remove_julia_addrspaces = true, kwargs...)
381392
run(`$(lld()) -flavor wasm --no-entry --export-all $flags $obj_path/obj.o -o $path/$name.wasm`)
382393
joinpath(abspath(path), filename * ".wasm")
383394
end
@@ -471,21 +482,19 @@ shell> ./hello
471482
Hello, world!
472483
```
473484
"""
474-
function generate_executable(f, tt, path=tempname(), name=fix_name(repr(f)), filename=string(name);
475-
cflags=``,
476-
kwargs...
477-
)
478-
mkpath(path)
479-
obj_path = joinpath(path, "$filename.o")
480-
exec_path = joinpath(path, filename)
481-
job, kwargs = native_job(f, tt, true; name, kwargs...)
482-
obj, _ = GPUCompiler.codegen(:obj, job; strip=true, only_entry=false, validate=false)
483-
484-
# Write to file
485-
open(obj_path, "w") do io
486-
write(io, obj)
487-
end
485+
function generate_executable(f, tt, args...; kwargs...)
486+
generate_executable([(f, tt)], args...; kwargs...)
487+
end
488488

489+
function generate_executable(funcs::Array, path=tempname(), name=fix_name(repr(funcs[1][1])), filename=string(name);
490+
demangle=false,
491+
cflags=``,
492+
kwargs...
493+
)
494+
lib_path = joinpath(path, "$filename.$(Libdl.dlext)")
495+
exec_path = joinpath(path, filename)
496+
external = true
497+
_, obj_path = generate_obj(funcs, external, path, filename; demangle=demangle, kwargs...)
489498
# Pick a compiler
490499
cc = Sys.isapple() ? `cc` : clang()
491500
# Compile!
@@ -510,10 +519,10 @@ function generate_executable(f, tt, path=tempname(), name=fix_name(repr(f)), fil
510519
# Clean up
511520
run(`rm $wrapper_path`)
512521
end
513-
514522
path, name
515523
end
516524

525+
517526
"""
518527
```julia
519528
generate_shlib(f::Function, tt, [external::Bool=true], [path::String], [name], [filename]; kwargs...)
@@ -553,23 +562,15 @@ julia> ccall(("julia_test", "example/test.dylib"), Float64, (Int64,), 100_000)
553562
```
554563
"""
555564
function generate_shlib(f::Function, tt, external::Bool=true, path::String=tempname(), name=fix_name(repr(f)), filename=name;
556-
cflags=``,
565+
cflags=``, demangle=false,
557566
kwargs...
558567
)
559-
560-
mkpath(path)
561-
obj_path = joinpath(path, "$filename.o")
562568
lib_path = joinpath(path, "$filename.$(Libdl.dlext)")
563-
job, kwargs = native_job(f, tt, external; name, kwargs...)
564-
obj, _ = GPUCompiler.codegen(:obj, job; strip=true, only_entry=false, validate=false)
565-
566-
open(obj_path, "w") do io
567-
write(io, obj)
568-
end
569-
569+
_, obj_path = generate_obj([(f, tt)], external, path, filename; demangle=demangle, kwargs...)
570+
570571
# Pick a Clang
571572
cc = Sys.isapple() ? `cc` : clang()
572-
# Compile!
573+
# Compile
573574
run(`$cc -shared $cflags $obj_path -o $lib_path`)
574575

575576
path, name
@@ -583,7 +584,7 @@ function generate_shlib(funcs::Array, external::Bool=true, path::String=tempname
583584

584585
lib_path = joinpath(path, "$filename.$(Libdl.dlext)")
585586

586-
_,obj_path = generate_obj(funcs, external, path, filename; demangle=demangle, kwargs...)
587+
_, obj_path = generate_obj(funcs, external, path, filename; demangle=demangle, kwargs...)
587588
# Pick a Clang
588589
cc = Sys.isapple() ? `cc` : clang()
589590
# Compile!
@@ -642,6 +643,71 @@ function native_llvm_module(funcs::Array; demangle = false, kwargs...)
642643
return mod
643644
end
644645

646+
647+
"""
648+
```julia
649+
generate_obj(f, tt, external::Bool, path::String = tempname(), filenamebase::String="obj";
650+
mixtape = NoContext(),
651+
target = (),
652+
demangle =false,
653+
strip_llvm = false,
654+
strip_asm = true,
655+
opt_level=3,
656+
kwargs...)
657+
```
658+
Low level interface for compiling object code (`.o`) for for function `f` given
659+
a tuple type `tt` characterizing the types of the arguments for which the
660+
function will be compiled.
661+
662+
`mixtape` defines a context that can be used to transform IR prior to compilation using
663+
[Mixtape](https://github.com/JuliaCompilerPlugins/Mixtape.jl) features.
664+
665+
`target` can be used to change the output target. This is useful for compiling to WebAssembly and embedded targets.
666+
This is a named tuple with fields `triple`, `cpu`, and `features` (each of these are strings).
667+
The defaults compile to the native target.
668+
669+
### Examples
670+
```julia
671+
julia> fib(n) = n <= 1 ? n : fib(n - 1) + fib(n - 2)
672+
fib (generic function with 1 method)
673+
674+
julia> path, name, table = StaticCompiler.generate_obj_for_compile(fib, Tuple{Int64}, "./test")
675+
("./test", "fib", IdDict{Any, String}())
676+
677+
shell> tree \$path
678+
./test
679+
└── obj.o
680+
681+
0 directories, 1 file
682+
```
683+
"""
684+
function generate_obj(f, tt, args...; kwargs...)
685+
generate_obj([(f, tt)], args...; kwargs...)
686+
end
687+
688+
689+
"""
690+
```julia
691+
generate_obj(funcs::Array, external::Bool, path::String = tempname(), filenamebase::String="obj";
692+
mixtape = NoContext(),
693+
target = (),
694+
demangle =false,
695+
strip_llvm = false,
696+
strip_asm = true,
697+
opt_level=3,
698+
kwargs...)
699+
```
700+
Low level interface for compiling object code (`.o`) for an array of Tuples
701+
(f, tt) where each function `f` and tuple type `tt` determine the set of methods
702+
which will be compiled.
703+
704+
`mixtape` defines a context that can be used to transform IR prior to compilation using
705+
[Mixtape](https://github.com/JuliaCompilerPlugins/Mixtape.jl) features.
706+
707+
`target` can be used to change the output target. This is useful for compiling to WebAssembly and embedded targets.
708+
This is a named tuple with fields `triple`, `cpu`, and `features` (each of these are strings).
709+
The defaults compile to the native target.
710+
"""
645711
function generate_obj(funcs::Array, external::Bool, path::String = tempname(), filenamebase::String="obj";
646712
demangle =false,
647713
strip_llvm = false,

0 commit comments

Comments
 (0)