[pypy-svn] r36392 - pypy/dist/pypy/jit/codegen/ppc

mwh at codespeak.net mwh at codespeak.net
Wed Jan 10 00:12:49 CET 2007


Author: mwh
Date: Wed Jan 10 00:12:37 2007
New Revision: 36392

Modified:
   pypy/dist/pypy/jit/codegen/ppc/codebuf.py
   pypy/dist/pypy/jit/codegen/ppc/conftest.py
   pypy/dist/pypy/jit/codegen/ppc/instruction.py
   pypy/dist/pypy/jit/codegen/ppc/rgenop.py
Log:
(mwh, a little arigo)

After only moderately crazy amounts of head-bashing, get the ppc jit tests
running again.


Modified: pypy/dist/pypy/jit/codegen/ppc/codebuf.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/codebuf.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/codebuf.py	Wed Jan 10 00:12:37 2007
@@ -55,11 +55,11 @@
         self._pos = _pos
 
     def write(self, data):
-         p = self._pos
-         if p >= self._size:
-             raise CodeBlockOverflow
-         self._data.contents[p] = data
-         self._pos = p + 1
+        p = self._pos
+        if p >= self._size:
+            raise CodeBlockOverflow
+        self._data.contents[p] = data
+        self._pos = p + 1
 
     def getpos(self):
         return self._pos
@@ -77,6 +77,13 @@
             self.write(0)
         return r
 
+class ExistingCodeBlock(MachineCodeBlock):
+    def __init__(self, start, end):
+        self._size = (end-start)/4
+        p = c_void_p(start)
+        self._data = cast(p, POINTER(c_int * self._size))
+        self._pos = 0
+
 class OwningMachineCodeBlock(MachineCodeBlock):
     def __del__(self):
         free(cast(self._data, PTR), self._size * 4)

Modified: pypy/dist/pypy/jit/codegen/ppc/conftest.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/conftest.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/conftest.py	Wed Jan 10 00:12:37 2007
@@ -5,7 +5,6 @@
 class Directory(py.test.collect.Directory):
 
     def run(self):
-        import py; py.test.skip("in-progress")
         try:
             processor = detect_cpu.autodetect()
         except detect_cpu.ProcessorAutodetectError, e:

Modified: pypy/dist/pypy/jit/codegen/ppc/instruction.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/instruction.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/instruction.py	Wed Jan 10 00:12:37 2007
@@ -78,10 +78,10 @@
     reg_arg_regclasses is the type of register that needs to be allocated
     '''
     def __init__(self):
-        self.__magic_index = _insn_index[0]
+        self._magic_index = _insn_index[0]
         _insn_index[0] += 1
     def __repr__(self):
-        return "<%s %d>" % (self.__class__.__name__, self.__magic_index)
+        return "<%s %d>" % (self.__class__.__name__, self._magic_index)
 
 class Insn_GPR__GPR_GPR(Insn):
     def __init__(self, methptr, result, args):
@@ -98,6 +98,9 @@
         self.arg_reg1 = allocator.loc_of(self.reg_args[0])
         self.arg_reg2 = allocator.loc_of(self.reg_args[1])
 
+    def __repr__(self):
+        return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
+
     def emit(self, asm):
         self.methptr(asm,
                      self.result_reg.number,
@@ -117,6 +120,9 @@
     def allocate(self, allocator):
         self.result_reg = allocator.loc_of(self.result)
         self.arg_reg = allocator.loc_of(self.reg_args[0])
+    def __repr__(self):
+        return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
+
     def emit(self, asm):
         self.methptr(asm,
                      self.result_reg.number,
@@ -135,6 +141,9 @@
     def allocate(self, allocator):
         self.result_reg = allocator.loc_of(self.result)
         self.arg_reg = allocator.loc_of(self.reg_args[0])
+    def __repr__(self):
+        return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
+
     def emit(self, asm):
         self.methptr(asm,
                      self.result_reg.number,
@@ -152,6 +161,9 @@
         self.reg_arg_regclasses = []
     def allocate(self, allocator):
         self.result_reg = allocator.loc_of(self.result)
+    def __repr__(self):
+        return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
+
     def emit(self, asm):
         self.methptr(asm,
                      self.result_reg.number,
@@ -170,6 +182,9 @@
     def allocate(self, allocator):
         self.reg1 = allocator.loc_of(self.reg_args[0])
         self.reg2 = allocator.loc_of(self.reg_args[1])
+    def __repr__(self):
+        return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
+
     def emit(self, asm):
         self.methptr(asm,
                      self.reg1.number,
@@ -189,6 +204,9 @@
         self.reg1 = allocator.loc_of(self.reg_args[0])
         self.reg2 = allocator.loc_of(self.reg_args[1])
         self.reg3 = allocator.loc_of(self.reg_args[2])
+    def __repr__(self):
+        return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
+
     def emit(self, asm):
         self.methptr(asm,
                      self.reg1.number,
@@ -253,21 +271,33 @@
 ##         asm.mtctr(self.arg_reg.number)
 
 class Jump(Insn):
-    def __init__(self, gv_cond, gv_target, jump_if_true):
+    def __init__(self, gv_cond, targetbuilder, jump_if_true, jump_args_gv):
         Insn.__init__(self)
         self.gv_cond = gv_cond
-        self.gv_target = gv_target
         self.jump_if_true = jump_if_true
 
         self.result = None
         self.result_regclass = NO_REGISTER
-        self.reg_args = [gv_cond, gv_target]
-        self.reg_arg_regclasses = [CR_FIELD, CT_REGISTER]
+        self.reg_args = [gv_cond]
+        self.reg_arg_regclasses = [CR_FIELD]
+
+        self.jump_args_gv = jump_args_gv
+        self.targetbuilder = targetbuilder
     def allocate(self, allocator):
-        assert allocator.loc_of(self.reg_args[1]) is ctr
         self.crf = allocator.loc_of(self.reg_args[0])
         self.bit, self.negated = allocator.crfinfo[self.crf.number]
+
+        self.targetbuilder.initial_var2loc = {}
+        for gv_arg in self.jump_args_gv:
+            self.targetbuilder.initial_var2loc[gv_arg] = allocator.var2loc[gv_arg]
+        self.targetbuilder.initial_spill_offset = allocator.spill_offset
     def emit(self, asm):
+        if self.targetbuilder.start:
+            asm.load_word(rSCRATCH, self.targetbuilder.start)
+        else:
+            self.targetbuilder.patch_start_here = asm.mc.tell()
+            asm.load_word(rSCRATCH, 0)
+        asm.mtctr(rSCRATCH)
         if self.negated ^ self.jump_if_true:
             BO = 12 # jump if relavent bit is set in the CR
         else:

Modified: pypy/dist/pypy/jit/codegen/ppc/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/rgenop.py	Wed Jan 10 00:12:37 2007
@@ -182,16 +182,20 @@
 
 class Builder(GenBuilder):
 
-    def __init__(self, rgenop, mc):
+    def __init__(self, rgenop):
         self.rgenop = rgenop
         self.asm = RPPCAssembler()
-        self.asm.mc = mc
+        self.asm.mc = None
         self.insns = []
         self.stack_adj_addr = 0
         self.initial_spill_offset = 0
         self.initial_var2loc = None
-        self.fresh_from_jump = False
         self.max_param_space = -1
+        self.final_jump_addr = 0
+
+        self.start = 0
+        self.closed = True
+        self.patch_start_here = 0
 
     # ----------------------------------------------------------------
     # the public Builder interface:
@@ -318,11 +322,8 @@
 ##     def genop_debug_pdb(self):    # may take an args_gv later
 
     def enter_next_block(self, kinds, args_gv):
-        if self.fresh_from_jump:
-            var2loc = self.initial_var2loc
-            self.fresh_from_jump = False
-        else:
-            var2loc = self.allocate_and_emit().var2loc
+        vars_gv = [v for v in args_gv if isinstance(v, Var)]
+        var2loc = self.allocate_and_emit(vars_gv).var2loc
 
         #print "enter_next_block:", args_gv, var2loc
 
@@ -366,15 +367,15 @@
         self.emit_stack_adjustment()
         return Label(target_addr, arg_locations, min_stack_offset)
 
-    def jump_if_false(self, gv_condition):
-        return self._jump(gv_condition, False)
+    def jump_if_false(self, gv_condition, args_gv):
+        return self._jump(gv_condition, False, args_gv)
 
-    def jump_if_true(self, gv_condition):
-        return self._jump(gv_condition, True)
+    def jump_if_true(self, gv_condition, args_gv):
+        return self._jump(gv_condition, True, args_gv)
 
     def finish_and_return(self, sigtoken, gv_returnvar):
         self.insns.append(insn.Return(gv_returnvar))
-        self.allocate_and_emit()
+        self.allocate_and_emit([])
 
         # standard epilogue:
 
@@ -393,7 +394,7 @@
         self._close()
 
     def finish_and_goto(self, outputargs_gv, target):
-        allocator = self.allocate_and_emit()
+        allocator = self.allocate_and_emit(outputargs_gv)
         min_offset = min(allocator.spill_offset, target.min_stack_offset)
         min_offset = prepare_for_jump(
             self.asm, min_offset, outputargs_gv, allocator.var2loc, target)
@@ -403,17 +404,54 @@
         self.asm.bctr()
         self._close()
 
-    def flexswitch(self, gv_exitswitch):
+    def flexswitch(self, gv_exitswitch, args_gv):
         # make sure the exitswitch ends the block in a register:
         crresult = Var()
         self.insns.append(insn.FakeUse(crresult, gv_exitswitch))
-        allocator = self.allocate_and_emit()
+        allocator = self.allocate_and_emit(args_gv)
         switch_mc = self.asm.mc.reserve(7 * 5 + 4)
         self._close()
-        return FlexSwitch(self.rgenop, switch_mc,
-                          allocator.loc_of(gv_exitswitch),
-                          allocator.loc_of(crresult),
-                          allocator.var2loc)
+        result = FlexSwitch(self.rgenop, switch_mc,
+                            allocator.loc_of(gv_exitswitch),
+                            allocator.loc_of(crresult),
+                            allocator.var2loc)
+        return result, result.add_default()
+
+    def start_writing(self):
+        if not self.closed:
+            return self
+        assert self.asm.mc is None
+        if self.final_jump_addr != 0:
+            mc = self.rgenop.open_mc()
+            target = mc.tell()
+            self.asm.mc = codebuf.ExistingCodeBlock(self.final_jump_addr, self.final_jump_addr+8)
+            self.asm.load_word(rSCRATCH, target)
+            self.asm.mc = mc
+            self.emit_stack_adjustment()
+            return self
+        else:
+            self._open()
+            self.maybe_patch_start_here()
+            self.emit_stack_adjustment()
+            return self
+
+    def maybe_patch_start_here(self):
+        if self.patch_start_here:
+            mc = self.asm.mc
+            self.asm.mc = codebuf.ExistingCodeBlock(self.patch_start_here, self.patch_start_here+8)
+            self.asm.load_word(rSCRATCH, mc.tell())
+            self.asm.mc = mc
+            self.patch_start_here = 0
+
+    def pause_writing(self, args_gv):
+        self.allocate_and_emit(args_gv)
+        self.final_jump_addr = self.asm.mc.tell()
+        self.asm.nop()
+        self.asm.nop()
+        self.asm.mtctr(rSCRATCH)
+        self.asm.bctr()
+        self._close()
+        return self 
 
     # ----------------------------------------------------------------
     # ppc-specific interface:
@@ -432,11 +470,6 @@
                                gv_itemoffset, [gv_offset, IntConst(startoffset)]))
         return gv_itemoffset
 
-    def make_fresh_from_jump(self, initial_var2loc):
-        self.fresh_from_jump = True
-        self.initial_var2loc = initial_var2loc
-        self.max_param_space = -1
-
     def _write_prologue(self, sigtoken):
         numargs = sigtoken     # for now
         if DEBUG_TRAP:
@@ -494,11 +527,14 @@
             param = 0
         return ((4 + param - lv + 15) & ~15)
 
+    def _open(self):
+        self.asm.mc = self.rgenop.open_mc()
+
     def _close(self):
         self.rgenop.close_mc(self.asm.mc)
         self.asm.mc = None
 
-    def allocate_and_emit(self):
+    def allocate_and_emit(self, live_vars_gv):
         assert self.initial_var2loc is not None
         allocator = RegisterAllocation(
             self.rgenop.freeregs, self.initial_var2loc, self.initial_spill_offset)
@@ -523,6 +559,7 @@
         # note that this stomps on both rSCRATCH (not a problem) and
         # crf0 (a very small chance of being a problem)
         self.stack_adj_addr = self.asm.mc.tell()
+        #print "emit_stack_adjustment at: ", self.stack_adj_addr
         self.asm.addi(rSCRATCH, rFP, 0) # this is the immediate that later gets patched
         self.asm.subx(rSCRATCH, rSCRATCH, rSP) # rSCRATCH should now be <= 0
         self.asm.beq(3) # if rSCRATCH == 0, there is no actual adjustment, so
@@ -534,6 +571,7 @@
     def patch_stack_adjustment(self, newsize):
         if self.stack_adj_addr == 0:
             return
+        #print "patch_stack_adjustment at:", self.stack_adj_addr, newsize
         # we build an addi instruction by hand here
         opcode = 14 << 26
         rD = rSCRATCH << 21
@@ -633,17 +671,11 @@
     def op_int_ne(self, gv_x, gv_y):
         return self._compare('ne', gv_x, gv_y)
 
-    def _jump(self, gv_condition, if_true):
-        targetbuilder = self.rgenop.openbuilder()
-
-        targetaddr = targetbuilder.asm.mc.tell()
+    def _jump(self, gv_condition, if_true, args_gv):
+        targetbuilder = self.rgenop.newbuilder()
 
         self.insns.append(
-            insn.Jump(gv_condition, self.rgenop.genconst(targetaddr), if_true))
-
-        allocator = self.allocate_and_emit()
-        self.make_fresh_from_jump(allocator.var2loc)
-        targetbuilder.make_fresh_from_jump(allocator.var2loc)
+            insn.Jump(gv_condition, targetbuilder, if_true, args_gv))
 
         return targetbuilder
 
@@ -688,7 +720,8 @@
 
     def newgraph(self, sigtoken, name):
         numargs = sigtoken          # for now
-        builder = self.openbuilder()
+        builder = self.newbuilder()
+        builder._open()
         entrypoint = builder.asm.mc.tell()
         inputargs_gv = builder._write_prologue(sigtoken)
         return builder, IntConst(entrypoint), inputargs_gv
@@ -780,8 +813,8 @@
 ##                             mc._size*4)
         self.mcs.append(mc)
 
-    def openbuilder(self):
-        return Builder(self, self.open_mc())
+    def newbuilder(self):
+        return Builder(self)
 
 # a switch can take 7 instructions:
 
@@ -808,8 +841,9 @@
         self.default_target_addr = 0
 
     def add_case(self, gv_case):
-        targetbuilder = self.rgenop.openbuilder()
-        targetbuilder.make_fresh_from_jump(self.var2loc)
+        targetbuilder = self.rgenop.newbuilder()
+        targetbuilder._open()
+        targetbuilder.initial_var2loc = self.var2loc
         target_addr = targetbuilder.asm.mc.tell()
         p = self.asm.mc.getpos()
         # that this works depends a bit on the fixed length of the
@@ -843,8 +877,9 @@
             self._write_default()
 
     def add_default(self):
-        targetbuilder = self.rgenop.openbuilder()
-        targetbuilder.make_fresh_from_jump(self.var2loc)
+        targetbuilder = self.rgenop.newbuilder()
+        targetbuilder._open()
+        targetbuilder.initial_var2loc = self.var2loc
         self.default_target_addr = targetbuilder.asm.mc.tell()
         self._write_default()
         return targetbuilder



More information about the Pypy-commit mailing list