icode: iroutine knows its local registers
authorJean Privat <jean@pryen.org>
Mon, 10 Aug 2009 17:14:54 +0000 (13:14 -0400)
committerJean Privat <jean@pryen.org>
Mon, 17 Aug 2009 18:56:54 +0000 (14:56 -0400)
iroutine inlining is also adapted to only duplicate local registers.

Signed-off-by: Jean Privat <jean@pryen.org>

src/icode/icode_base.nit
src/icode/icode_builder.nit
src/icode/icode_tools.nit

index 5c265e6..f15b4a0 100644 (file)
@@ -51,6 +51,9 @@ class IRoutine
        # The closure declared
        readable writable var _closure_decls: nullable Sequence[IClosureDecl] = null
 
+       # The local variables (excluding params and result)
+       readable var _registers: Set[IRegister] = new ArraySet[IRegister]
+
        # The result of the routine
        readable var _result: nullable IRegister
 
index c7cfe59..d1dd617 100644 (file)
@@ -184,7 +184,9 @@ class ICodeBuilder
        # Get a new register
        fun new_register(s: MMType): IRegister
        do
-               return new IRegister(s)
+               var r = new IRegister(s)
+               iroutine.registers.add(r)
+               return r
        end
 
        # The module where classes and types are extracted
index 349ed1a..0b48de9 100644 (file)
@@ -97,37 +97,48 @@ redef class ICodeBuilder
        do
                var d = new ICodeDupContext
                assert args.length == routine.params.length
+
+               # Fill register duplicate association
+               var dico = d._registers
+               var res = routine.result
+               if res != null then
+                       var res2 = new_register(res.stype)
+                       dico[res] = res2
+                       res = res2
+               end
+               for reg in routine.registers do
+                       assert not dico.has_key(reg)
+                       dico[reg] = new_register(reg.stype)
+               end
                for i in [0..args.length[ do
                        # FIXME The following assumes that params are readonly.
                        # The alternative is safe but add one move :/
-                       d._registers[routine.params[i]] = args[i]
-                       #seq.icodes.add(new IMove(d.dup_ireg(routine.params[i]), args[i]))
+                       dico[routine.params[i]] = args[i]
+                       #seq.icodes.add(new IMove(dico[routine.params[i]]), args[i]))
                end
+
+               # Process inlining
                seq.icodes.add(routine.body.dup_with(d))
-               var r = routine.result
-               if r != null then r = d.dup_ireg(r)
-               return r
+               return res
        end
 end
 
 # This class stores reference to allow correct duplication of icodes
 private class ICodeDupContext
-       # Duplicate one register
-       # Subsequent invocation will return the same register
+       # Return the correct register
+       # * a duplicate of the local register 'r' of the inlined iroutine
+       # * 'r' else (it is a register of the caller iroutine)
        fun dup_ireg(r: IRegister): IRegister
        do
                var rs = _registers
                if rs.has_key(r) then
                        return rs[r]
                else
-                       var r2 = new IRegister(r.stype)
-                       rs[r] = r2
-                       return r2
+                       return r
                end
        end
 
-       # Duplicate a bunch of registers
-       # Subsequent invocation will return the same registers
+       # Return a correct bunch of registers
        fun dup_iregs(regs: Sequence[IRegister]): Sequence[IRegister]
        do
                var a = new Array[IRegister].with_capacity(regs.length)