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

arigo at codespeak.net arigo at codespeak.net
Thu Jan 11 14:27:19 CET 2007


Author: arigo
Date: Thu Jan 11 14:27:16 2007
New Revision: 36478

Modified:
   pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py
   pypy/branch/i386-regalloc/pypy/jit/codegen/i386/ri386.py
Log:
- spill registers on the frame stack.
- start some support for int_gt.


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	Thu Jan 11 14:27:16 2007
@@ -27,6 +27,7 @@
             return    # simple operation whose result is not used anyway
         op = allocator.load_location_with(loc, self.x)
         self.emit(allocator.mc, op)
+        allocator.store_back_location(loc, op)
 
 class OpSameAs(Op1):
     emit = staticmethod(lambda mc, x: None)
@@ -46,6 +47,7 @@
         op1 = allocator.load_location_with(loc, self.x)
         op2 = allocator.get_operand(self.y)
         self.emit(allocator.mc, op1, op2)
+        allocator.store_back_location(loc, op1)
 
 class OpIntAdd(Op2):
     opname = 'int_add'
@@ -55,6 +57,29 @@
     opname = 'int_sub'
     emit = staticmethod(I386CodeBuilder.SUB)
 
+class OpIntGt(Op2):
+    opname = 'int_gt'
+    @staticmethod
+    def emit(mc, x, y):
+        mc.CMP(x, y)
+        mc.SETG(cl)
+        mc.MOVZX(x, cl)
+
+class JumpIfFalse(Operation):
+    def __init__(self, gv_condition, targetbuilder):
+        self.gv_condition = gv_condition
+        self.targetbuilder = targetbuilder
+    def allocate_registers(self, allocator):
+        allocator.using(self.gv_condition)
+    def generate(self, allocator):
+        op = allocator.get_operand(self.gv_condition)
+        mc = allocator.mc
+        mc.CMP(op, imm8(0))
+        targetbuilder = self.targetbuilder
+        targetbuilder.set_coming_from(mc, insn=I386CodeBuilder.JE)
+        targetbuilder.inputoperands = [allocator.get_operand(gv)
+                                       for gv in targetbuilder.inputargs_gv]
+
 # ____________________________________________________________
 
 class IntConst(GenConst):
@@ -135,12 +160,27 @@
 OPCLASSES1['int_is_true'] = None
 
 
-class OutOfRegisters(Exception):
-    pass
+class StackOpCache:
+    INITIAL_STACK_EBP_OFS = -4
+stack_op_cache = StackOpCache()
+stack_op_cache.lst = []
+
+def stack_op(n):
+    "Return the mem operand that designates the nth stack-spilled location"
+    assert n >= 0
+    lst = stack_op_cache.lst
+    while len(lst) <= n:
+        ofs = WORD * (StackOpCache.INITIAL_STACK_EBP_OFS - len(lst))
+        lst.append(mem(ebp, ofs))
+    return lst[n]
+
+def stack_n_from_op(op):
+    ofs = op.ofs_relative_to_ebp()
+    return StackOpCache.INITIAL_STACK_EBP_OFS - ofs / WORD
 
 
 class RegAllocator(object):
-    AVAILABLE_REGS = [eax, ecx, edx, ebx, esi, edi]
+    AVAILABLE_REGS = [eax, edx, ebx, esi, edi]   # XXX ecx reserved for stuff
 
     # 'gv' -- GenVars, used as arguments and results of operations
     #
@@ -212,24 +252,33 @@
         force_loc2operand = self.force_loc2operand
         operands = []
         seen_regs = 0
+        seen_stackn = {}
         for op in force_loc2operand.values():
             if isinstance(op, REG):
                 seen_regs |= 1 << op.op
+            elif isinstance(op, MODRM):
+                seen_stackn[stack_n_from_op(op)] = None
         i = 0
+        stackn = 0
         for loc in range(self.nextloc):
             try:
                 operand = force_loc2operand[loc]
             except KeyError:
                 # grab the next free register
-                while seen_regs & (1 << i):
-                    i += 1
                 try:
-                    operand = RegAllocator.AVAILABLE_REGS[i]
-                    i += 1
+                    while True:
+                        operand = RegAllocator.AVAILABLE_REGS[i]
+                        i += 1
+                        if not (seen_regs & (1 << operand.op)):
+                            break
                 except IndexError:
-                    raise OutOfRegisters
+                    while stackn in seen_stackn:
+                        stackn += 1
+                    operand = stack_op(stackn)
+                    stackn += 1
             operands.append(operand)
         self.operands = operands
+        self.required_frame_depth = stackn
 
     def get_operand(self, gv_source):
         if isinstance(gv_source, IntConst):
@@ -240,14 +289,30 @@
 
     def load_location_with(self, loc, gv_source):
         dstop = self.operands[loc]
+        if not isinstance(dstop, REG):
+            dstop = ecx
         srcop = self.get_operand(gv_source)
         if srcop != dstop:
             self.mc.MOV(dstop, srcop)
         return dstop
 
+    def store_back_location(self, loc, operand):
+        dstop = self.operands[loc]
+        if operand != dstop:
+            self.mc.MOV(dstop, operand)
+
     def generate_initial_moves(self):
-        # XXX naive algo for now
         initial_moves = self.initial_moves
+        # first make sure that the reserved stack frame is big enough
+        last_n = self.required_frame_depth - 1
+        for loc, srcoperand in initial_moves:
+            if isinstance(srcoperand, MODRM):
+                n = stack_n_from_op(srcoperand)
+                if last_n < n:
+                    last_n = n
+        if last_n >= 0:
+            self.mc.LEA(esp, stack_op(last_n))
+        # XXX naive algo for now
         for loc, srcoperand in initial_moves:
             self.mc.PUSH(srcoperand)
         initial_moves.reverse()
@@ -273,7 +338,6 @@
         allocator.allocate_locations(self.operations)
         allocator.force_var_operands(force_vars, force_operands,
                                      at_start=False)
-        #import pdb; pdb.set_trace()
         allocator.force_var_operands(self.inputargs_gv, self.inputoperands,
                                      at_start=True)
         allocator.allocate_registers()
@@ -284,33 +348,10 @@
             op.generate(allocator)
         self.operations = None
         self.inputargs_gv = [GenVar() for v in final_vars_gv]
-        self.inputoperands = [allocator.operands[allocator.var2loc[v]]
-                              for v in final_vars_gv]
+        self.inputoperands = [allocator.get_operand(v) for v in final_vars_gv]
         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)
         args_gv[:] = self.inputargs_gv
         self.set_coming_from(mc)
@@ -336,9 +377,15 @@
             self.coming_from = 0
         return mc
 
+    def jump_if_false(self, gv_condition, args_for_jump_gv):
+        newbuilder = Builder(self.rgenop, list(args_for_jump_gv), None)
+        self.operations.append(JumpIfFalse(gv_condition, newbuilder))
+        return newbuilder
+
     def finish_and_return(self, sigtoken, gv_returnvar):
         mc = self.generate_block_code([gv_returnvar], [gv_returnvar], [eax])
         # --- epilogue ---
+        mc.LEA(esp, mem(ebp, -12))
         mc.POP(edi)
         mc.POP(esi)
         mc.POP(ebx)
@@ -422,7 +469,7 @@
         #ops = [OpSameAs(v) for v in inputargs_gv]
         #builder.operations.extend(ops)
         #inputargs_gv = ops
-        return builder, IntConst(entrypoint), inputargs_gv
+        return builder, IntConst(entrypoint), inputargs_gv[:]
 
 ##    def replay(self, label, kinds):
 ##        return ReplayBuilder(self), [dummy_var] * len(kinds)

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	Thu Jan 11 14:27:16 2007
@@ -105,6 +105,23 @@
         mod = self.byte & 0xC0
         return mod == 0xC0
 
+    def ofs_relative_to_ebp(self):
+        # very custom: if self is a mem(ebp, ofs) then return ofs
+        # otherwise raise ValueError
+        mod = self.byte & 0xC0
+        rm  = self.byte & 0x07
+        if mod == 0xC0:
+            raise ValueError     # self is just a register
+        if self.byte == 0x05:
+            raise ValueError     # self is just an [immediate]
+        if rm != 5:
+            raise ValueError     # not a simple [ebp+ofs]
+        offset = self.extradata
+        if not offset:
+            return 0
+        else:
+            return unpack(offset)
+
 
 class MODRM8(MODRM):
     width = 1



More information about the Pypy-commit mailing list