1
1
const calllike = Set ([:call , :foreigncall ])
2
2
3
+ const compiled_calls = Dict {Any,Any} ()
4
+
3
5
function extract_inner_call! (stmt, idx, once:: Bool = false )
4
6
isa (stmt, Expr) || return nothing
5
7
(stmt. head == :toplevel || stmt. head == :thunk ) && return nothing
@@ -127,8 +129,10 @@ which this will run) and ensures that no statement includes nested `:call` expre
127
129
"""
128
130
function optimize! (code:: CodeInfo , scope)
129
131
mod = moduleof (scope)
132
+ evalmod = mod == Core. Compiler ? Core. Compiler : CompiledCalls
130
133
sparams = scope isa Method ? Symbol[sparam_syms (scope)... ] : Symbol[]
131
134
code. inferred && error (" optimization of inferred code not implemented" )
135
+ replace_coretypes! (code)
132
136
# TODO : because of builtins.jl, for CodeInfos like
133
137
# %1 = Core.apply_type
134
138
# %2 = (%1)(args...)
@@ -163,7 +167,7 @@ function optimize!(code::CodeInfo, scope)
163
167
ustr = replace (string (uuid), ' -' => ' _' )
164
168
methname = Symbol (" llvmcall_" , ustr)
165
169
nargs = length (stmt. args)- 4
166
- delete_idx = build_compiled_call! (stmt, methname, Base. llvmcall, stmt. args[2 : 4 ], code, idx, nargs, sparams)
170
+ delete_idx = build_compiled_call! (stmt, methname, Base. llvmcall, stmt. args[2 : 4 ], code, idx, nargs, sparams, evalmod )
167
171
push! (foreigncalls_idx, idx)
168
172
append! (delete_idxs, delete_idx)
169
173
end
@@ -189,7 +193,7 @@ function optimize!(code::CodeInfo, scope)
189
193
ustr = replace (string (uuid), ' -' => ' _' )
190
194
methname = Symbol (" ccall" , ' _' , f, ' _' , ustr)
191
195
nargs = stmt. args[5 ]
192
- delete_idx = build_compiled_call! (stmt, methname, :ccall , stmt. args[1 : 3 ], code, idx, nargs, sparams)
196
+ delete_idx = build_compiled_call! (stmt, methname, :ccall , stmt. args[1 : 3 ], code, idx, nargs, sparams, evalmod )
193
197
push! (foreigncalls_idx, idx)
194
198
append! (delete_idxs, delete_idx)
195
199
end
@@ -239,14 +243,15 @@ end
239
243
function parametric_type_to_expr (t:: Type )
240
244
t isa Core. TypeofBottom && return t
241
245
t isa UnionAll && (t = t. body)
242
- if t <: Vararg
246
+ if t <: Vararg
243
247
return Expr (:(... ), t. parameters[1 ])
244
248
end
245
249
return t. hasfreetypevars ? Expr (:curly , t. name. name, ((tv-> tv isa TypeVar ? tv. name : tv). (t. parameters)). .. ) : t
246
250
end
247
251
248
252
# Handle :llvmcall & :foreigncall (issue #28)
249
- function build_compiled_call! (stmt, methname, fcall, typargs, code, idx, nargs, sparams)
253
+ function build_compiled_call! (stmt, methname, fcall, typargs, code, idx, nargs, sparams, evalmod)
254
+ TVal = evalmod == Core. Compiler ? Core. Compiler. Val : Val
250
255
argnames = Any[Symbol (" arg" , string (i)) for i = 1 : nargs]
251
256
delete_idx = Int[]
252
257
if fcall == :ccall
@@ -287,48 +292,74 @@ function build_compiled_call!(stmt, methname, fcall, typargs, code, idx, nargs,
287
292
cfunc, RetType, ArgType = @lookup (frame, stmt. args[2 ]), @lookup (frame, stmt. args[3 ]), @lookup (frame, stmt. args[4 ])
288
293
args = stmt. args[5 : end ]
289
294
end
290
- if isa (cfunc, Expr)
295
+ if isa (cfunc, Expr) # specification by tuple, e.g., (:clock, "libc")
291
296
cfunc = eval (cfunc)
292
297
end
293
298
if isa (cfunc, Symbol)
294
299
cfunc = QuoteNode (cfunc)
295
300
end
296
- if fcall == :ccall
297
- ArgType = Expr (:tuple , [parametric_type_to_expr (t) for t in ArgType]. .. )
298
- end
299
301
if isa (RetType, SimpleVector)
300
302
@assert length (RetType) == 1
301
303
RetType = RetType[1 ]
302
304
end
303
- RetType = parametric_type_to_expr (RetType)
304
- wrapargs = copy (argnames)
305
- for sparam in sparams
306
- push! (wrapargs, :(:: Val{$sparam} ))
307
- end
308
- if stmt. args[4 ] == :(:llvmcall )
309
- def = :(
310
- function $methname ($ (wrapargs... )) where {$ (sparams... )}
311
- return $ fcall ($ cfunc, llvmcall, $ RetType, $ ArgType, $ (argnames... ))
312
- end )
313
- elseif stmt. args[4 ] == :(:stdcall )
314
- def = :(
315
- function $methname ($ (wrapargs... )) where {$ (sparams... )}
316
- return $ fcall ($ cfunc, stdcall, $ RetType, $ ArgType, $ (argnames... ))
317
- end )
318
- else
319
- def = :(
320
- function $methname ($ (wrapargs... )) where {$ (sparams... )}
321
- return $ fcall ($ cfunc, $ RetType, $ ArgType, $ (argnames... ))
322
- end )
305
+ cc_key = (cfunc, RetType, ArgType, evalmod) # compiled call key
306
+ f = get (compiled_calls, cc_key, nothing )
307
+ if f === nothing
308
+ if fcall == :ccall
309
+ ArgType = Expr (:tuple , [parametric_type_to_expr (t) for t in ArgType]. .. )
310
+ end
311
+ RetType = parametric_type_to_expr (RetType)
312
+ wrapargs = copy (argnames)
313
+ for sparam in sparams
314
+ push! (wrapargs, :(:: $TVal{$sparam} ))
315
+ end
316
+ if stmt. args[4 ] == :(:llvmcall )
317
+ def = :(
318
+ function $methname ($ (wrapargs... )) where {$ (sparams... )}
319
+ return $ fcall ($ cfunc, llvmcall, $ RetType, $ ArgType, $ (argnames... ))
320
+ end )
321
+ elseif stmt. args[4 ] == :(:stdcall )
322
+ def = :(
323
+ function $methname ($ (wrapargs... )) where {$ (sparams... )}
324
+ return $ fcall ($ cfunc, stdcall, $ RetType, $ ArgType, $ (argnames... ))
325
+ end )
326
+ else
327
+ def = :(
328
+ function $methname ($ (wrapargs... )) where {$ (sparams... )}
329
+ return $ fcall ($ cfunc, $ RetType, $ ArgType, $ (argnames... ))
330
+ end )
331
+ end
332
+ f = Core. eval (evalmod, def)
333
+ compiled_calls[cc_key] = f
323
334
end
324
- f = Core. eval (CompiledCalls, def)
325
335
stmt. args[1 ] = QuoteNode (f)
326
336
stmt. head = :call
327
337
deleteat! (stmt. args, 2 : length (stmt. args))
328
338
append! (stmt. args, args)
329
339
for i in 1 : length (sparams)
330
- push! (stmt. args, :($ Val ($ (Expr (:static_parameter , i)))))
340
+ push! (stmt. args, :($ TVal ($ (Expr (:static_parameter , i)))))
331
341
end
332
342
return delete_idx
333
343
end
334
344
345
+ function replace_coretypes! (src; rev:: Bool = false )
346
+ if isa (src, CodeInfo)
347
+ replace_coretypes_list! (src. code; rev= rev)
348
+ elseif isa (src, Expr)
349
+ replace_coretypes_list! (src. args; rev= rev)
350
+ end
351
+ return src
352
+ end
353
+
354
+ function replace_coretypes_list! (list; rev:: Bool )
355
+ for (i, stmt) in enumerate (list)
356
+ if isa (stmt, rev ? SSAValue : Core. SSAValue)
357
+ list[i] = rev ? Core. SSAValue (stmt. id) : SSAValue (stmt. id)
358
+ elseif isa (stmt, rev ? SlotNumber : Core. SlotNumber)
359
+ list[i] = rev ? Core. SlotNumber (stmt. id) : SlotNumber (stmt. id)
360
+ elseif isa (stmt, Expr)
361
+ replace_coretypes! (stmt; rev= rev)
362
+ end
363
+ end
364
+ return nothing
365
+ end
0 commit comments