[pypy-svn] r33455 - in pypy/dist/pypy/jit/codegen: ppc test
mwh at codespeak.net
mwh at codespeak.net
Thu Oct 19 15:26:09 CEST 2006
Author: mwh
Date: Thu Oct 19 15:26:06 2006
New Revision: 33455
Modified:
pypy/dist/pypy/jit/codegen/ppc/conftest.py
pypy/dist/pypy/jit/codegen/ppc/rgenop.py
pypy/dist/pypy/jit/codegen/test/rgenop_tests.py
Log:
add another two tests to rgenop_tests, associated fixing and coding in
ppc/rgenop.
i'm generating _really_ bad assembly currently :)
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 Thu Oct 19 15:26:06 2006
@@ -14,3 +14,10 @@
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/dist/pypy/jit/codegen/ppc/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/rgenop.py (original)
+++ pypy/dist/pypy/jit/codegen/ppc/rgenop.py Thu Oct 19 15:26:06 2006
@@ -1,7 +1,8 @@
from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenerator
from pypy.jit.codegen.model import GenVar, GenConst
from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython.objectmodel import specialize
+from pypy.rpython.objectmodel import specialize, we_are_translated
+from pypy.jit.codegen.ppc.conftest import option
class VarLocation(object):
pass
@@ -82,6 +83,33 @@
self.mc.write(value)
RPPCAssembler.emit = emit
+def prepare_for_jump(builder, outputargs_gv, targetblock):
+ assert len(targetblock.arg_locations) == len(outputargs_gv)
+ outregs = []
+ targetregs = []
+ for gv in outputargs_gv:
+ assert isinstance(gv, Var)
+ assert isinstance(gv.location, RegisterLocation)
+ outregs.append(gv.location.reg)
+ for loc in targetblock.arg_locations:
+ assert isinstance(loc, RegisterLocation)
+ targetregs.append(loc.reg)
+ for i in range(len(outregs)):
+ treg = targetregs[i]
+ oreg = outregs[i]
+ if oreg == treg:
+ continue
+ if treg in outregs:
+ outi = outregs.index(treg)
+ assert outi > i
+ builder.asm.xor(treg, treg, oreg)
+ builder.asm.xor(oreg, treg, oreg)
+ builder.asm.xor(treg, treg, oreg)
+ outregs[outi] = oreg
+ outregs[i] == treg
+ else:
+ builder.asm.mr(treg, oreg)
+
class MachineCodeBlock:
def __init__(self, map_size):
@@ -119,17 +147,20 @@
class Builder(CodeGenerator):
- def __init__(self, rgenop, mc, stackdepth):
+ def __init__(self, rgenop, mc, parent):
self.rgenop = rgenop
- self.stackdepth = stackdepth
self.asm = RPPCAssembler()
self.asm.mc = mc
- self.curreg = 3
+ if parent is None:
+ self.curreg = 3
+ else:
+ self.curreg = parent.curreg
def _write_prologue(self, sigtoken):
numargs = sigtoken # for now
self.curreg += numargs
- #self.asm.trap()
+ if not we_are_translated() and option.trap:
+ self.asm.trap()
return [Var(RegisterLocation(pos)) for pos in range(3, 3+numargs)]
def _close(self):
@@ -146,6 +177,14 @@
self.asm.blr()
self._close()
+ def finish_and_goto(self, outputargs_gv, targetblock):
+ prepare_for_jump(self, outputargs_gv, targetblock)
+ gv = self.newvar()
+ self.asm.load_word(gv.reg(), targetblock.startaddr)
+ self.asm.mtctr(gv.reg())
+ self.asm.bctr()
+ self._close()
+
def enter_next_block(self, kinds, args_gv):
arg_locations = []
seen = {}
@@ -205,8 +244,17 @@
self.asm.beqctr()
return targetbuilder
+ def jump_if_true(self, gv_condition):
+ targetbuilder = self._fork()
+ gv = self.newvar()
+ self.asm.load_word(gv.reg(), targetbuilder.asm.mc.tell())
+ self.asm.mtctr(gv.reg())
+ self.asm.cmpwi(0, gv_condition.load(self), 0)
+ self.asm.bnectr()
+ return targetbuilder
+
def _fork(self):
- return self.rgenop.openbuilder(self.stackdepth)
+ return self.rgenop.openbuilder(self)
class RPPCGenOp(AbstractRGenOp):
@@ -215,13 +263,8 @@
def __init__(self):
self.mcs = [] # machine code blocks where no-one is currently writing
-
- def __init__(self):
- self.mcs = [] # machine code blocks where no-one is currently writing
-
def open_mc(self):
if self.mcs:
- # XXX think about inserting NOPS for alignment
return self.mcs.pop()
else:
return MachineCodeBlock(65536) # XXX supposed infinite for now
@@ -239,13 +282,13 @@
def kindToken(T):
return None # for now
- def openbuilder(self, stackdepth):
- return Builder(self, self.open_mc(), stackdepth)
+ def openbuilder(self, parent):
+ return Builder(self, self.open_mc(), parent)
def newgraph(self, sigtoken):
numargs = sigtoken # for now
initialstackdepth = numargs+1
- builder = self.openbuilder(initialstackdepth)
+ builder = self.openbuilder(None)
entrypoint = builder.asm.mc.tell()
inputargs_gv = builder._write_prologue(sigtoken)
return builder, entrypoint, inputargs_gv
Modified: pypy/dist/pypy/jit/codegen/test/rgenop_tests.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/test/rgenop_tests.py (original)
+++ pypy/dist/pypy/jit/codegen/test/rgenop_tests.py Thu Oct 19 15:26:06 2006
@@ -95,6 +95,47 @@
return branching_runner
+def make_goto(rgenop):
+ # while x > 0:
+ # y += x
+ # x -= 1
+ # return y
+ signed_kind = rgenop.kindToken(lltype.Signed)
+ sigtoken = rgenop.sigToken(FUNC2)
+ builder, entrypoint, [gv_x, gv_y] = rgenop.newgraph(sigtoken)
+
+ # loop start block
+ args_gv = [gv_x, gv_y]
+ loopblock = builder.enter_next_block([signed_kind, signed_kind], args_gv)
+ [gv_x, gv_y] = args_gv
+
+ gv_cond = builder.genop2("int_gt", gv_x, rgenop.genconst(0))
+ bodybuilder = builder.jump_if_true(gv_cond)
+ builder.finish_and_return(sigtoken, gv_y)
+
+ # loop body
+ args_gv = [gv_y, gv_x]
+ bodybuilder.enter_next_block([signed_kind, signed_kind], args_gv)
+ [gv_y, gv_x] = args_gv
+
+ gv_y2 = bodybuilder.genop2("int_add", gv_x, gv_y)
+ gv_x2 = bodybuilder.genop2("int_sub", gv_x, rgenop.genconst(1))
+ bodybuilder.finish_and_goto([gv_x2, gv_y2], loopblock)
+
+ # done
+ gv_gotofn = rgenop.gencallableconst(sigtoken, "goto", entrypoint)
+ return gv_gotofn
+
+def get_goto_runner(RGenOp):
+ def goto_runner(x, y):
+ rgenop = RGenOp()
+ gv_gotofn = make_goto(rgenop)
+ gotofn = gv_gotofn.revealconst(lltype.Ptr(FUNC2))
+ res = gotofn(x, y)
+ keepalive_until_here(rgenop) # to keep the code blocks alive
+ return res
+ return goto_runner
+
class AbstractRGenOpTests(test_boehm.AbstractGCTestClass):
RGenOp = None
@@ -143,3 +184,21 @@
assert res == 29
res = fn(3, 17)
assert res == 17
+
+ def test_goto_direct(self):
+ rgenop = self.RGenOp()
+ gv_gotofn = make_goto(rgenop)
+ print gv_gotofn.value
+ fnptr = cast(c_void_p(gv_gotofn.value), CFUNCTYPE(c_int, c_int, c_int))
+ res = fnptr(30, 17) # <== the segfault is here
+ assert res == 31 * 15 + 17
+ res = fnptr(3, 17) # <== or here
+ assert res == 23
+
+ def test_goto_compile(self):
+ fn = self.compile(get_goto_runner(self.RGenOp), [int, int])
+ res = fn(30, 17)
+ assert res == 31 * 15 + 17
+ res = fn(3, 17)
+ assert res == 23
+
More information about the Pypy-commit
mailing list