Commits

Armin Rigo committed c5a52cd

Implement the unaligned variants in the C backend.

Comments (0)

Files changed (4)

rpython/memory/gctransform/framework.py

         v_struct = hop.spaceop.args[0]
         v_newvalue = hop.spaceop.args[-1]
         assert opname in ('setfield', 'setarrayitem', 'setinteriorfield',
-                          'raw_store')
+                          'raw_store', 'raw_store_unaligned')
         assert isinstance(v_newvalue.concretetype, lltype.Ptr)
         # XXX for some GCs the skipping if the newvalue is a constant won't be
         # ok

rpython/memory/gctransform/transform.py

     gct_setarrayitem = gct_setfield
     gct_setinteriorfield = gct_setfield
     gct_raw_store = gct_setfield
+    gct_raw_store_unaligned = gct_setfield
 
     gct_getfield = default
 

rpython/translator/c/funcgen.py

         offset = self.expr(op.args[1])
         value = self.expr(op.args[2])
         TYPE = op.args[2].concretetype
-        typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
+        ptrname = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
+        if op.opname.endswith('_unaligned'):
+            typename = cdecl(self.db.gettype(TYPE), '')
+            return ('{\n\t'
+                    '%(typename)s tmpbuf = %(value)s;\n\t'
+                    'memcpy(((char *)%(addr)s) + %(offset)s,\n\t'
+                    '       (char *)&tmpbuf, sizeof(%(typename)s));\n'
+                    '}' % locals())
         return (
-           '((%(typename)s) (((char *)%(addr)s) + %(offset)s))[0] = %(value)s;'
+           '((%(ptrname)s) (((char *)%(addr)s) + %(offset)s))[0] = %(value)s;'
            % locals())
     OP_BARE_RAW_STORE = OP_RAW_STORE
+    OP_RAW_STORE_UNALIGNED = OP_RAW_STORE
+    OP_BARE_RAW_STORE_UNALIGNED = OP_RAW_STORE
 
     def OP_RAW_LOAD(self, op):
         addr = self.expr(op.args[0])
         offset = self.expr(op.args[1])
         result = self.expr(op.result)
         TYPE = op.result.concretetype
-        typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
-        res = (
-          "%(result)s = ((%(typename)s) (((char *)%(addr)s) + %(offset)s))[0];"
+        ptrname = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
+        if op.opname.endswith('_unaligned'):
+            typename = cdecl(self.db.gettype(TYPE), '')
+            return ('{\n\t'
+                    '%(typename)s tmpbuf;\n\t'
+                    'memcpy((char *)&tmpbuf,\n\t'
+                    '       ((char *)%(addr)s) + %(offset)s,\n\t'
+                    '       sizeof(%(typename)s));\n\t'
+                    '%(result)s = tmpbuf;\n'
+                    '}' % locals())
+        return (
+          "%(result)s = ((%(ptrname)s) (((char *)%(addr)s) + %(offset)s))[0];"
           % locals())
-        return res    
+    OP_RAW_LOAD_UNALIGNED = OP_RAW_LOAD
 
     def OP_CAST_PRIMITIVE(self, op):
         TYPE = self.lltypemap(op.result)

rpython/translator/c/test/test_lladdresses.py

 from rpython.rtyper.lltypesystem.llmemory import *
 from rpython.translator.c.test.test_genc import compile
 from rpython.rlib.objectmodel import free_non_gc_object
+from rpython.rlib import rawstorage
 
 def test_null():
     def f():
     assert res == f(42.42)
 
 def test_memory_float_unaligned():
+    py.test.skip("XXX do we really want to support unaligned "
+                 "raw_load/raw_store with the syntax 'addr.float[]'?")
     S = lltype.GcStruct("S", ('c0', lltype.Char), ("x", lltype.Float), ('c1', lltype.Char), ("y", lltype.Float))
     offset = FieldOffset(S, 'x')
     offset_c0 = FieldOffset(S, 'c0')
     assert res == 456
     res = fc(77)
     assert res == 123
+
+def test_rawstorage_int():
+    def f(i):
+        r = rawstorage.alloc_raw_storage(24)
+        rawstorage.raw_storage_setitem(r, 8, i)
+        res = rawstorage.raw_storage_getitem(lltype.Signed, r, 8)
+        rawstorage.free_raw_storage(r)
+        return res
+
+    fc = compile(f, [int])
+    x = fc(1<<30)
+    assert x == 1 << 30
+
+def test_rawstorage_float_unaligned():
+    def f(v):
+        r = rawstorage.alloc_raw_storage(24)
+        rawstorage.raw_storage_setitem_unaligned(r, 3, v)
+        res = rawstorage.raw_storage_getitem_unaligned(lltype.Float, r, 3)
+        rawstorage.free_raw_storage(r)
+        return res
+
+    fc = compile(f, [float])
+    x = fc(3.14)
+    assert x == 3.14