Skip to content

Commit b1240f0

Browse files
authored
Cassette-type functionality with Mixtape (#69)
1 parent 141e1ab commit b1240f0

15 files changed

Lines changed: 358 additions & 141 deletions

.github/workflows/ci-integration-nightly.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

.github/workflows/ci-integration.yml

Lines changed: 0 additions & 38 deletions
This file was deleted.

.github/workflows/ci-julia-nightly.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ jobs:
1818
fail-fast: false
1919
matrix:
2020
version:
21-
- '1.7'
2221
- '1.8'
22+
- '^1.9.0-rc2'
2323
os:
2424
- ubuntu-latest
2525
- macOS-latest

LICENSE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Copyright (c) 2019-2022 Mason Protter, William Moses, Valentin Churavy,
2-
Brenhin Keller, Julian Samaroo, Tom Short, and
3-
other contributors
2+
McCoy R. Becker, Brenhin Keller, Julian Samaroo,
3+
Tom Short, and other contributors
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

Project.toml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
name = "StaticCompiler"
22
uuid = "81625895-6c0f-48fc-b932-11a18313743c"
33
authors = ["Tom Short and contributors"]
4-
version = "0.4.9"
4+
version = "0.4.10"
55

66
[deps]
77
Clang_jll = "0ee61d77-7f21-5576-8119-9fcc46b10100"
8+
CodeInfoTools = "bc773b8a-8374-437a-b9f2-0e9785855863"
89
GPUCompiler = "61eb1bfa-7361-4325-ad38-22787b887f55"
10+
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
911
LLVM = "929cbde3-209d-540e-8aea-75f648917ca0"
1012
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
13+
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
1114
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
1215
StaticTools = "86c06d3c-3f03-46de-9781-57580aa96d0a"
1316

1417
[compat]
15-
GPUCompiler = "0.16, 0.17"
18+
CodeInfoTools = "0.3"
19+
GPUCompiler = "0.17"
1620
LLVM = "4.8, 5"
1721
StaticTools = "0.8"
18-
julia = "1.7"
22+
MacroTools = "0.5"
23+
julia = "1.8, 1.9"
24+
25+
[extras]
26+
Formatting = "59287772-0a20-5a39-b81b-1366585eb4c0"
27+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
28+
29+
[targets]
30+
test = ["Test", "Formatting"]

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ Hello, world!
6565
```
6666
This latter approach comes with substantially more limitations, as you cannot rely on `libjulia` (see, e.g., [StaticTools.jl](https://github.com/brenhinkeller/StaticTools.jl) for some ways to work around these limitations).
6767

68+
### Mixtape
69+
70+
This feature allows one to change functionality when statically compiling. This uses code and API from [Mixtape](https://github.com/JuliaCompilerPlugins/Mixtape.jl) to transform lowered code much like [Cassette](https://github.com/JuliaLabs/Cassette.jl).
71+
72+
To use the Mixtape feature, define a `CompilationContext` struct and pass this to any of the compilation functions with the `mixtape` keyword. Define `transform` and `allow` functions for this `CompilationContext` to define the transformation to be done.
73+
74+
See [here](https://github.com/tshort/StaticCompiler.jl/blob/master/test/testintegration.jl#L329) for an example.
75+
6876
## Approach
6977

7078
This package uses the [GPUCompiler package](https://github.com/JuliaGPU/GPUCompiler.jl) to generate code.

src/StaticCompiler.jl

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module StaticCompiler
2-
2+
using InteractiveUtils
33
using GPUCompiler: GPUCompiler
44
using LLVM
55
using LLVM.Interop
@@ -15,6 +15,8 @@ export compile, load_function, compile_shlib, compile_executable
1515
export native_code_llvm, native_code_typed, native_llvm_module, native_code_native
1616
export @device_override, @print_and_throw
1717

18+
include("mixtape.jl")
19+
include("interpreter.jl")
1820
include("target.jl")
1921
include("pointer_patching.jl")
2022
include("code_loading.jl")
@@ -87,19 +89,21 @@ with `load_function(path)`. `LazyStaticcompiledfunction`s contain the requisite
8789
`StaticCompiledFunction` and may be called with arguments of type `types` as if it were a function with a
8890
single method (the method determined by `types`).
8991
"""
90-
function compile(f, _tt, path::String = tempname(); name = GPUCompiler.safe_name(repr(f)), filename="obj",
92+
function compile(f, _tt, path::String = tempname();
93+
mixtape = NoContext(),
94+
name = GPUCompiler.safe_name(repr(f)),
95+
filename = "obj",
9196
strip_llvm = false,
9297
strip_asm = true,
9398
opt_level=3,
9499
kwargs...)
95100
tt = Base.to_tuple_type(_tt)
96101
isconcretetype(tt) || error("input type signature $_tt is not concrete")
97102

98-
rt = last(only(native_code_typed(f, tt)))
103+
rt = last(only(native_code_typed(f, tt, mixtape = mixtape)))
99104
isconcretetype(rt) || error("$f on $_tt did not infer to a concrete type. Got $rt")
100-
101105
f_wrap!(out::Ref, args::Ref{<:Tuple}) = (out[] = f(args[]...); nothing)
102-
_, _, table = generate_obj(f_wrap!, Tuple{RefValue{rt}, RefValue{tt}}, false, path, name; opt_level, strip_llvm, strip_asm, filename, kwargs...)
106+
_, _, table = generate_obj(f_wrap!, Tuple{RefValue{rt}, RefValue{tt}}, false, path, name; mixtape = mixtape, opt_level, strip_llvm, strip_asm, filename, kwargs...)
103107

104108
lf = LazyStaticCompiledFunction{rt, tt}(Symbol(f), path, name, filename, table)
105109
cjl_path = joinpath(path, "$filename.cjl")
@@ -136,18 +140,26 @@ shell> tree \$path
136140
```
137141
"""
138142
function generate_obj(f, tt, external = true, path::String = tempname(), name = GPUCompiler.safe_name(repr(f)), filenamebase::String="obj";
143+
mixtape = NoContext(),
139144
strip_llvm = false,
140145
strip_asm = true,
141146
opt_level=3,
142147
kwargs...)
143148
mkpath(path)
144149
obj_path = joinpath(path, "$filenamebase.o")
145150
tm = GPUCompiler.llvm_machine(external ? ExternalNativeCompilerTarget() : NativeCompilerTarget())
146-
job, kwargs = native_job(f, tt, external; name, kwargs...)
147151
#Get LLVM to generated a module of code for us. We don't want GPUCompiler's optimization passes.
152+
job = CompilerJob(NativeCompilerTarget(),
153+
FunctionSpec(f, tt, false, name),
154+
StaticCompilerParams(;
155+
opt = true,
156+
mixtape = mixtape,
157+
optlevel = Base.JLOptions().opt_level))
158+
148159
mod, meta = GPUCompiler.JuliaContext() do context
149160
GPUCompiler.codegen(:llvm, job; strip=strip_llvm, only_entry=false, validate=false, optimize=false, ctx=context)
150-
end
161+
end
162+
151163
# Use Enzyme's annotation and optimization pipeline
152164
annotate!(mod)
153165
optimize!(mod, tm)
@@ -247,7 +259,7 @@ function compile_executable(f::Function, types=(), path::String="./", name=GPUCo
247259
isexecutableargtype = tt == Tuple{} || tt == Tuple{Int, Ptr{Ptr{UInt8}}}
248260
isexecutableargtype || @warn "input type signature $types should be either `()` or `(Int, Ptr{Ptr{UInt8}})` for standard executables"
249261

250-
rt = last(only(native_code_typed(f, tt)))
262+
rt = last(only(native_code_typed(f, tt; kwargs...)))
251263
isconcretetype(rt) || error("`$f$types` did not infer to a concrete type. Got `$rt`")
252264
nativetype = isprimitivetype(rt) || isa(rt, Ptr)
253265
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!"
@@ -302,7 +314,7 @@ function compile_shlib(f::Function, types=(), path::String="./", name=GPUCompile
302314
tt = Base.to_tuple_type(types)
303315
isconcretetype(tt) || error("input type signature `$types` is not concrete")
304316

305-
rt = last(only(native_code_typed(f, tt)))
317+
rt = last(only(native_code_typed(f, tt; kwargs...)))
306318
isconcretetype(rt) || error("`$f$types` did not infer to a concrete type. Got `$rt`")
307319
nativetype = isprimitivetype(rt) || isa(rt, Ptr)
308320
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!"

src/code_loading.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ function instantiate(p::LazyStaticCompiledFunction{rt, tt}) where {rt, tt}
4949
prefix = LLVM.get_prefix(lljit)
5050
dg = LLVM.CreateDynamicLibrarySearchGeneratorForProcess(prefix)
5151
LLVM.add!(jd, dg)
52-
5352
LLVM.add!(lljit, jd, ofile)
5453
fptr = pointer(LLVM.lookup(lljit, "julia_" * p.name))
5554

0 commit comments

Comments
 (0)