end
redef class ICodeBuilder
- # IRoutine currently inlining
- # Used to avoid recursive inlining
- var _current_inlining: Array[IRoutine] = new Array[IRoutine]
-
- # Return false if routine can be saflely inlined
- fun is_currently_inlining_routine(routine: IRoutine): Bool
- do
- return routine == iroutine or _current_inlining.has(routine)
- end
-
# Inline an iroutine in the current icode sequence
- # Require not is_currently_inlining
+ # Require that routine != self.iroutine
fun inline_routine(routine: IRoutine, args: Sequence[IRegister], closdefs: nullable Sequence[nullable IClosureDef]): nullable IRegister
do
- assert not is_currently_inlining_routine(routine)
- _current_inlining.add(routine)
+ assert routine != self.iroutine
var d = new ICodeDupContext(self)
assert args.length == routine.params.length
var closdecls = routine.closure_decls
# Process inlining
routine.body.dup_with(d)
- _current_inlining.pop
return res
end
end
end
# Return a correct bunch of registers
- fun dup_iregs(regs: Sequence[IRegister]): Sequence[IRegister]
+ fun dup_iregs(regs: Sequence[IRegister]): Array[IRegister]
do
var a = new Array[IRegister].with_capacity(regs.length)
for r in regs do
var c = inner_dup_with(d)
if self isa ICodeN then
assert c isa ICodeN
- c.closure_defs = closure_defs
+ var cdecl = closure_defs
+ if cdecl != null then
+ # Duplicate the colsure definitions
+ var cdecl2 = new Array[nullable IClosureDef].with_capacity(cdecl.length)
+ for cd in cdecl do
+ if cd == null then
+ cdecl2.add(null)
+ else
+ var r = cd.result
+ if r != null then r = d.dup_ireg(r)
+ var cd2 = new IClosureDef(d.dup_iregs(cd.params), r)
+ cdecl2.add(cd2)
+ cd.body.dup_seq_to(d, cd2.body)
+ end
+ end
+ c.closure_defs = cdecl2
+ end
end
var r = result
if r != null then c.result = d.dup_ireg(r)
redef class IClosCall
redef fun dup_with(d)
do
- var closdef = d._closures[closure_decl]
- if closdef == null then
- # Default is already guarded and inlined
- return
- end
- # Break sequence cannot be inlined :/
- assert break_seq == null
- var res = d._icb.inline_routine(closdef, d.dup_iregs(exprs), null)
- if result != null then
- assert res != null
- d._icb.stmt(new IMove(d.dup_ireg(result.as(not null)), res))
+ if d._closures.has_key(closure_decl) then
+ # The icloscall need to be replaced with an inlined closdef
+ var closdef = d._closures[closure_decl]
+ if closdef == null then
+ # Default is already guarded and inlined
+ return
+ end
+ # Break sequence cannot be inlined :/
+ assert break_seq == null
+ # Inline the closdef
+ var res = d._icb.inline_routine(closdef, d.dup_iregs(exprs), null)
+ if result != null then
+ assert res != null
+ d._icb.stmt(new IMove(d.dup_ireg(result.as(not null)), res))
+ end
+ else
+ # Standard icloscall duplication
+ super
end
end
+
+ redef fun inner_dup_with(d)
+ do
+ return new IClosCall(closure_decl, exprs)
+ end
end
redef class INative
redef fun inner_dup_with(d)
do
- var c2 = new INative(code, d.dup_iregs(exprs))
+ var c2 = new INative(method, d.dup_iregs(exprs))
c2.is_pure = is_pure
return c2
end
end
+redef class IIntValue
+ redef fun inner_dup_with(d)
+ do
+ return new IIntValue(value)
+ end
+end
+
+redef class IBoolValue
+ redef fun inner_dup_with(d)
+ do
+ return new IBoolValue(value)
+ end
+end
+
+redef class IStringValue
+ redef fun inner_dup_with(d)
+ do
+ return new IStringValue(value)
+ end
+end
+
+redef class IFloatValue
+ redef fun inner_dup_with(d)
+ do
+ return new IFloatValue(value)
+ end
+end
+
+redef class ICharValue
+ redef fun inner_dup_with(d)
+ do
+ return new ICharValue(value)
+ end
+end
+
redef class IMove
redef fun inner_dup_with(d)
do
redef class ITypeCheck
redef fun inner_dup_with(d)
do
- return new ITypeCheck(d.dup_ireg(expr), stype)
+ return new ITypeCheck(d.dup_ireg(expr1), d.dup_ireg(expr2), stype)
end
end
redef class IHasClos
redef fun inner_dup_with(d)
do
- var closdef = d._closures[closure_decl]
- var res: IRegister
- if closdef != null then
- res = d._icb.lit_true_reg
+ if d._closures.has_key(closure_decl) then
+ # closdef will be inlined
+ var closdef = d._closures[closure_decl]
+ var res: IRegister
+ if closdef != null then
+ res = d._icb.lit_true_reg
+ else
+ res = d._icb.lit_false_reg
+ end
+ return new IMove(d.dup_ireg(result.as(not null)), res)
else
- res = d._icb.lit_false_reg
+ return new IHasClos(closure_decl)
end
- return new IMove(d.dup_ireg(result.as(not null)), res)
end
end