Skip to content

Commit b8a925e

Browse files
author
William Moses
committed
fix
1 parent 3b78329 commit b8a925e

File tree

1 file changed

+204
-6
lines changed

1 file changed

+204
-6
lines changed

src/utils.jl

Lines changed: 204 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,168 @@ macro LineInfoNode(method)
4545
end
4646

4747

48+
function rewrite_inst(inst)
49+
@show inst
50+
if Meta.isexpr(inst, :call)
51+
rep = Expr(:call, call_with_reactant, inst.args...)
52+
@show rep
53+
return rep
54+
end
55+
if Meta.isexpr(inst, :invoke)
56+
return Expr(:call, inst.args[2:end]...)
57+
end
58+
return inst
59+
end
60+
4861
const REDUB_ARGUMENTS_NAME = gensym("redub_arguments")
4962

50-
function call_with_reactant_generator(world::UInt, source::LineNumberNode, self, @nospecialize(args))
63+
function arg_partially_inline!(code::Vector{Any}, slot_replacements::Vector{Any},
64+
@nospecialize(type_signature)#=::Type{<:Tuple}=#,
65+
static_param_values::Vector{Any},
66+
slot_offset::Int, arg_offset::Int, statement_offset::Int,
67+
boundscheck::Symbol)
68+
for i = 1:length(code)
69+
isassigned(code, i) || continue
70+
code[i] = _arg_partially_inline!(code[i], slot_replacements, type_signature,
71+
static_param_values, slot_offset, arg_offset,
72+
statement_offset, boundscheck)
73+
end
74+
return code
75+
end
76+
77+
function _arg_partially_inline!(@nospecialize(x), slot_replacements::Vector{Any},
78+
@nospecialize(type_signature), static_param_values::Vector{Any},
79+
slot_offset::Int, arg_offset::Int, statement_offset::Int,
80+
boundscheck::Symbol)
81+
if isa(x, Core.SSAValue)
82+
return Core.SSAValue(x.id + statement_offset)
83+
end
84+
if isa(x, Core.GotoNode)
85+
return Core.GotoNode(x.label + statement_offset)
86+
end
87+
if isa(x, Core.SlotNumber)
88+
id = x.id
89+
if 1 <= id <= length(slot_replacements)
90+
return slot_replacements[id]
91+
end
92+
return Core.SlotNumber(id + slot_offset)
93+
end
94+
if isa(x, Core.Argument)
95+
return Core.SlotNumber(x.n + arg_offset)
96+
end
97+
if isa(x, Core.NewvarNode)
98+
return Core.NewvarNode(_arg_partially_inline!(x.slot, slot_replacements, type_signature,
99+
static_param_values, slot_offset, arg_offset,
100+
statement_offset, boundscheck))
101+
end
102+
if isa(x, Core.PhiNode)
103+
arg_partially_inline!(x.values, slot_replacements, type_signature, static_param_values,
104+
slot_offset, arg_offset, statement_offset, boundscheck)
105+
x.edges .+= slot_offset
106+
return x
107+
end
108+
if isa(x, Core.ReturnNode)
109+
return Core.ReturnNode(
110+
_arg_partially_inline!(x.val, slot_replacements, type_signature, static_param_values,
111+
slot_offset, arg_offset, statement_offset, boundscheck),
112+
)
113+
end
114+
if isa(x, Core.GotoIfNot)
115+
return Core.GotoIfNot(
116+
_arg_partially_inline!(x.cond, slot_replacements, type_signature, static_param_values,
117+
slot_offset, arg_offset, statement_offset, boundscheck),
118+
x.dest + statement_offset,
119+
)
120+
end
121+
if isdefined(Core, :EnterNode) && isa(x, Core.EnterNode)
122+
return Core.EnterNode(x, x.catch_dest + statement_offset)
123+
end
124+
if isa(x, Expr)
125+
head = x.head
126+
if head === :static_parameter
127+
if isassigned(static_param_values, x.args[1])
128+
return QuoteNode(static_param_values[x.args[1]])
129+
end
130+
return x
131+
elseif head === :cfunction
132+
@assert !isa(type_signature, UnionAll) || !isempty(spvals)
133+
if !isa(x.args[2], QuoteNode) # very common no-op
134+
x.args[2] = Core.Compiler._partially_inline!(x.args[2], slot_replacements, type_signature,
135+
static_param_values, slot_offset, arg_offset,
136+
statement_offset, boundscheck)
137+
end
138+
x.args[3] = Core.Compiler._instantiate_type_in_env(x.args[3], type_signature, static_param_values)
139+
x.args[4] = Core.svec(Any[Core.Compiler._instantiate_type_in_env(argt, type_signature, static_param_values) for argt in x.args[4]]...)
140+
elseif head === :foreigncall
141+
@assert !isa(type_signature, UnionAll) || !isempty(static_param_values)
142+
for i = 1:length(x.args)
143+
if i == 2
144+
x.args[2] = Core.Compiler._instantiate_type_in_env(x.args[2], type_signature, static_param_values)
145+
elseif i == 3
146+
x.args[3] = Core.svec(Any[Core.Compiler._instantiate_type_in_env(argt, type_signature, static_param_values) for argt in x.args[3]]...)
147+
elseif i == 4
148+
@assert isa(x.args[4], Int)
149+
elseif i == 5
150+
@assert isa((x.args[5]::QuoteNode).value, Union{Symbol, Tuple{Symbol, UInt8}})
151+
else
152+
x.args[i] = _arg_partially_inline!(x.args[i], slot_replacements,
153+
type_signature, static_param_values,
154+
slot_offset, statement_offset, arg_offset,
155+
boundscheck)
156+
end
157+
end
158+
elseif head === :boundscheck
159+
if boundscheck === :propagate
160+
return x
161+
elseif boundscheck === :off
162+
return false
163+
else
164+
return true
165+
end
166+
elseif head === :gotoifnot
167+
x.args[1] = _arg_partially_inline!(x.args[1], slot_replacements, type_signature,
168+
static_param_values, slot_offset, arg_offset,
169+
statement_offset, boundscheck)
170+
x.args[2] += statement_offset
171+
elseif head === :isdefined
172+
arg = x.args[1]
173+
# inlining a QuoteNode or literal into `Expr(:isdefined, x)` is invalid, replace with true
174+
if isa(arg, Core.SlotNumber)
175+
id = arg.id
176+
if 1 <= id <= length(slot_replacements)
177+
replacement = slot_replacements[id]
178+
if isa(replacement, Union{Core.SlotNumber, GlobalRef, Symbol})
179+
return Expr(:isdefined, replacement)
180+
else
181+
@assert !isa(replacement, Expr)
182+
return true
183+
end
184+
end
185+
return Expr(:isdefined, Core.SlotNumber(id + slot_offset))
186+
elseif isexpr(arg, :static_parameter)
187+
if isassigned(static_param_values, arg.args[1])
188+
return true
189+
end
190+
return x
191+
else
192+
@assert isa(arg, Union{GlobalRef, Symbol})
193+
return x
194+
end
195+
elseif !Core.Compiler.is_meta_expr_head(head)
196+
arg_partially_inline!(x.args, slot_replacements, type_signature, static_param_values,
197+
slot_offset, arg_offset, statement_offset, boundscheck)
198+
end
199+
end
200+
return x
201+
end
202+
203+
function call_with_reactant_generator(world::UInt, source::LineNumberNode, self, @nospecialize(redub_arguments))
51204
@nospecialize
52205

206+
args = redub_arguments
53207
@show args
54208

55-
stub = Core.GeneratedFunctionStub(identity, Core.svec(:call_with_reactant, REDUB_ARGUMENTS_NAME), Core.svec())
209+
stub = Core.GeneratedFunctionStub(identity, Core.svec(:call_with_reactant, :redub_arguments), Core.svec())
56210

57211
# look up the method match
58212
builtin_error = :(throw(AssertionError("Unsupported call_with_reactant of builtin $args")))
@@ -85,7 +239,40 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
85239
(Any, Any, Any), match.method, match.spec_types, match.sparams)
86240

87241
result = Core.Compiler.InferenceResult(mi, Core.Compiler.typeinf_lattice(interp))
88-
src = Core.Compiler.retrieve_code_info(mi, world)
242+
@static if true
243+
frame = Core.Compiler.InferenceState(result, #=cache_mode=#:local, interp)
244+
@assert frame !== nothing
245+
Core.Compiler.typeinf(interp, frame)
246+
@assert Core.Compiler.is_inferred(frame)
247+
248+
#if Core.Compiler.result_is_constabi(interp, frame.result)
249+
# rt = frame.result.result::Core.Compiler.Const
250+
# src = Core.Compiler.codeinfo_for_const(interp, frame.linfo, rt.val)
251+
#else
252+
opt = Core.Compiler.OptimizationState(frame, interp)
253+
254+
caller = frame.result
255+
@static if VERSION < v"1.11-"
256+
ir = Core.Compiler.run_passes(opt.src, opt, caller)
257+
else
258+
ir = Core.Compiler.run_passes_ipo_safe(opt.src, opt, caller)
259+
Core.Compiler.ipo_dataflow_analysis!(interp, opt, ir, caller)
260+
end
261+
262+
for (i, inst) in enumerate(ir.stmts)
263+
@static if VERSION < v"1.11"
264+
Core.Compiler.setindex!(ir.stmts[i], rewrite_inst(inst[:inst]), :inst)
265+
else
266+
Core.Compiler.setindex!(ir.stmts[i], rewrite_inst(inst[:stmt]), :stmt)
267+
end
268+
end
269+
Core.Compiler.finish(interp, opt, ir, caller)
270+
271+
src = Core.Compiler.ir_to_codeinf!(opt)
272+
#end
273+
else
274+
src = Core.Compiler.retrieve_code_info(mi, world)
275+
end
89276

90277
# prepare a new code info
91278
code_info = copy(src)
@@ -99,7 +286,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
99286
code_info.min_world = lookup_result.valid_worlds.min_world
100287
code_info.max_world = lookup_result.valid_worlds.max_world
101288

102-
code_info.slotnames = Any[:call_with_reactant, REDUB_ARGUMENTS_NAME, code_info.slotnames...]
289+
code_info.slotnames = Any[:call_with_reactant, :redub_arguments, code_info.slotnames...]
103290
code_info.slotflags = UInt8[0x00, 0x00, code_info.slotflags...]
104291
#code_info.slotnames = Any[:call_with_reactant, REDUB_ARGUMENTS_NAME] #code_info.slotnames...]
105292
#code_info.slotflags = UInt8[0x00, 0x00] # code_info.slotflags...]
@@ -163,8 +350,13 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
163350
@show code_info.code
164351

165352
@show n_prepended_slots
353+
@static if false
166354
Base.Meta.partially_inline!(code_info.code, fn_args, method.sig, Any[static_params...],
167355
n_prepended_slots, length(overdubbed_code), :propagate)
356+
else
357+
arg_partially_inline!(code_info.code, fn_args, method.sig, Any[static_params...],
358+
n_prepended_slots, n_prepended_slots, length(overdubbed_code), :propagate)
359+
end
168360
@show code_info.code
169361

170362
#callexpr = Expr(:call, Core.OpaqueClosure(ir), fn_args...)
@@ -181,6 +373,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
181373

182374
@show overdubbed_code
183375

376+
@static if false
184377
for i in eachindex(overdubbed_code)
185378
prev = overdubbed_code[i]
186379
if Base.Meta.isexpr(prev, :call)
@@ -193,6 +386,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
193386
end
194387
end
195388
end
389+
end
196390

197391
#=== set `code_info`/`reflection` fields accordingly ===#
198392

@@ -204,9 +398,12 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
204398
code_info.codelocs = overdubbed_codelocs
205399
code_info.ssavaluetypes = length(overdubbed_code)
206400
code_info.ssaflags = [0x00 for _ in 1:length(overdubbed_code)] # XXX we need to copy flags that are set for the original code
207-
self_result = Core.Compiler.InferenceResult(self_mi, Core.Compiler.typeinf_lattice(interp))
208401

209402
@show code_info
403+
return code_info
404+
405+
self_result = Core.Compiler.InferenceResult(self_mi, Core.Compiler.typeinf_lattice(interp))
406+
210407

211408
@show self
212409
self_meths = Base._methods_by_ftype(Tuple{self, Vararg{Any}}, -1, world)
@@ -241,6 +438,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
241438
else
242439
ir = Core.Compiler.run_passes_ipo_safe(ir, opt, caller)
243440
Core.Compiler.ipo_dataflow_analysis!(interp, opt, ir, caller)
441+
244442
end
245443
Core.Compiler.finish(interp, opt, ir, caller)
246444

@@ -255,7 +453,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
255453
return src
256454
end
257455

258-
@eval function call_with_reactant($REDUB_ARGUMENTS_NAME...)
456+
@eval function call_with_reactant(redub_arguments...)
259457
$(Expr(:meta, :generated_only))
260458
$(Expr(:meta, :generated, call_with_reactant_generator))
261459
end

0 commit comments

Comments
 (0)