[pypy-svn] r36419 - pypy/branch/i386-regalloc/pypy/jit/codegen/i386

arigo at codespeak.net arigo at codespeak.net
Wed Jan 10 18:49:09 CET 2007


Author: arigo
Date: Wed Jan 10 18:49:07 2007
New Revision: 36419

Modified:
   pypy/branch/i386-regalloc/pypy/jit/codegen/i386/conftest.py
   pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py
   pypy/branch/i386-regalloc/pypy/jit/codegen/i386/ri386.py
Log:
Intermediate check-in before I change many things again (because the
current approach doesn't work).



Modified: pypy/branch/i386-regalloc/pypy/jit/codegen/i386/conftest.py
==============================================================================
--- pypy/branch/i386-regalloc/pypy/jit/codegen/i386/conftest.py	(original)
+++ pypy/branch/i386-regalloc/pypy/jit/codegen/i386/conftest.py	Wed Jan 10 18:49:07 2007
@@ -14,3 +14,11 @@
                 py.test.skip('detected a %r CPU' % (processor,))
 
         return super(Directory, self).run()
+
+Option = py.test.Config.Option
+
+option = py.test.Config.addoptions("ppc options",
+        Option('--trap', action="store_true", default=False,
+               dest="trap",
+               help=""),
+        )

Modified: pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py
==============================================================================
--- pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py	(original)
+++ pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py	Wed Jan 10 18:49:07 2007
@@ -2,8 +2,8 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder
 from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch
-from pypy.jit.codegen.i386 import ri386
-from pypy.jit.codegen.i386.ri386 import I386CodeBuilder
+from pypy.jit.codegen.i386.ri386 import *
+from pypy.jit.codegen.i386 import conftest
 
 
 WORD = 4    # bytes
@@ -49,15 +49,70 @@
     opname = 'int_sub'
     emit = staticmethod(I386CodeBuilder.SUB)
 
-
-class InputVar(GenVar):
-    def __init__(self, operand):
-        self.operand = operand
+# ____________________________________________________________
 
 class IntConst(GenConst):
+
     def __init__(self, value):
         self.value = value
 
+    def operand(self, builder):
+        return imm(self.value)
+
+    def nonimmoperand(self, builder, tmpregister):
+        builder.mc.MOV(tmpregister, self.operand(builder))
+        return tmpregister
+
+    @specialize.arg(1)
+    def revealconst(self, T):
+        if isinstance(T, lltype.Ptr):
+            return lltype.cast_int_to_ptr(T, self.value)
+        elif T is llmemory.Address:
+            return llmemory.cast_int_to_adr(self.value)
+        else:
+            return lltype.cast_primitive(T, self.value)
+
+    def __repr__(self):
+        "NOT_RPYTHON"
+        try:
+            return "const=%s" % (imm(self.value).assembler(),)
+        except TypeError:   # from Symbolics
+            return "const=%r" % (self.value,)
+
+    def repr(self):
+        return "const=$%s" % (self.value,)
+
+class AddrConst(GenConst):
+
+    def __init__(self, addr):
+        self.addr = addr
+
+    def operand(self, builder):
+        return imm(llmemory.cast_adr_to_int(self.addr))
+
+    def nonimmoperand(self, builder, tmpregister):
+        builder.mc.MOV(tmpregister, self.operand(builder))
+        return tmpregister
+
+    @specialize.arg(1)
+    def revealconst(self, T):
+        if T is llmemory.Address:
+            return self.addr
+        elif isinstance(T, lltype.Ptr):
+            return llmemory.cast_adr_to_ptr(self.addr, T)
+        elif T is lltype.Signed:
+            return llmemory.cast_adr_to_int(self.addr)
+        else:
+            assert 0, "XXX not implemented"
+
+    def __repr__(self):
+        "NOT_RPYTHON"
+        return "const=%r" % (self.addr,)
+
+    def repr(self):
+        return "const=<0x%x>" % (llmemory.cast_adr_to_int(self.addr),)
+
+# ____________________________________________________________
 
 def setup_opclasses(base):
     d = {}
@@ -73,38 +128,39 @@
 
 
 class RegAllocator(object):
-    AVAILABLE_REGS = [ri386.eax, ri386.ecx, ri386.edx,
-                      ri386.ebx, ri386.esi, ri386.edi]
-    AVAILABLE_REGS.reverse()
+    AVAILABLE_REGS = [eax, ecx, edx, ebx, esi, edi]
+    AVAILABLE_REGS_REV = AVAILABLE_REGS[:]
+    AVAILABLE_REGS_REV.reverse()
 
-    def __init__(self, operations):
+    def __init__(self, operations, input_var2loc):
         self.operations = operations
+        self.input_var2loc = input_var2loc
         self.var2loc = {}
 
-    def set_final(self, final_vars, final_locs):
+    def set_final(self, final_vars_gv, final_locs):
         used = {}
-        for i in range(len(final_vars)):
-            v = final_vars[i]
+        for i in range(len(final_vars_gv)):
+            v = final_vars_gv[i]
             loc = final_locs[i]
             if v.is_const or v in self.var2loc or (
-                isinstance(v, InputVar) and v.operand != loc):
+                self.input_var2loc.get(v, loc) != loc):
                 v = OpSameAs(v)
                 self.operations.append(v)
             self.var2loc[v] = loc
             used[loc] = True
-        self.available_regs = [reg for reg in self.AVAILABLE_REGS
+        self.available_regs = [reg for reg in self.AVAILABLE_REGS_REV
                                    if reg not in used]
 
     def creating(self, v):
         loc = self.var2loc.get(v, None)
-        if isinstance(loc, ri386.REG):
+        if isinstance(loc, REG):
             self.available_regs.append(loc)
 
     def using(self, v):
         if not v.is_const and v not in self.var2loc:
-            if isinstance(v, InputVar):
-                loc = v.operand
-            else:
+            try:
+                loc = self.input_var2loc[v]
+            except KeyError:
                 try:
                     loc = self.available_regs.pop()
                 except IndexError:
@@ -114,7 +170,7 @@
 
     def get_location(self, gv_source):
         if isinstance(gv_source, IntConst):
-            return ri386.imm(gv_source.value)
+            return imm(gv_source.value)
         else:
             return self.var2loc[gv_source]
 
@@ -125,39 +181,106 @@
 
 
 class Builder(GenBuilder):
+    coming_from = 0
 
-    def __init__(self, rgenop, inputargs_gv):
+    def __init__(self, rgenop, input_vars_gv, input_var2loc):
         self.rgenop = rgenop
-        self.inputargs_gv = inputargs_gv
+        self.input_vars_gv = input_vars_gv
+        self.input_var2loc = input_var2loc
 
     def start_writing(self):
         self.operations = []
 
-    def generate_block_code(self, final_vars, final_locs):
-        allocator = RegAllocator(self.operations)
-        allocator.set_final(final_vars, final_locs)
+    def generate_block_code(self, final_vars_gv, final_locs):
+        operations = self.operations
+        allocator = RegAllocator(operations, self.input_var2loc)
+        allocator.set_final(final_vars_gv, final_locs)
         for i in range(len(operations)-1, -1, -1):
             v = operations[i]
             allocator.creating(v)
             v.allocate_registers(allocator)
-        allocator.mc = self.rgenop.open_mc()
+        mc = self.start_mc()
+        allocator.mc = mc
         for op in operations:
             op.generate(allocator)
+        self.operations = None
+        return mc
+
+    def enter_next_block(self, kinds, args_gv):
+        locs = {}
+        seen_regs = 0
+        for v in args_gv:
+            loc = self.input_var2loc.get(v, None)
+            locs[v] = loc
+            if isinstance(loc, REG):
+                i = loc.op
+                seen_regs |= 1 << i
+        i = 0
+        final_locs = []
+        final_var2loc = {}
+        for v in args_gv:
+            loc = locs[v]
+            if loc is None:
+                while seen_regs & (1 << i):
+                    i += 1
+                assert i < len(RegAllocator.AVAILABLE_REGS)   # XXX
+                loc = RegAllocator.AVAILABLE_REGS[i]
+                i += 1
+            final_locs.append(loc)
+            final_var2loc[v] = loc
+        mc = self.generate_block_code(args_gv, final_locs)
+        self.set_coming_from(mc)
+        self.rgenop.close_mc(mc)
+        self.input_args_gv = args_gv
+        self.input_var2loc = final_var2loc
+        self.start_writing()
+
+    def set_coming_from(self, mc, insn=I386CodeBuilder.JMP):
+        self.coming_from_insn = insn
+        self.coming_from = mc.tell()
+        insn(mc, rel32(0))
+
+    def start_mc(self):
+        mc = self.rgenop.open_mc()
+        # update the coming_from instruction
+        start = self.coming_from
+        if start:
+            targetaddr = mc.tell()
+            end = start + 6    # XXX hard-coded, enough for JMP and Jcond
+            oldmc = self.rgenop.InMemoryCodeBuilder(start, end)
+            insn = self.coming_from_insn
+            insn(oldmc, rel32(targetaddr))
+            oldmc.done()
+            self.coming_from = 0
+        return mc
 
     def finish_and_return(self, sigtoken, gv_returnvar):
-        mc = self.generate_block_code([gv_returnvar], [ri386.eax])
+        mc = self.generate_block_code([gv_returnvar], [eax])
+        # --- epilogue ---
+        mc.POP(edi)
+        mc.POP(esi)
+        mc.POP(ebx)
+        mc.POP(ebp)
         mc.RET()
-        self.close_mc(mc)
+        # ----------------
+        self.rgenop.close_mc(mc)
+
+    def end(self):
+        pass
 
     @specialize.arg(1)
     def genop1(self, opname, gv_arg):
         cls = OPCLASSES1[opname]
-        return cls(gv_arg)
+        op = cls(gv_arg)
+        self.operations.append(op)
+        return op
 
     @specialize.arg(1)
     def genop2(self, opname, gv_arg1, gv_arg2):
         cls = OPCLASSES2[opname]
-        return cls(gv_arg1, gv_arg2)
+        op = cls(gv_arg1, gv_arg2)
+        self.operations.append(op)
+        return op
 
 
 class RI386GenOp(AbstractRGenOp):
@@ -190,19 +313,33 @@
         assert len(self.mcs) == self.total_code_blocks
 
     def newgraph(self, sigtoken, name):
+        # --- prologue ---
+        mc = self.open_mc()
+        entrypoint = mc.tell()
+        if conftest.option.trap:
+            mc.BREAKPOINT()
+        mc.PUSH(ebp)
+        mc.MOV(ebp, esp)
+        mc.PUSH(ebx)
+        mc.PUSH(esi)
+        mc.PUSH(edi)
+        self.close_mc(mc)
+        # NB. a bit of a hack: the first generated block of the function
+        # will immediately follow, by construction
+        # ----------------
         numargs = sigtoken     # for now
-        inputargs_gv = [InputVar(ri386.mem(ri386.EBP, WORD * (2+i)))
-                        for i in range(numargs)]
-        builder = Builder(self, inputargs_gv)
+        inputargs_gv = []
+        input_var2loc = {}
+        for i in range(numargs):
+            v = GenVar()
+            inputargs_gv.append(v)
+            input_var2loc[v] = mem(ebp, WORD * (2+i))
+        builder = Builder(self, inputargs_gv, input_var2loc)
         builder.start_writing()
-        builder.operations.append(prologue)
-        builder.generate_block_code(
-        ...
-        entrypoint = builder.mc.tell()
         return builder, IntConst(entrypoint), inputargs_gv
 
-    def replay(self, label, kinds):
-        return ReplayBuilder(self), [dummy_var] * len(kinds)
+##    def replay(self, label, kinds):
+##        return ReplayBuilder(self), [dummy_var] * len(kinds)
 
     @specialize.genconst(1)
     def genconst(self, llvalue):

Modified: pypy/branch/i386-regalloc/pypy/jit/codegen/i386/ri386.py
==============================================================================
--- pypy/branch/i386-regalloc/pypy/jit/codegen/i386/ri386.py	(original)
+++ pypy/branch/i386-regalloc/pypy/jit/codegen/i386/ri386.py	Wed Jan 10 18:49:07 2007
@@ -6,11 +6,15 @@
 
 class REG(OPERAND):
     width = 4
+    def __repr__(self):
+        return '<%s>' % self.__class__.__name__.lower()
     def assembler(self):
         return '%' + self.__class__.__name__.lower()
 
 class REG8(OPERAND):
     width = 1
+    def __repr__(self):
+        return '<%s>' % self.__class__.__name__.lower()
     def assembler(self):
         return '%' + self.__class__.__name__.lower()
 



More information about the Pypy-commit mailing list