@@ -163,37 +163,14 @@ function optimize!(code::CodeInfo, scope)
163
163
# Check for :llvmcall
164
164
arg1 = stmt. args[1 ]
165
165
if (arg1 == :llvmcall || lookup_stmt (code. code, arg1) == Base. llvmcall) && isempty (sparams) && scope isa Method
166
- uuid = uuid1 (rng)
167
- ustr = replace (string (uuid), ' -' => ' _' )
168
- methname = Symbol (" llvmcall_" , ustr)
169
166
nargs = length (stmt. args)- 4
170
- delete_idx = build_compiled_call! (stmt, methname, Base. llvmcall, stmt. args[2 : 4 ], code, idx, nargs, sparams, evalmod)
167
+ delete_idx = build_compiled_call! (stmt, Base. llvmcall, stmt. args[2 : 4 ], code, idx, nargs, sparams, evalmod)
171
168
push! (foreigncalls_idx, idx)
172
169
append! (delete_idxs, delete_idx)
173
170
end
174
171
elseif isexpr (stmt, :foreigncall ) && scope isa Method
175
- f = lookup_stmt (code. code, stmt. args[1 ])
176
- if isa (f, Ptr)
177
- f = string (uuid1 (rng))
178
- elseif isexpr (f, :call )
179
- length (f. args) == 3 || continue
180
- if ! (f. args[1 ] === tuple || f. args[1 ] == :($ (QuoteNode (tuple))))
181
- continue
182
- end
183
- lib = f. args[3 ] isa String ? f. args[3 ] : f. args[3 ]. value
184
- prefix = f. args[2 ] isa String ? f. args[2 ] : f. args[2 ]. value
185
- f = Symbol (prefix, ' _' , lib)
186
- end
187
- # Punt on non literal ccall arguments for now
188
- if ! (isa (f, String) || isa (f, Symbol) || isa (f, Ptr))
189
- continue
190
- end
191
- # TODO : Only compile one ccall per call and argument types
192
- uuid = uuid1 (rng)
193
- ustr = replace (string (uuid), ' -' => ' _' )
194
- methname = Symbol (" ccall" , ' _' , f, ' _' , ustr)
195
172
nargs = stmt. args[5 ]
196
- delete_idx = build_compiled_call! (stmt, methname, :ccall , stmt. args[1 : 3 ], code, idx, nargs, sparams, evalmod)
173
+ delete_idx = build_compiled_call! (stmt, :ccall , stmt. args[1 : 3 ], code, idx, nargs, sparams, evalmod)
197
174
push! (foreigncalls_idx, idx)
198
175
append! (delete_idxs, delete_idx)
199
176
end
@@ -250,7 +227,7 @@ function parametric_type_to_expr(t::Type)
250
227
end
251
228
252
229
# Handle :llvmcall & :foreigncall (issue #28)
253
- function build_compiled_call! (stmt, methname, fcall, typargs, code, idx, nargs, sparams, evalmod)
230
+ function build_compiled_call! (stmt, fcall, typargs, code, idx, nargs, sparams, evalmod)
254
231
TVal = evalmod == Core. Compiler ? Core. Compiler. Val : Val
255
232
argnames = Any[Symbol (" arg" , string (i)) for i = 1 : nargs]
256
233
delete_idx = Int[]
@@ -292,27 +269,39 @@ function build_compiled_call!(stmt, methname, fcall, typargs, code, idx, nargs,
292
269
cfunc, RetType, ArgType = @lookup (frame, stmt. args[2 ]), @lookup (frame, stmt. args[3 ]), @lookup (frame, stmt. args[4 ])
293
270
args = stmt. args[5 : end ]
294
271
end
272
+ dynamic_ccall = false
295
273
if isa (cfunc, Expr) # specification by tuple, e.g., (:clock, "libc")
296
274
cfunc = eval (cfunc)
297
275
end
298
276
if isa (cfunc, Symbol)
299
277
cfunc = QuoteNode (cfunc)
278
+ elseif isa (cfunc, String) || isa (cfunc, Ptr) || isa (cfunc, Tuple)
279
+ # do nothing
280
+ else
281
+ dynamic_ccall = true
282
+ oldcfunc = cfunc
283
+ cfunc = gensym (" ptr" )
300
284
end
301
285
if isa (RetType, SimpleVector)
302
286
@assert length (RetType) == 1
303
287
RetType = RetType[1 ]
304
288
end
305
- cc_key = (cfunc, RetType, ArgType, evalmod) # compiled call key
289
+ # When the ccall is dynamic we pass the pointer as an argument so can reuse the function
290
+ cc_key = (dynamic_ccall ? :ptr : cfunc, RetType, ArgType, evalmod) # compiled call key
306
291
f = get (compiled_calls, cc_key, nothing )
307
292
if f === nothing
308
293
if fcall == :ccall
309
294
ArgType = Expr (:tuple , [parametric_type_to_expr (t) for t in ArgType]. .. )
310
295
end
311
296
RetType = parametric_type_to_expr (RetType)
312
297
wrapargs = copy (argnames)
298
+ if dynamic_ccall
299
+ pushfirst! (wrapargs, cfunc)
300
+ end
313
301
for sparam in sparams
314
302
push! (wrapargs, :(:: $TVal{$sparam} ))
315
303
end
304
+ methname = gensym (" compiledcall" )
316
305
if stmt. args[4 ] == :(:llvmcall )
317
306
def = :(
318
307
function $methname ($ (wrapargs... )) where {$ (sparams... )}
@@ -335,6 +324,9 @@ function build_compiled_call!(stmt, methname, fcall, typargs, code, idx, nargs,
335
324
stmt. args[1 ] = QuoteNode (f)
336
325
stmt. head = :call
337
326
deleteat! (stmt. args, 2 : length (stmt. args))
327
+ if dynamic_ccall
328
+ push! (stmt. args, oldcfunc)
329
+ end
338
330
append! (stmt. args, args)
339
331
for i in 1 : length (sparams)
340
332
push! (stmt. args, :($ TVal ($ (Expr (:static_parameter , i)))))
0 commit comments