[pypy-svn] r22590 - in pypy/dist/pypy: annotation rpython rpython/l3interp rpython/l3interp/test rpython/lltypesystem rpython/lltypesystem/test rpython/memory translator/c

ac at codespeak.net ac at codespeak.net
Tue Jan 24 14:22:58 CET 2006


Author: ac
Date: Tue Jan 24 14:22:57 2006
New Revision: 22590

Added:
   pypy/dist/pypy/rpython/lltypesystem/test/   (props changed)
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py   (contents, props changed)
Modified:
   pypy/dist/pypy/annotation/binaryop.py
   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/l3interp/test/test_l3interp.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/memory/lladdress.py
   pypy/dist/pypy/rpython/memory/lltypelayout.py
   pypy/dist/pypy/rpython/raddress.py
   pypy/dist/pypy/translator/c/primitive.py
Log:
(mwh, arre)
Implemented getarrayitem and in the process refactored
Offsets.



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Tue Jan 24 14:22:57 2006
@@ -737,6 +737,10 @@
     def add((s_off1, s_off2)):
         return SomeOffset()
 
+class __extend__(pairtype(SomeOffset, SomeInteger)):
+    def mul((s_off1, s_off2)):
+        return SomeOffset()
+
 class __extend__(pairtype(SomeAddress, SomeOffset)):
     def add((s_addr, s_off)):
         return SomeAddress()

Modified: pypy/dist/pypy/rpython/l3interp/convertgraph.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/convertgraph.py	(original)
+++ pypy/dist/pypy/rpython/l3interp/convertgraph.py	Tue Jan 24 14:22:57 2006
@@ -3,7 +3,8 @@
 from pypy.rpython.l3interp.model import Op
 from pypy.objspace.flow import model as flowmodel
 from pypy.rpython.lltypesystem import lltype
-from pypy.rpython.lltypesystem.llmemory import OffsetOf, fakeaddress
+from pypy.rpython.lltypesystem.llmemory import FieldOffset, \
+     ItemOffset, ArrayItemsOffset, fakeaddress
 
 
 class LL2L3Converter(object):
@@ -86,6 +87,15 @@
             position = var2stack[v]
             return position - stacksizes[kind]    # < 0
 
+    def getoffset(offset):
+        clist = constants['offset']
+        try:
+            res = clist.index(offset)
+        except ValueError:
+            res = len(clist)
+            clist.append(offset)
+        return res
+
     for v in block.inputargs:
         if v.concretetype is not lltype.Void:
             push(v)
@@ -117,14 +127,8 @@
             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)
+            offset = FieldOffset(v0.concretetype, v1.value)
+            insns.append(getoffset(offset))
         elif spaceop.opname == 'setfield':
             v0, v1, v2 = spaceop.args
             opname = spaceop.opname + '_' + \
@@ -132,15 +136,22 @@
             insns.append(model.very_low_level_opcode[opname])
             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)
+            offset = FieldOffset(v0.concretetype, v1.value)
+            insns.append(getoffset(offset))
             insns.append(get(v2))
+        elif spaceop.opname == 'getarrayitem':
+            opname = spaceop.opname + '_' + \
+                     getaccesskind(spaceop.result.concretetype)
+            insns.append(model.very_low_level_opcode[opname])
+            v0, v1 = spaceop.args
+            insns.append(get(v0))
+            insns.append(get(v1))
+
+            offset = ArrayItemsOffset(v0.concretetype)
+            insns.append(getoffset(offset))
+
+            offset = ItemOffset(spaceop.result.concretetype)
+            insns.append(getoffset(offset))
         else:
             insns.append(model.very_low_level_opcode[spaceop.opname])
             for v in spaceop.args:

Modified: pypy/dist/pypy/rpython/l3interp/l3interp.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/l3interp.py	(original)
+++ pypy/dist/pypy/rpython/l3interp/l3interp.py	Tue Jan 24 14:22:57 2006
@@ -2,7 +2,7 @@
 from pypy.rpython.memory import lladdress
 from pypy.rpython.rarithmetic import r_uint
 from pypy.interpreter.miscutils import InitializedClass
-from pypy.rpython.lltypesystem.llmemory import fakeaddress, OffsetOf
+from pypy.rpython.lltypesystem.llmemory import fakeaddress, AddressOffset
 from pypy.rpython.lltypesystem import lltype
 
 class L3Exception(Exception):
@@ -46,7 +46,7 @@
         return L3Nothing()
     raise AssertionError("stacks corrupted")
 
-constant_offset = OffsetOf(lltype.Void)
+constant_offset = AddressOffset()
 constant_fakeaddress = fakeaddress(None)
 
 class L3Frame(object):
@@ -203,6 +203,14 @@
         o = self.getoffset()
         v = self.getint()
         (p + o).signed[0] = v
+
+    def op_getarrayitem_int(self):
+        a = self.getptr()
+        i = self.getint()
+        items_offset = self.getoffset()
+        s = self.getoffset()
+        v = (a + items_offset + s * i).signed[0]
+        self.stack_int.append(v)
         
     def op_flavored_malloc(self):
         self.stack_ptr.append(constant_fakeaddress)

Modified: pypy/dist/pypy/rpython/l3interp/model.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/model.py	(original)
+++ pypy/dist/pypy/rpython/l3interp/model.py	Tue Jan 24 14:22:57 2006
@@ -37,7 +37,8 @@
     'float_ne', 'float_neg', 'float_sub', 'float_truediv',
 
     #array operations:
-    'getarrayitem', 'getarraysize', 'getarraysubstruct', 'setarrayitem',
+    'getarrayitem_int', 'getarrayitem_ptr',
+    'getarraysize', 'getarraysubstruct', 'setarrayitem',
 
     #struct operations:
     'getfield_int', 'getfield_char', 'getfield_dbl', 'getfield_ptr', 

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	Tue Jan 24 14:22:57 2006
@@ -76,6 +76,29 @@
     assert isinstance(result, l3interp.L3Integer)
     assert result.intval == 2
 
+
+def test_convert_getitem():
+    from pypy.rpython.lltypesystem import lltype 
+
+    A = lltype.GcArray(lltype.Signed)
+    a = lltype.malloc(A, 3)
+    a[0] = 1
+    a[1] = 2
+    a[2] = 3
+    
+
+    def f(n):
+        return a[n]
+
+    l3graph = l3ify(f, [int])
+    result = l3interp.l3interpret(l3graph, [0], [], [])
+    assert isinstance(result, l3interp.L3Integer)
+    assert result.intval == 1
+
+    result = l3interp.l3interpret(l3graph, [1], [], [])
+    assert isinstance(result, l3interp.L3Integer)
+    assert result.intval == 2
+    
 def dont_test_call():
     def f():
         return 2

Modified: pypy/dist/pypy/rpython/l3interp/test/test_l3interp.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/test/test_l3interp.py	(original)
+++ pypy/dist/pypy/rpython/l3interp/test/test_l3interp.py	Tue Jan 24 14:22:57 2006
@@ -238,3 +238,31 @@
         for y in 0, 1:
             assert fn(x, y) == f(x, y)
 
+
+def test_getitem():
+    from pypy.rpython.lltypesystem import lltype 
+
+    A = lltype.GcArray(lltype.Signed)
+    a = lltype.malloc(A, 3)
+    a[0] = 1
+    a[1] = 2
+    a[2] = 3
+    
+
+    def f(n):
+        return a[n]
+
+    l3graph = l3ify(f, [int])
+    def entry_point(x):
+        value = l3interp.l3interpret(l3graph, [x], [], [])
+        assert isinstance(value, l3interp.L3Integer)
+        return value.intval
+
+    for arg in 0,1,2:
+        assert entry_point(arg) == f(arg)
+
+    fn = translate(entry_point, [int])
+        
+    for arg in 0,1,2:
+        assert fn(arg) == f(arg)
+

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Tue Jan 24 14:22:57 2006
@@ -7,11 +7,7 @@
 from pypy.rpython.objectmodel import Symbolic
 from pypy.rpython.lltypesystem import lltype
 
-class OffsetOf(Symbolic):
-
-    def __init__(self, TYPE, *fldnames):
-        self.TYPE = TYPE
-        self.fldnames = fldnames
+class AddressOffset(Symbolic):
 
     def annotation(self):
         from pypy.annotation import model
@@ -20,72 +16,140 @@
     def lltype(self):
         return lltype.Signed
 
+    def __add__(self, other):
+        return CompositeOffset(self, other)
+
+
+class ItemOffset(AddressOffset):
+
+    def __init__(self, TYPE, repeat=1):
+        self.TYPE = TYPE
+        self.repeat = repeat
+
     def __repr__(self):
-        return "<OffsetOf %r %r>" % (self.TYPE, self.fldnames)
+        return "<ItemOffset %r %r>" % (self.TYPE, self.repeat)
 
-    def __add__(self, other):
-        if not isinstance(other, OffsetOf):
+    def __mul__(self, other):
+        if not isinstance(other, int):
             return NotImplemented
-        t = self.TYPE
-        for f in self.fldnames:
-            t = t._flds[f]
-        assert t == other.TYPE
-        return OffsetOf(self.TYPE, *(self.fldnames + other.fldnames))
+        return ItemOffset(self.TYPE, self.repeat * other)
+
+    def get(self, ob):
+        return ob[self.repeat]
+
+    def set(self, ob, value):
+        ob[self.repeat] = value
+
+    
+class FieldOffset(AddressOffset):
+
+    def __init__(self, TYPE, fldname):
+        self.TYPE = TYPE
+        self.fldname = fldname
+
+    def __repr__(self):
+        return "<FieldOffset %r %r>" % (self.TYPE, self.fldname)
+
+    def get(self, ob):
+        return getattr(ob, self.fldname)
+
+    def set(self, ob, value):
+        setattr(ob, self.fldname, value)
+
+
+class CompositeOffset(AddressOffset):
+
+    def __init__(self, first, second):
+        self.first = first
+        self.second = second
+
+    def __repr__(self):
+        return '< %r + %r >'%(self.first, self.second)
+
+    def get(self, ob):
+        return self.second.get(self.first.get(ob))
+
+    def set(self, ob, value):
+        return self.second.set(self.first.get(ob), value)
+
+
+class ArrayItemsOffset(AddressOffset):
+
+    def __init__(self, TYPE):
+        self.TYPE = TYPE
+
+    def __repr__(self):
+        return '< ArrayItemsOffset >'
+
+    def get(self, ob):
+        return ob
+
+    def set(self, ob, value):
+        raise Exception("can't assign to an array's items")
+
 
 def sizeof(TYPE, n=None):
     pass
 
 def offsetof(TYPE, fldname):
     assert fldname in TYPE._flds
-    return OffsetOf(TYPE, fldname)
+    return FieldOffset(TYPE, fldname)
 
-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(lltype.typeOf(self.ob))
-        else:
-            self.offset = offset
+        self.offset = offset
 
     def __add__(self, other):
-        if not isinstance(other, OffsetOf):
-            return NotImplemented
-        return fakeaddress(self.ob, self.offset + other)
-    
+        if isinstance(other, AddressOffset):
+            if self.offset is None:
+                offset = other
+            else:
+                offset = self.offset + other
+            return fakeaddress(self.ob, offset)
+        return NotImplemented
+
+    def get(self):
+        if self.offset is None:
+            return self.ob
+        else:
+            return self.offset.get(self.ob)
+
+    def set(self, value):
+        if self.offset is None:
+            raise Exception("can't assign to whole object")
+        else:
+            self.offset.set(self.ob, value)
+
+# XXX the indexing in code like
+#     addr.signed[0] = v
+#     is just silly.  remove it.
+
 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)
-        return self.vet(ob)
+        return self.convert(self.addr.get())
 
     def __setitem__(self, index, value):
         assert index == 0
-        ob = self.addr.ob
-        for n in self.addr.offset.fldnames[:-1]:
-            ob = getattr(ob, n)
-        fld = self.addr.offset.fldnames[-1]
-        assert lltype.typeOf(value) == self.TYPE
-        assert lltype.typeOf(ob).TO._flds[fld] == self.TYPE
-        setattr(ob, fld, value)
+        self.addr.set(value)
+
         
 class _signed_fakeaccessor(_fakeaccessor):
     TYPE = lltype.Signed
 
-    def vet(self, value):
+    def convert(self, value):
         assert lltype.typeOf(value) == self.TYPE
         return value
 
 class _address_fakeaccessor(_fakeaccessor):
     TYPE = None
 
-    def vet(self, value):
+    def convert(self, value):
         # XXX is this the right check for "Ptr-ness" ?
         assert isinstance(value, lltype._ptr)
         return fakeaddress(value)

Added: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Tue Jan 24 14:22:57 2006
@@ -0,0 +1,35 @@
+from pypy.rpython.lltypesystem.llmemory import *
+
+def test_simple():
+    class C:
+        def __init__(self, x):
+            self.x = x
+    c = C(1)
+    a = fakeaddress(c)
+    assert a.get() is c
+    b = a + FieldOffset('dummy', 'x')
+    assert b.get() == 1
+    b.set(2)
+    assert c.x == 2
+
+def test_composite():
+    class C:
+        def __init__(self, x):
+            self.x = x
+    c = C(C(3))
+    a = fakeaddress(c)
+    assert a.get() is c
+    b = a + FieldOffset('dummy', 'x') + FieldOffset('dummy', 'x')
+    assert b.get() == 3
+    b.set(2)
+    assert c.x.x == 2
+    
+def test_array():
+    x = [2, 3, 5, 7, 11]
+    a = fakeaddress(x)
+    # is there a way to ensure that we add the ArrayItemsOffset ?
+    b = a + ArrayItemsOffset('dummy') + ItemOffset('dummy')*3
+    assert b.get() == x[3]
+    b.set(14)
+    assert x[3] == 14
+    

Modified: pypy/dist/pypy/rpython/memory/lladdress.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lladdress.py	(original)
+++ pypy/dist/pypy/rpython/memory/lladdress.py	Tue Jan 24 14:22:57 2006
@@ -28,7 +28,7 @@
         if isinstance(offset, int):
             return address(self.intaddress + offset)
         else:
-            assert isinstance(offset, llmemory.OffsetOf)
+            assert isinstance(offset, llmemory.AddressOffset)
             return address(self.intaddress + convert_offset_to_int(offset))
 
     def __sub__(self, other):
@@ -50,7 +50,7 @@
     def _store(self, fmt, *values):
         # XXX annoyance: suddenly an OffsetOf changes into a Signed?!
         from pypy.rpython.memory.lltypelayout import convert_offset_to_int
-        if len(values) == 1 and isinstance(values[0], llmemory.OffsetOf):
+        if len(values) == 1 and isinstance(values[0], llmemory.AddressOffset):
             values = [convert_offset_to_int(values[0])]
         simulator.setstruct(fmt, self.intaddress, *values)
 
@@ -81,7 +81,7 @@
     def convert_to(self, offset):
         from pypy.rpython.memory.lltypelayout import convert_offset_to_int
         # XXX same annoyance as in _store
-        if isinstance(offset, llmemory.OffsetOf):
+        if isinstance(offset, llmemory.AddressOffset):
             return convert_offset_to_int(offset)
         return int(offset)
 

Modified: pypy/dist/pypy/rpython/memory/lltypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypelayout.py	(original)
+++ pypy/dist/pypy/rpython/memory/lltypelayout.py	Tue Jan 24 14:22:57 2006
@@ -88,13 +88,21 @@
         return fixedsize + i * varsize
 
 def convert_offset_to_int(offset):
-    TYPE = offset.TYPE
-    res = 0
-    for fld in offset.fldnames:
-        layout = get_layout(TYPE)
-        res += layout[fld]
-        TYPE = getattr(TYPE, fld)
-    return res
+    if isinstance(offset, llmemory.FieldOffset):
+        layout = get_layout(offset.TYPE)
+        return layout[offset.fldname]
+    elif isinstance(offset, llmemory.CompositeOffset):
+        return convert_offset_to_int(offset.first) + \
+               convert_offset_to_int(offset.second)
+    elif type(offset) == llmemory.AddressOffset:
+        return 0
+    elif isinstance(offset, llmemory.ItemOffset):
+        return sizeof(offset.TYPE) * offset.repeat
+    elif isinstance(offset, llmemory.ArrayItemsOffset):
+        return get_fixed_size(lltype.Signed)
+    else:
+        raise Exception("unknown offset type %r"%offset)
+        
 # _____________________________________________________________________________
 # the following functions are used to find contained pointers
 

Modified: pypy/dist/pypy/rpython/raddress.py
==============================================================================
--- pypy/dist/pypy/rpython/raddress.py	(original)
+++ pypy/dist/pypy/rpython/raddress.py	Tue Jan 24 14:22:57 2006
@@ -129,6 +129,11 @@
         v_offset1, v_offset2 = hop.inputargs(offset_repr, offset_repr)
         return hop.genop('int_add', [v_offset1, v_offset2], resulttype=lltype.Signed)
 
+class __extend__(pairtype(OffsetRepr, IntegerRepr)):
+    def rtype_mul((r_offset, r_int), hop):
+        v_offset, v_int = hop.inputargs(r_offset, r_int)
+        return hop.genop('int_mul', [v_offset, v_int], resulttype=lltype.Signed)
+
 class __extend__(pairtype(AddressRepr, OffsetRepr)):
     def rtype_add((r_offset1, r_offset2), hop):
         v_offset1, v_offset2 = hop.inputargs(Address, offset_repr)

Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Tue Jan 24 14:22:57 2006
@@ -1,6 +1,7 @@
 import sys
 from pypy.rpython.lltypesystem.lltype import *
-from pypy.rpython.lltypesystem.llmemory import Address, OffsetOf, fakeaddress
+from pypy.rpython.lltypesystem.llmemory import Address, fakeaddress, \
+     AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset
 from pypy.rpython.memory.lladdress import NULL
 
 # ____________________________________________________________
@@ -9,15 +10,21 @@
 
 def name_signed(value, db):
     if isinstance(value, Symbolic):
-        assert isinstance(value, OffsetOf)
-        assert len(value.fldnames) <= 1
-        if len(value.fldnames) == 0:
-            return '0 /*offsetof*/'
-        else:
+        if isinstance(value, FieldOffset):
             structnode = db.gettypedefnode(value.TYPE.TO)
-            return 'offsetof(struct %s, %s)'%(
-                structnode.name,
-                structnode.c_struct_field_name(value.fldnames[0]))
+            return 'offsetof(%s, %s)'%(
+                db.gettype(value.TYPE.TO).replace('@', ''),
+                structnode.c_struct_field_name(value.fldname))
+        elif isinstance(value, ItemOffset):
+            return '(sizeof(%s) * %s)'%(
+                db.gettype(value.TYPE).replace('@', ''), value.repeat)
+        elif isinstance(value, ArrayItemsOffset):
+            return 'offsetof(%s, items)'%(
+                db.gettype(value.TYPE.TO).replace('@', ''))
+        elif type(value) == AddressOffset:
+            return '0'
+        else:
+            raise Exception("unimplemented symbolic %r"%value)
     if value == -sys.maxint-1:   # blame C
         return '(-%dL-1L)' % sys.maxint
     else:



More information about the Pypy-commit mailing list