[pypy-svn] r22508 - in pypy/dist/pypy/rpython: l3interp l3interp/test memory
mwh at codespeak.net
mwh at codespeak.net
Mon Jan 23 12:14:44 CET 2006
Author: mwh
Date: Mon Jan 23 12:14:39 2006
New Revision: 22508
Modified:
pypy/dist/pypy/rpython/l3interp/convertgraph.py
pypy/dist/pypy/rpython/l3interp/l3interp.py
pypy/dist/pypy/rpython/l3interp/model.py
pypy/dist/pypy/rpython/l3interp/test/test_convert.py
pypy/dist/pypy/rpython/memory/lladdress.py
Log:
(arre, mwh)
A test that getfield of an int on a constant struct can be converted to an
L3 graph that can be l3interped -- and almost nothing else :)
Modified: pypy/dist/pypy/rpython/l3interp/convertgraph.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/convertgraph.py (original)
+++ pypy/dist/pypy/rpython/l3interp/convertgraph.py Mon Jan 23 12:14:39 2006
@@ -3,6 +3,7 @@
from pypy.rpython.l3interp.model import Op
from pypy.objspace.flow import model as flowmodel
from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.memory.lladdress import OffsetOf, fakeaddress
class LL2L3Converter(object):
@@ -32,6 +33,22 @@
else:
return 'ptr'
+def getaccesskind(T):
+ assert isinstance(T, lltype.LowLevelType)
+ if isinstance(T, lltype.Primitive):
+ if T == lltype.Float:
+ return 'dbl'
+ if T == lltype.Signed:
+ return 'int'
+ if T == lltype.Char:
+ return 'char'
+ elif T == lltype.Void:
+ raise Exception("accessing a Void value?")
+ else:
+ raise Exception("don't know how to acess %s value"%T)
+ else:
+ return 'ptr'
+
def convert_block(block, memo):
if block in memo:
return memo[block]
@@ -41,7 +58,8 @@
'ptr': 0}
constants = {'int': [],
'dbl': [],
- 'ptr': []}
+ 'ptr': [],
+ 'offset':[]}
var2stack = {}
def push(v):
@@ -54,11 +72,15 @@
kind = getkind(v.concretetype)
if isinstance(v, flowmodel.Constant):
clist = constants[kind]
+ if kind == 'ptr':
+ value = fakeaddress(v.value)
+ else:
+ value = v.value
try:
- res = clist.index(v.value)
+ res = clist.index(value)
except ValueError:
res = len(clist)
- clist.append(v.value)
+ clist.append(value)
return res
else:
position = var2stack[v]
@@ -87,9 +109,25 @@
return l3block
for spaceop in block.operations:
- insns.append(model.very_low_level_opcode[spaceop.opname])
- for v in spaceop.args:
- insns.append(get(v))
+ if spaceop.opname == 'getfield':
+ opname = spaceop.opname + '_' + \
+ getaccesskind(spaceop.result.concretetype)
+ insns.append(model.very_low_level_opcode[opname])
+ v0, v1 = spaceop.args
+ insns.append(get(v0))
+
+ offset = OffsetOf(v0.concretetype, v1.value)
+ clist = constants['offset']
+ try:
+ res = clist.index(offset)
+ except ValueError:
+ res = len(clist)
+ clist.append(offset)
+ insns.append(res)
+ else:
+ insns.append(model.very_low_level_opcode[spaceop.opname])
+ for v in spaceop.args:
+ insns.append(get(v))
if spaceop.result.concretetype is not lltype.Void:
push(spaceop.result)
@@ -127,5 +165,6 @@
if constants['int']: l3block.constants_int = constants['int']
if constants['dbl']: l3block.constants_dbl = constants['dbl']
if constants['ptr']: l3block.constants_ptr = constants['ptr']
+ if constants['offset']: l3block.constants_offset = constants['offset']
return l3block
Modified: pypy/dist/pypy/rpython/l3interp/l3interp.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/l3interp.py (original)
+++ pypy/dist/pypy/rpython/l3interp/l3interp.py Mon Jan 23 12:14:39 2006
@@ -114,6 +114,11 @@
if op >= 0: return self.block.constants_ptr[op]
else: return self.stack_ptr[op]
+ def getoffset(self):
+ op = self.nextop()
+ assert op >= 0
+ return self.block.constants_offset[op]
+
def restorestacks(self):
del self.stack_int[self.base_int:]
del self.stack_dbl[self.base_dbl:]
@@ -164,6 +169,11 @@
else:
self.stack_int.append(0)
+ def op_getfield_int(self):
+ p = self.getptr()
+ o = self.getoffset()
+ self.stack_int.append((p + o).signed[0])
+
def op_direct_call(self):
block = self.block
assert block.called_graphs is not None
Modified: pypy/dist/pypy/rpython/l3interp/model.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/model.py (original)
+++ pypy/dist/pypy/rpython/l3interp/model.py Mon Jan 23 12:14:39 2006
@@ -41,7 +41,8 @@
'getarrayitem', 'getarraysize', 'getarraysubstruct', 'setarrayitem',
#struct operations:
- 'getfield', 'getsubstruct', 'setfield',
+ 'getfield_int', 'getfield_char', 'getfield_dbl', 'getfield_ptr',
+ 'getsubstruct', 'setfield',
#integer operations:
'int_abs', 'int_abs_ovf', 'int_add', 'int_add_ovf', 'int_and',
@@ -104,6 +105,7 @@
constants_int=None,
constants_dbl=None,
constants_ptr=None,
+ constants_offset=None,
called_graphs=None):
self.insns = insns
self.exit0 = exit0
@@ -111,6 +113,7 @@
self.constants_int = constants_int
self.constants_dbl = constants_dbl
self.constants_ptr = constants_ptr
+ self.constants_offset = constants_offset
self.called_graphs = called_graphs
class Link(object):
Modified: pypy/dist/pypy/rpython/l3interp/test/test_convert.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/test/test_convert.py (original)
+++ pypy/dist/pypy/rpython/l3interp/test/test_convert.py Mon Jan 23 12:14:39 2006
@@ -40,4 +40,24 @@
assert isinstance(result, l3interp.L3Integer)
assert result.intval == 1
-
+def test_convert_getfield():
+ class C:
+ def __init__(self, x):
+ self.x = x
+ one = C(1)
+ two = C(2)
+
+ def f(n):
+ if n:
+ return one.x
+ else:
+ return two.x
+ l3graph = l3ify(f, [int])
+ result = l3interp.l3interpret(l3graph, [3], [], [])
+ assert isinstance(result, l3interp.L3Integer)
+ assert result.intval == 1
+
+ result = l3interp.l3interpret(l3graph, [0], [], [])
+ assert isinstance(result, l3interp.L3Integer)
+ assert result.intval == 2
+
Modified: pypy/dist/pypy/rpython/memory/lladdress.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lladdress.py (original)
+++ pypy/dist/pypy/rpython/memory/lladdress.py Mon Jan 23 12:14:39 2006
@@ -160,3 +160,33 @@
def itemoffsetof(TYPE, n=None):
pass
+
+class fakeaddress(object):
+ def __init__(self, ob, offset=None):
+ self.ob = ob
+ if offset is None:
+ self.offset = OffsetOf(self.ob._TYPE)
+ else:
+ self.offset = offset
+
+ def __add__(self, other):
+ if not isinstance(other, OffsetOf):
+ return NotImplemented
+ return fakeaddress(self.ob, self.offset + other)
+
+class _fakeaccessor(object):
+ def __init__(self, addr):
+ self.addr = addr
+ def __getitem__(self, index):
+ assert index == 0
+ ob = self.addr.ob
+ for n in self.addr.offset.fldnames:
+ ob = getattr(ob, n)
+ # XXX will need to do pointers differently!
+ assert lltype.typeOf(ob) == self.TYPE
+ return ob
+
+class _signed_fakeaccessor(_fakeaccessor):
+ TYPE = lltype.Signed
+
+fakeaddress.signed = property(_signed_fakeaccessor)
More information about the Pypy-commit
mailing list