Skip to content

Commit 64a2eae

Browse files
authored
fix ccall with e.g. integer static parameters (#234)
* fix ccall with e.g. integer static parameters
1 parent c644081 commit 64a2eae

File tree

2 files changed

+39
-29
lines changed

2 files changed

+39
-29
lines changed

src/optimize.jl

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -127,33 +127,10 @@ function optimize!(code::CodeInfo, scope)
127127
end
128128
end
129129

130-
## Un-nest :call expressions (so that there will be only one :call per line)
131-
# This will allow us to re-use args-buffers rather than having to allocate new ones each time.
132-
old_code, old_codelocs = code.code, code.codelocs
133-
code.code = new_code = eltype(old_code)[]
134-
code.codelocs = new_codelocs = Int32[]
135-
ssainc = fill(1, length(old_code))
136-
for (i, stmt) in enumerate(old_code)
137-
loc = old_codelocs[i]
138-
inner = extract_inner_call!(stmt, length(new_code)+1)
139-
while inner !== nothing
140-
push!(new_code, inner)
141-
push!(new_codelocs, loc)
142-
ssainc[i] += 1
143-
inner = extract_inner_call!(stmt, length(new_code)+1)
144-
end
145-
push!(new_code, stmt)
146-
push!(new_codelocs, loc)
147-
end
148-
# Fix all the SSAValues and GotoNodes
149-
ssalookup = cumsum(ssainc)
150-
renumber_ssa!(new_code, ssalookup)
151-
code.ssavaluetypes = length(new_code)
152-
153-
# Replace :llvmcall and :foreigncall with compiled variants. See
130+
# Replace :llvmcall and :foreigncall with compiled variants. See
154131
# https://github.com/JuliaDebug/JuliaInterpreter.jl/issues/13#issuecomment-464880123
155-
methodtables = Vector{Union{Compiled,TypeMapEntry}}(undef, length(code.code))
156132
# @show code
133+
foreigncalls_idx = Int[]
157134
for (idx, stmt) in enumerate(code.code)
158135
# Foregincalls can be rhs of assignments
159136
if isexpr(stmt, :(=))
@@ -168,7 +145,7 @@ function optimize!(code::CodeInfo, scope)
168145
methname = Symbol("llvmcall_", ustr)
169146
nargs = length(stmt.args)-4
170147
build_compiled_call!(stmt, methname, Base.llvmcall, stmt.args[2:4], code, idx, nargs, sparams)
171-
methodtables[idx] = Compiled()
148+
push!(foreigncalls_idx, idx)
172149
end
173150
elseif isexpr(stmt, :foreigncall) && scope isa Method
174151
f = lookup_stmt(code.code, stmt.args[1])
@@ -193,8 +170,37 @@ function optimize!(code::CodeInfo, scope)
193170
methname = Symbol("ccall", '_', f, '_', ustr)
194171
nargs = stmt.args[5]
195172
build_compiled_call!(stmt, methname, :ccall, stmt.args[1:3], code, idx, nargs, sparams)
196-
methodtables[idx] = Compiled()
173+
push!(foreigncalls_idx, idx)
174+
end
175+
end
176+
177+
## Un-nest :call expressions (so that there will be only one :call per line)
178+
# This will allow us to re-use args-buffers rather than having to allocate new ones each time.
179+
old_code, old_codelocs = code.code, code.codelocs
180+
code.code = new_code = eltype(old_code)[]
181+
code.codelocs = new_codelocs = Int32[]
182+
ssainc = fill(1, length(old_code))
183+
for (i, stmt) in enumerate(old_code)
184+
loc = old_codelocs[i]
185+
inner = extract_inner_call!(stmt, length(new_code)+1)
186+
while inner !== nothing
187+
push!(new_code, inner)
188+
push!(new_codelocs, loc)
189+
ssainc[i] += 1
190+
inner = extract_inner_call!(stmt, length(new_code)+1)
197191
end
192+
push!(new_code, stmt)
193+
push!(new_codelocs, loc)
194+
end
195+
# Fix all the SSAValues and GotoNodes
196+
ssalookup = cumsum(ssainc)
197+
renumber_ssa!(new_code, ssalookup)
198+
code.ssavaluetypes = length(new_code)
199+
200+
# Insert the foreigncall wrappers at the updated idxs
201+
methodtables = Vector{Union{Compiled,TypeMapEntry}}(undef, length(code.code))
202+
for idx in foreigncalls_idx
203+
methodtables[ssalookup[idx]] = Compiled()
198204
end
199205

200206
return code, methodtables
@@ -259,7 +265,7 @@ function build_compiled_call!(stmt, methname, fcall, typargs, code, idx, nargs,
259265
RetType = parametric_type_to_expr(RetType)
260266
wrapargs = copy(argnames)
261267
for sparam in sparams
262-
push!(wrapargs, :(::Type{$sparam}))
268+
push!(wrapargs, :(::Val{$sparam}))
263269
end
264270
if stmt.args[4] == :(:llvmcall)
265271
def = :(
@@ -278,7 +284,7 @@ function build_compiled_call!(stmt, methname, fcall, typargs, code, idx, nargs,
278284
deleteat!(stmt.args, 2:length(stmt.args))
279285
append!(stmt.args, args)
280286
for i in 1:length(sparams)
281-
push!(stmt.args, :($(Expr(:static_parameter, i))))
287+
push!(stmt.args, :($Val($(Expr(:static_parameter, i)))))
282288
end
283289
return
284290
end

test/interpret.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,10 @@ function call_cf()
464464
end
465465
@test (@interpret call_cf()) == call_cf()
466466

467+
# ccall with integer static parameter
468+
f_N() = Array{Float64, 4}(undef, 1, 3, 2, 1)
469+
@test (@interpret f_N()) isa Array{Float64, 4}
470+
467471
f() = ccall((:clock, "libc"), Int32, ())
468472
# See that the method gets compiled
469473
try @interpret f()

0 commit comments

Comments
 (0)