@@ -19,9 +19,13 @@ export JuliaContext
19
19
# unique context on all other versions. Once we only support Julia 1.9, we'll deprecate
20
20
# this helper to a regular `Context()` call.
21
21
function JuliaContext ()
22
- if VERSION >= v " 1.9.0-DEV.115"
22
+ if VERSION >= v " 1.9.0-DEV.516"
23
+ # Julia 1.9 knows how to deal with arbitrary contexts,
24
+ # and uses ORC's thread safe versions.
25
+ ThreadSafeContext ()
26
+ elseif VERSION >= v " 1.9.0-DEV.115"
23
27
# Julia 1.9 knows how to deal with arbitrary contexts
24
- JuliaContextType ()
28
+ Context ()
25
29
else
26
30
# earlier versions of Julia claim so, but actually use a global context
27
31
isboxed_ref = Ref {Bool} ()
@@ -31,19 +35,34 @@ function JuliaContext()
31
35
end
32
36
end
33
37
function JuliaContext (f)
34
- if VERSION >= v " 1.9.0-DEV.115"
35
- JuliaContextType (f)
38
+ if VERSION >= v " 1.9.0-DEV.516"
39
+ ts_ctx = ThreadSafeContext ()
40
+ # for now, also activate the underlying context
41
+ # XXX : this is wrong; we can't expose the underlying LLVM context, but should
42
+ # instead always go through the callback in order to unlock it properly.
43
+ # rework this once we depend on Julia 1.9 or later.
44
+ ctx = context (ts_ctx)
45
+ activate (ctx)
46
+ try
47
+ f (ctx)
48
+ finally
49
+ deactivate (ctx)
50
+ dispose (ts_ctx)
51
+ end
52
+ elseif VERSION >= v " 1.9.0-DEV.115"
53
+ Context (f)
36
54
else
37
- f (JuliaContext ())
38
- # we cannot dispose of the global unique context
55
+ ctx = JuliaContext ()
56
+ activate (ctx)
57
+ try
58
+ f (ctx)
59
+ finally
60
+ deactivate (ctx)
61
+ # we cannot dispose of the global unique context
62
+ end
39
63
end
40
64
end
41
65
42
- if VERSION >= v " 1.9.0-DEV.516"
43
- unwrap_context (ctx:: ThreadSafeContext ) = context (ctx)
44
- end
45
- unwrap_context (ctx:: Context ) = ctx
46
-
47
66
48
67
# # compiler entrypoint
49
68
@@ -79,76 +98,62 @@ Other keyword arguments can be found in the documentation of [`cufunction`](@ref
79
98
function compile (target:: Symbol , @nospecialize (job:: CompilerJob );
80
99
libraries:: Bool = true , toplevel:: Bool = true ,
81
100
optimize:: Bool = true , cleanup:: Bool = true , strip:: Bool = false ,
82
- validate:: Bool = true , only_entry:: Bool = false ,
83
- ctx:: Union{JuliaContextType,Nothing} = nothing )
101
+ validate:: Bool = true , only_entry:: Bool = false )
84
102
if compile_hook[] != = nothing
85
103
compile_hook[](job)
86
104
end
87
105
88
106
return codegen (target, job;
89
- libraries, toplevel, optimize, cleanup, strip, validate, only_entry, ctx )
107
+ libraries, toplevel, optimize, cleanup, strip, validate, only_entry)
90
108
end
91
109
92
110
function codegen (output:: Symbol , @nospecialize (job:: CompilerJob );
93
111
libraries:: Bool = true , toplevel:: Bool = true , optimize:: Bool = true ,
94
112
cleanup:: Bool = true , strip:: Bool = false , validate:: Bool = true ,
95
- only_entry:: Bool = false , parent_job:: Union{Nothing, CompilerJob} = nothing ,
96
- ctx:: Union{JuliaContextType,Nothing} = nothing )
113
+ only_entry:: Bool = false , parent_job:: Union{Nothing, CompilerJob} = nothing )
114
+ if context (; throw_error= false ) === nothing
115
+ error (" No active LLVM context. Use `JuliaContext()` do-block syntax to create one." )
116
+ elseif VERSION < v " 1.9.0-DEV.115" && context () != JuliaContext ()
117
+ error (""" Julia <1.9 does not suppport generating code in an arbitrary LLVM context.
118
+ Use `JuliaContext()` do-block syntax to get an appropriate one.""" )
119
+ end
120
+
97
121
@timeit_debug to " Validation" begin
98
122
check_method (job) # not optional
99
123
validate && check_invocation (job)
100
124
end
101
125
102
- temporary_context = ctx === nothing
103
- if temporary_context && output == :llvm
104
- # if we return IR structures, we cannot construct a temporary context
105
- error (" Request to return LLVM IR; please provide a context" )
106
- end
107
-
108
- try
109
- # # LLVM IR
110
126
111
- if temporary_context
112
- ctx = JuliaContext ()
113
- elseif VERSION < v " 1.9.0-DEV.115" && ctx != JuliaContext ()
114
- error (""" Julia <1.9 does not suppport generating code in an arbitrary LLVM context.
115
- Use a JuliaContext instead.""" )
116
- end
127
+ # # LLVM IR
117
128
118
- ir, ir_meta = emit_llvm (job; libraries, toplevel, optimize, cleanup, only_entry, validate, ctx)
119
-
120
- if output == :llvm
121
- if strip
122
- @timeit_debug to " strip debug info" strip_debuginfo! (ir)
123
- end
129
+ ir, ir_meta = emit_llvm (job; libraries, toplevel, optimize, cleanup, only_entry, validate)
124
130
125
- return ir, ir_meta
131
+ if output == :llvm
132
+ if strip
133
+ @timeit_debug to " strip debug info" strip_debuginfo! (ir)
126
134
end
127
135
136
+ return ir, ir_meta
137
+ end
128
138
129
- # # machine code
130
139
131
- format = if output == :asm
132
- LLVM. API. LLVMAssemblyFile
133
- elseif output == :obj
134
- LLVM. API. LLVMObjectFile
135
- else
136
- error (" Unknown assembly format $output " )
137
- end
138
- asm, asm_meta = emit_asm (job, ir; strip, validate, format)
139
-
140
- if output == :asm || output == :obj
141
- return asm, (; asm_meta... , ir_meta... , ir)
142
- end
140
+ # # machine code
143
141
142
+ format = if output == :asm
143
+ LLVM. API. LLVMAssemblyFile
144
+ elseif output == :obj
145
+ LLVM. API. LLVMObjectFile
146
+ else
147
+ error (" Unknown assembly format $output " )
148
+ end
149
+ asm, asm_meta = emit_asm (job, ir; strip, validate, format)
144
150
145
- error (" Unknown compilation output $output " )
146
- finally
147
- if temporary_context && VERSION >= v " 1.9.0-DEV.115"
148
- @assert ctx != JuliaContext ()
149
- dispose (ctx)
150
- end
151
+ if output == :asm || output == :obj
152
+ return asm, (; asm_meta... , ir_meta... , ir)
151
153
end
154
+
155
+
156
+ error (" Unknown compilation output $output " )
152
157
end
153
158
154
159
# primitive mechanism for deferred compilation, for implementing CUDA dynamic parallelism.
@@ -183,8 +188,7 @@ const __llvm_initialized = Ref(false)
183
188
184
189
@locked function emit_llvm (@nospecialize (job:: CompilerJob );
185
190
libraries:: Bool = true , toplevel:: Bool = true , optimize:: Bool = true ,
186
- cleanup:: Bool = true , only_entry:: Bool = false , validate:: Bool = true ,
187
- ctx:: JuliaContextType )
191
+ cleanup:: Bool = true , only_entry:: Bool = false , validate:: Bool = true )
188
192
if ! __llvm_initialized[]
189
193
InitializeAllTargets ()
190
194
InitializeAllTargetInfos ()
@@ -195,7 +199,7 @@ const __llvm_initialized = Ref(false)
195
199
end
196
200
197
201
@timeit_debug to " IR generation" begin
198
- ir, compiled = irgen (job; ctx )
202
+ ir, compiled = irgen (job)
199
203
if job. config. entry_abi === :specfunc
200
204
entry_fn = compiled[job. source]. specfunc
201
205
else
@@ -251,20 +255,20 @@ const __llvm_initialized = Ref(false)
251
255
dyn_ir, dyn_meta = codegen (:llvm , dyn_job; validate= false ,
252
256
optimize= false ,
253
257
toplevel= false ,
254
- parent_job= job, ctx )
258
+ parent_job= job)
255
259
dyn_entry_fn = LLVM. name (dyn_meta. entry)
256
260
merge! (compiled, dyn_meta. compiled)
257
- @assert context (dyn_ir) == unwrap_context (ctx )
261
+ @assert context (dyn_ir) == context (ir )
258
262
link! (ir, dyn_ir)
259
263
changed = true
260
264
dyn_entry_fn
261
265
end
262
266
dyn_entry = functions (ir)[dyn_entry_fn]
263
267
264
268
# insert a pointer to the function everywhere the entry is used
265
- T_ptr = convert (LLVMType, Ptr{Cvoid}; ctx = unwrap_context (ctx) )
269
+ T_ptr = convert (LLVMType, Ptr{Cvoid})
266
270
for call in worklist[dyn_job]
267
- @dispose builder= IRBuilder (unwrap_context (ctx) ) begin
271
+ @dispose builder= IRBuilder () begin
268
272
position! (builder, call)
269
273
fptr = ptrtoint! (builder, dyn_entry, T_ptr)
270
274
replace_uses! (call, fptr)
@@ -283,7 +287,7 @@ const __llvm_initialized = Ref(false)
283
287
# always preload the runtime, and do so early; it cannot be part of any
284
288
# timing block because it recurses into the compiler
285
289
if ! uses_julia_runtime (job) && libraries
286
- runtime = load_runtime (job; ctx )
290
+ runtime = load_runtime (job)
287
291
runtime_fns = LLVM. name .(defs (runtime))
288
292
runtime_intrinsics = [" julia.gc_alloc_obj" ]
289
293
end
@@ -323,7 +327,7 @@ const __llvm_initialized = Ref(false)
323
327
324
328
# mark the kernel entry-point functions (optimization may need it)
325
329
if job. config. kernel
326
- push! (metadata (ir)[" julia.kernel" ], MDNode ([entry]; ctx = unwrap_context (ctx) ))
330
+ push! (metadata (ir)[" julia.kernel" ], MDNode ([entry]))
327
331
328
332
# IDEA: save all jobs, not only kernels, and save other attributes
329
333
# so that we can reconstruct the CompileJob instead of setting it globally
0 commit comments