[pypy-svn] r31516 - in pypy/dist/pypy/jit/codegen/i386: . test
arigo at codespeak.net
arigo at codespeak.net
Wed Aug 23 11:44:01 CEST 2006
Author: arigo
Date: Wed Aug 23 11:43:59 2006
New Revision: 31516
Modified:
pypy/dist/pypy/jit/codegen/i386/ri386.py
pypy/dist/pypy/jit/codegen/i386/ri386genop.py
pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py
Log:
(pedronis, arigo)
Some link support. Fun copying values from a "previous stack layout" to
a "new stack layout" overlapping it.
Modified: pypy/dist/pypy/jit/codegen/i386/ri386.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/ri386.py (original)
+++ pypy/dist/pypy/jit/codegen/i386/ri386.py Wed Aug 23 11:43:59 2006
@@ -84,6 +84,12 @@
imm16 = IMM16
rel32 = REL32
+def imm(value):
+ if single_byte(value):
+ return imm8(value)
+ else:
+ return imm32(value)
+
def memregister(register):
assert register.width == 4
return MODRM(0xC0 | register.op, '')
Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original)
+++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Wed Aug 23 11:43:59 2006
@@ -25,7 +25,7 @@
self.stackpos = stackpos
def operand(self, block):
- return mem(esp, WORD * (block.stackdepth-1 - self.stackpos))
+ return block.stack_access(self.stackpos)
class TypeConst(VarOrConst):
@@ -40,10 +40,7 @@
self.value = value
def operand(self, block):
- if single_byte(self.value):
- return IMM8(self.value)
- else:
- return IMM32(self.value)
+ return imm(self.value)
class FnPtrConst(IntConst):
@@ -65,6 +62,9 @@
self.stackdepth += 1
return res
+ def stack_access(self, stackpos):
+ return mem(esp, WORD * (self.stackdepth-1 - stackpos))
+
def push(self, reg):
self.mc.PUSH(reg)
res = Var(self.stackdepth)
@@ -76,25 +76,97 @@
self.mc.ADD(eax, gv_y.operand(self))
return self.push(eax)
+ def op_int_sub(self, (gv_x, gv_y), gv_RESTYPE):
+ self.mc.MOV(eax, gv_x.operand(self))
+ self.mc.SUB(eax, gv_y.operand(self))
+ return self.push(eax)
+
class RI386GenOp(object):
gv_IntWord = TypeConst('IntWord')
gv_Void = TypeConst('Void')
def __init__(self):
- self.mc = MachineCodeBlock(65536) # XXX!!!
+ 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
+
+ def close_mc(self, mc):
+ self.mcs.append(mc)
def newblock(self):
- # XXX concurrently-open Blocks cannot use the same mc
- return Block(self.mc)
+ return Block(self.open_mc())
def closeblock1(self, block):
- return block
+ return block # NB. links and blocks are the same for us
def closereturnlink(self, link, gv_result):
link.mc.MOV(eax, gv_result.operand(link))
- link.mc.ADD(esp, IMM32(WORD * link.stackdepth))
+ link.mc.ADD(esp, imm32(WORD * link.stackdepth))
link.mc.RET()
+ self.close_mc(link.mc)
+
+ def closelink(self, link, outputargs_gv, targetblock):
+ N = len(outputargs_gv)
+ if link.stackdepth < N:
+ link.mc.SUB(esp, imm(WORD * (N - link.stackdepth)))
+ link.stackdepth = N
+
+ pending_dests = N
+ srccount = [0] * N
+ for i in range(N):
+ gv = outputargs_gv[i]
+ if isinstance(gv, Var):
+ p = gv.stackpos
+ if 0 <= p < N:
+ if p == i:
+ srccount[p] = -N # ignore 'v=v'
+ pending_dests -= 1
+ else:
+ srccount[p] += 1
+
+ while pending_dests:
+ progress = False
+ for i in range(N):
+ if srccount[i] == 0:
+ srccount[i] = -1
+ pending_dests -= 1
+ gv_src = outputargs_gv[i]
+ link.mc.MOV(eax, gv_src.operand(link))
+ link.mc.MOV(link.stack_access(i), eax)
+ progress = True
+ if not progress:
+ # we are left with only pure disjoint cycles; break them
+ for i in range(N):
+ if srccount[i] >= 0:
+ dst = i
+ link.mc.MOV(edx, link.stack_access(dst))
+ while True:
+ assert srccount[dst] == 1
+ srccount[dst] = -1
+ pending_dests -= 1
+ gv_src = outputargs_gv[dst]
+ assert isinstance(gv_src, Var)
+ src = gv_src.stackpos
+ assert 0 <= src < N
+ if src == i:
+ break
+ link.mc.MOV(eax, link.stack_access(src))
+ link.mc.MOV(link.stack_access(dst), eax)
+ dst = src
+ link.mc.MOV(link.stack_access(dst), edx)
+ assert pending_dests == 0
+
+ if link.stackdepth > N:
+ link.mc.ADD(esp, imm(WORD * (link.stackdepth - N)))
+ link.stackdepth = N
+ link.mc.JMP(rel32(targetblock.startaddr))
+ self.close_mc(link.mc)
def geninputarg(self, block, gv_TYPE):
return block.geninputarg(gv_TYPE)
@@ -122,10 +194,13 @@
def gencallableconst(self, name, block, gv_FUNCTYPE):
prologue = self.newblock()
#prologue.mc.BREAKPOINT()
- operand = mem(esp, WORD * block.argcount)
+ # re-push the arguments so that they are after the return value
+ # and in the correct order
for i in range(block.argcount):
+ operand = mem(esp, WORD * (2*i+1))
prologue.mc.PUSH(operand)
prologue.mc.JMP(rel32(block.startaddr))
+ self.close_mc(prologue.mc)
return FnPtrConst(prologue.startaddr, prologue.mc)
def revealconst(T, gv_const):
Modified: pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py (original)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py Wed Aug 23 11:43:59 2006
@@ -1,6 +1,5 @@
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import llinterp
-from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython.llinterp import LLInterpreter
from pypy.rpython.objectmodel import keepalive_until_here
from pypy.translator.c.test.test_genc import compile
from pypy.jit.codegen.i386.ri386genop import RI386GenOp
@@ -31,10 +30,16 @@
gv_add_x = make_adder(rgenop, x)
add_x = rgenop.revealconst(lltype.Ptr(FUNC), gv_add_x)
res = add_x(y)
- keepalive_until_here(gv_add_x) # to keep the 'add_x' fnptr alive
+ keepalive_until_here(rgenop) # to keep the code blocks alive
return res
-# ____________________________________________________________
+def test_adder_interpret():
+ from pypy.rpython import rgenop
+ gv_add_5 = make_adder(rgenop, 5)
+ add_5 = rgenop.revealconst(lltype.Ptr(FUNC), gv_add_5)
+ llinterp = LLInterpreter(None)
+ res = llinterp.eval_graph(add_5._obj.graph, [12])
+ assert res == 17
def test_adder_direct():
rgenop = RI386GenOp()
@@ -48,3 +53,63 @@
fn = compile(runner, [int, int])
res = fn(9080983, -9080941)
assert res == 42
+
+# ____________________________________________________________
+
+FUNC2 = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
+
+def make_dummy(rgenop):
+ # 'return x - (y - (x-1))'
+ gv_SIGNED = rgenop.constTYPE(lltype.Signed)
+ block = rgenop.newblock()
+ gv_x = rgenop.geninputarg(block, gv_SIGNED)
+ gv_y = rgenop.geninputarg(block, gv_SIGNED)
+ args_gv = [gv_x, rgenop.genconst(1)]
+ gv_z = rgenop.genop(block, "int_sub", args_gv, gv_SIGNED)
+ link = rgenop.closeblock1(block)
+
+ block2 = rgenop.newblock()
+ gv_y2 = rgenop.geninputarg(block2, gv_SIGNED)
+ gv_z2 = rgenop.geninputarg(block2, gv_SIGNED)
+ gv_x2 = rgenop.geninputarg(block2, gv_SIGNED)
+ rgenop.closelink(link, [gv_y, gv_z, gv_x], block2)
+
+ args_gv = [gv_y2, gv_z2]
+ gv_s2 = rgenop.genop(block2, "int_sub", args_gv, gv_SIGNED)
+ args_gv = [gv_x2, gv_s2]
+ gv_t2 = rgenop.genop(block2, "int_sub", args_gv, gv_SIGNED)
+ link2 = rgenop.closeblock1(block2)
+
+ rgenop.closereturnlink(link2, gv_t2)
+ gv_FUNC2 = rgenop.constTYPE(FUNC2)
+ gv_dummyfn = rgenop.gencallableconst("dummy", block, gv_FUNC2)
+ return gv_dummyfn
+
+def dummy_runner(x, y):
+ rgenop = RI386GenOp()
+ gv_dummyfn = make_dummy(rgenop)
+ dummyfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_dummyfn)
+ res = dummyfn(x, y)
+ keepalive_until_here(rgenop) # to keep the code blocks alive
+ return res
+
+def test_dummy_interpret():
+ from pypy.rpython import rgenop
+ gv_dummyfn = make_dummy(rgenop)
+ dummyfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_dummyfn)
+ llinterp = LLInterpreter(None)
+ res = llinterp.eval_graph(dummyfn._obj.graph, [30, 17])
+ assert res == 42
+
+def test_dummy_direct():
+ rgenop = RI386GenOp()
+ gv_dummyfn = make_dummy(rgenop)
+ print gv_dummyfn.value
+ fnptr = cast(c_void_p(gv_dummyfn.value), CFUNCTYPE(c_int, c_int, c_int))
+ res = fnptr(30, 17) # <== the segfault is here
+ assert res == 42
+
+def test_dummy_compile():
+ fn = compile(dummy_runner, [int, int])
+ res = fn(40, 37)
+ assert res == 42
More information about the Pypy-commit
mailing list