From a54761a8229931579c64421e30f67744039898ce Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 10 Feb 2019 09:49:02 -0600 Subject: [PATCH] Restore unnesting and use it in ccall. Fixes #8. --- src/JuliaInterpreter.jl | 49 ++++++++++++++++++++++------------------- test/interpret.jl | 9 ++++++++ 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/JuliaInterpreter.jl b/src/JuliaInterpreter.jl index cb28a6081333b..99d3a6f500150 100644 --- a/src/JuliaInterpreter.jl +++ b/src/JuliaInterpreter.jl @@ -391,13 +391,16 @@ function copy_codeinfo(code::CodeInfo) return newcode end -const calllike = Set([:call, :struct_type]) +const calllike = Set([:call, :foreigncall]) function extract_inner_call!(stmt, idx, once::Bool=false) isa(stmt, Expr) || return nothing once |= stmt.head ∈ calllike for (i, a) in enumerate(stmt.args) isa(a, Expr) || continue + if stmt.head == :foreigncall && i == 1 + continue + end ret = extract_inner_call!(a, idx, once) # doing this first extracts innermost calls ret !== nothing && return ret iscalllike = a.head ∈ calllike @@ -488,28 +491,28 @@ function optimize!(code::CodeInfo, mod::Module) end end - # ## Un-nest :call expressions (so that there will be only one :call per line) - # # This will allow us to re-use args-buffers rather than having to allocate new ones each time. - # old_code, old_codelocs = code.code, code.codelocs - # code.code = new_code = eltype(old_code)[] - # code.codelocs = new_codelocs = Int32[] - # ssainc = fill(1, length(old_code)) - # for (i, stmt) in enumerate(old_code) - # loc = old_codelocs[i] - # inner = extract_inner_call!(stmt, length(new_code)+1) - # while inner !== nothing - # push!(new_code, inner) - # push!(new_codelocs, loc) - # ssainc[i] += 1 - # inner = extract_inner_call!(stmt, length(new_code)+1) - # end - # push!(new_code, stmt) - # push!(new_codelocs, loc) - # end - # # Fix all the SSAValues and GotoNodes - # ssalookup = cumsum(ssainc) - # renumber_ssa!(new_code, ssalookup) - # code.ssavaluetypes = length(new_code) + ## Un-nest :call expressions (so that there will be only one :call per line) + # This will allow us to re-use args-buffers rather than having to allocate new ones each time. + old_code, old_codelocs = code.code, code.codelocs + code.code = new_code = eltype(old_code)[] + code.codelocs = new_codelocs = Int32[] + ssainc = fill(1, length(old_code)) + for (i, stmt) in enumerate(old_code) + loc = old_codelocs[i] + inner = extract_inner_call!(stmt, length(new_code)+1) + while inner !== nothing + push!(new_code, inner) + push!(new_codelocs, loc) + ssainc[i] += 1 + inner = extract_inner_call!(stmt, length(new_code)+1) + end + push!(new_code, stmt) + push!(new_codelocs, loc) + end + # Fix all the SSAValues and GotoNodes + ssalookup = cumsum(ssainc) + renumber_ssa!(new_code, ssalookup) + code.ssavaluetypes = length(new_code) return code end diff --git a/test/interpret.jl b/test/interpret.jl index 9a845e6f075b1..cf65e5dbb6578 100644 --- a/test/interpret.jl +++ b/test/interpret.jl @@ -38,3 +38,12 @@ fkw(x::Int8; y=0, z="hello") = y @test @interpret(Vararg.body.body.name) === Vararg.body.body.name frame = JuliaInterpreter.prepare_toplevel(Main, :(Vararg.body.body.name)) @test JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame, true) === Vararg.body.body.name + +ex = quote + if sizeof(JLOptions) === ccall(:jl_sizeof_jl_options, Int, ()) + else + ccall(:jl_throw, Cvoid, (Any,), "Option structure mismatch") + end +end +frame = JuliaInterpreter.prepare_toplevel(Base, ex) +JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame, true)