Skip to content

Commit 4d1dc32

Browse files
committed
make dynamic-ccall detection more correct
Relies on JuliaLang/julia#59165 for exact accuracy, otherwise we're relying on hoping that `eval` on a random expression is safe and correct (both hopes are quite false).
1 parent 5a2af25 commit 4d1dc32

File tree

1 file changed

+22
-20
lines changed

1 file changed

+22
-20
lines changed

src/optimize.jl

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const compiled_calls = Dict{Any,Any}()
22

33
# Pre-frame-construction lookup
44
function lookup_stmt(stmts::Vector{Any}, @nospecialize arg)
5+
# this convert a statement into something else, without the slightly interest in correctness:
56
if isa(arg, SSAValue)
67
arg = stmts[arg.id]
78
end
@@ -210,30 +211,31 @@ end
210211
# Handle :llvmcall & :foreigncall (issue #28)
211212
function build_compiled_foreigncall!(stmt::Expr, code::CodeInfo, sparams::Vector{Symbol}, evalmod::Module)
212213
TVal = evalmod == Core.Compiler ? Core.Compiler.Val : Val
213-
cfuncarg = stmt.args[1]
214-
while isa(cfuncarg, SSAValue)
215-
cfuncarg = lookup_stmt(code.code, cfuncarg)
216-
end
217214
RetType, ArgType = stmt.args[2], stmt.args[3]::SimpleVector
218215

219216
dynamic_ccall = false
220-
oldcfunc = nothing
221-
if isa(cfuncarg, Expr) || isa(cfuncarg, GlobalRef) || isa(cfuncarg, Symbol) # specification by tuple, e.g., (:clock, "libc")
222-
cfunc = something(try Core.eval(evalmod, cfuncarg) catch nothing end, cfuncarg)
223-
elseif isa(cfuncarg, QuoteNode)
224-
cfunc = cfuncarg.value
225-
else
226-
cfunc = cfuncarg
227-
end
228-
if isa(cfunc, Symbol)
229-
cfunc = QuoteNode(cfunc)
230-
elseif isa(cfunc, String) || isa(cfunc, Ptr) || isa(cfunc, Tuple)
231-
# do nothing
217+
argcfunc = cfunc = stmt.args[1]
218+
if @isdefined(__has_internal_change) && __has_internal_change(v"1.13.0", :syntacticccall)
219+
if !isexpr(cfunc, :tuple)
220+
dynamic_ccall = true
221+
cfunc = gensym("ptr")
222+
end
232223
else
233-
dynamic_ccall = true
234-
oldcfunc = cfunc
235-
cfunc = gensym("ptr")
224+
while isa(cfunc, SSAValue)
225+
cfunc = lookup_stmt(code.code, cfunc)
226+
cfunc isa Symbol && (cfunc = QuoteNode(cfunc))
227+
end
228+
# n.b. Base.memhash is deprecated (continued use would cause serious faults) in the same version as the syntax is deprecated
229+
# so this is only needed as a legacy hack
230+
if isa(cfunc, Expr) || (cfunc isa GlobalRef && cfunc == GlobalRef(Base, :memhash))
231+
cfunc = something(try QuoteNode(Core.eval(evalmod, cfunc)) catch nothing end, cfunc)
232+
end
233+
if !(isa(cfunc, Union{String, Tuple}) || (isa(cfunc, QuoteNode) && isa(cfunc.value, Union{String, Tuple, Symbol})))
234+
dynamic_ccall = true
235+
cfunc = gensym("ptr")
236+
end
236237
end
238+
237239
if isa(RetType, SimpleVector)
238240
@assert length(RetType) == 1
239241
RetType = RetType[1]
@@ -274,7 +276,7 @@ function build_compiled_foreigncall!(stmt::Expr, code::CodeInfo, sparams::Vector
274276
stmt.head = :call
275277
deleteat!(stmt.args, 2:length(stmt.args))
276278
if dynamic_ccall
277-
push!(stmt.args, oldcfunc)
279+
push!(stmt.args, argcfunc)
278280
end
279281
append!(stmt.args, args)
280282
for i in 1:length(sparams)

0 commit comments

Comments
 (0)