[pypy-svn] r25894 - in pypy/dist/pypy/rpython: . lltypesystem rctypes rctypes/test

arigo at codespeak.net arigo at codespeak.net
Mon Apr 17 15:06:43 CEST 2006


Author: arigo
Date: Mon Apr 17 15:06:42 2006
New Revision: 25894

Modified:
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rctypes/rpointer.py
   pypy/dist/pypy/rpython/rctypes/test/test_rpointer.py
Log:
Some support for pointer[non-zero-index].


Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Mon Apr 17 15:06:42 2006
@@ -908,7 +908,16 @@
 
     def _cast_to_adr(self):
         from pypy.rpython.lltypesystem import llmemory
-        return llmemory.fakeaddress(self)
+        if isinstance(self._obj, _subarray):
+            # return an address built as an offset in the whole array
+            parent, parentindex = parentlink(self._obj)
+            T = typeOf(parent)
+            addr = llmemory.fakeaddress(_ptr(Ptr(T), parent))
+            addr += llmemory.itemoffsetof(T, parentindex)
+            return addr
+        else:
+            # normal case
+            return llmemory.fakeaddress(self)
 
 assert not '__dict__' in dir(_ptr)
 

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Mon Apr 17 15:06:42 2006
@@ -335,6 +335,19 @@
     return llops.genop('cast_adr_to_ptr', [v_base_adr],
                        resulttype = ARRAYPTRTYPE)
 
+def gen_add_itemoffset_to_pointer(llops, ITEMTYPE, v_ptr, v_index):
+    "Generates address manipulations equivalent to the C expression ptr+index."
+    from pypy.rpython.lltypesystem import llmemory
+    v_adr = llops.genop('cast_ptr_to_adr', [v_ptr],
+                        resulttype = llmemory.Address)
+    c_ofs = inputconst(lltype.Signed, llmemory.ItemOffset(ITEMTYPE))
+    v_ofs = llops.genop('int_mul', [c_ofs, v_index],
+                        resulttype = lltype.Signed)
+    v_newadr = llops.genop('adr_add', [v_adr, v_ofs],
+                           resulttype = llmemory.Address)
+    return llops.genop('cast_adr_to_ptr', [v_newadr],
+                       resulttype = v_ptr.concretetype)
+
 def rtype_cast_structfield_pointer(hop):
     assert hop.args_s[0].is_constant()
     assert hop.args_s[2].is_constant()

Modified: pypy/dist/pypy/rpython/rctypes/rpointer.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rpointer.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rpointer.py	Mon Apr 17 15:06:42 2006
@@ -1,3 +1,4 @@
+from pypy.rpython.rbuiltin import gen_add_itemoffset_to_pointer
 from pypy.rpython.rmodel import IntegerRepr, inputconst
 from pypy.rpython.error import TyperError
 from pypy.rpython.lltypesystem import lltype
@@ -64,11 +65,14 @@
     def rtype_getitem((r_ptr, _), hop):
         self = r_ptr
         v_ptr, v_index = hop.inputargs(self, lltype.Signed)
+        v_c_ptr = self.getvalue(hop.llops, v_ptr)
         if hop.args_s[1].is_constant() and hop.args_s[1].const == 0:
-            v_c_ptr = self.getvalue(hop. llops, v_ptr)
-            return self.r_contents.return_c_data(hop.llops, v_c_ptr)
+            pass   # skip adding the offset
         else:
-            raise NotImplementedError("XXX: pointer[non-zero-index]")
+            v_c_ptr = gen_add_itemoffset_to_pointer(hop.llops,
+                                                    r_ptr.r_contents.ll_type,
+                                                    v_c_ptr, v_index)
+        return self.r_contents.return_c_data(hop.llops, v_c_ptr)
 
     def rtype_setitem((r_ptr, _), hop):
         # p[0] = x  is not the same as  p.contents.value = x

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rpointer.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rpointer.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rpointer.py	Mon Apr 17 15:06:42 2006
@@ -2,13 +2,14 @@
 Test the rctypes pointer implementation
 """
 
-import py.test
+import py
 import pypy.rpython.rctypes.implementation
 from pypy.translator.translator import TranslationContext
 from pypy import conftest
 from pypy.rpython.test.test_llinterp import interpret
+from pypy.translator.c.test.test_genc import compile
 
-from ctypes import c_int, c_float, POINTER, pointer
+from ctypes import c_int, c_float, POINTER, pointer, Structure
 
 class Test_annotation:
     def test_simple(self):
@@ -251,3 +252,32 @@
         res = interpret(fn, [])
         float_c_data = res.c_data[0]
         assert float_c_data[0] == 6.25
+
+    def test_specialize_getitem_nonzero_index(self):
+        A = c_int * 10
+        class S(Structure):
+            _fields_ = [('x', POINTER(c_int))]
+        def fn():
+            a = A()
+            a[3] = 5
+            s = S()
+            s.x = a
+            return s.x[3]
+        assert fn() == 5
+        res = interpret(fn, [])
+        assert res == 5
+
+class Test_compilation:
+    def test_compile_getitem_nonzero_index(self):
+        A = c_int * 10
+        class S(Structure):
+            _fields_ = [('x', POINTER(c_int))]
+        def func():
+            a = A()
+            a[3] = 5
+            s = S()
+            s.x = a
+            return s.x[3]
+        fn = compile(func, [])
+        res = fn()
+        assert res == 5



More information about the Pypy-commit mailing list