[pypy-commit] pypy stdlib-2.7.6: fix _rawffi bitfield mask calculation

bdkearns noreply at buildbot.pypy.org
Sun Mar 2 16:29:48 CET 2014


Author: Brian Kearns <bdkearns at gmail.com>
Branch: stdlib-2.7.6
Changeset: r69614:0bee77fda190
Date: 2014-03-02 09:32 -0500
http://bitbucket.org/pypy/pypy/changeset/0bee77fda190/

Log:	fix _rawffi bitfield mask calculation

diff --git a/pypy/module/_rawffi/structure.py b/pypy/module/_rawffi/structure.py
--- a/pypy/module/_rawffi/structure.py
+++ b/pypy/module/_rawffi/structure.py
@@ -1,4 +1,3 @@
-
 """ Interpreter-level implementation of structure, exposing ll-structure
 to app-level with apropriate interface
 """
@@ -17,8 +16,8 @@
 from pypy.module._rawffi.interp_rawffi import size_alignment
 from pypy.module._rawffi.interp_rawffi import read_ptr, write_ptr
 from rpython.rlib import clibffi, rgc
-from rpython.rlib.rarithmetic import intmask, signedtype, widen
-from rpython.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong
+from rpython.rlib.rarithmetic import intmask, signedtype, widen, r_uint
+
 
 def unpack_fields(space, w_fields):
     fields_w = space.unpackiterable(w_fields)
@@ -269,31 +268,24 @@
     return x >> 16
 
 def BIT_MASK(x, ll_t):
-    if ll_t is lltype.SignedLongLong:
-        return (r_longlong(1) << x) - 1
-    elif ll_t is lltype.UnsignedLongLong:
-        return (r_ulonglong(1) << x) - 1
-    return (1  << x) -1
+    return (((1 << (x - 1)) - 1) << 1) + 1
 BIT_MASK._annspecialcase_ = 'specialize:arg(1)'
 
 def push_field(self, num, value):
     ptr = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[num])
     TP = lltype.typeOf(value)
-    T = lltype.Ptr(rffi.CArray(TP))
-
     # Handle bitfields
     for c in unroll_letters_for_numbers:
         if LL_TYPEMAP[c] is TP and self.shape.ll_bitsizes:
             # Modify the current value with the bitfield changed
             bitsize = self.shape.ll_bitsizes[num]
             numbits = NUM_BITS(bitsize)
-            lowbit = LOW_BIT(bitsize)
             if numbits:
+                lowbit = LOW_BIT(bitsize)
+                bitmask = BIT_MASK(numbits, TP)
                 value = widen(value)
-                bitmask = BIT_MASK(numbits, TP)
-                #
                 current = widen(read_ptr(ptr, 0, TP))
-                current &= ~ (bitmask << lowbit)
+                current &= ~(bitmask << lowbit)
                 current |= (value & bitmask) << lowbit
                 value = rffi.cast(TP, current)
             break
@@ -302,29 +294,24 @@
 
 def cast_pos(self, i, ll_t):
     pos = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[i])
-    TP = lltype.Ptr(rffi.CArray(ll_t))
     value = read_ptr(pos, 0, ll_t)
-
     # Handle bitfields
     for c in unroll_letters_for_numbers:
         if LL_TYPEMAP[c] is ll_t and self.shape.ll_bitsizes:
             bitsize = self.shape.ll_bitsizes[i]
             numbits = NUM_BITS(bitsize)
-            lowbit = LOW_BIT(bitsize)
             if numbits:
+                lowbit = LOW_BIT(bitsize)
+                bitmask = BIT_MASK(numbits, ll_t)
                 value = widen(rffi.cast(ll_t, value))
-                bitmask = BIT_MASK(numbits, ll_t)
-                #
                 value >>= lowbit
                 value &= bitmask
                 if ll_t is lltype.Bool or signedtype(ll_t._type):
                     sign = (value >> (numbits - 1)) & 1
                     if sign:
-                        one = r_longlong(1) if ll_t is lltype.SignedLongLong else 1
-                        value = value - (one << numbits)
+                        value = value - (1 << numbits)
                 value = rffi.cast(ll_t, value)
             break
-
     return value
 cast_pos._annspecialcase_ = 'specialize:arg(2)'
 
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -534,6 +534,15 @@
         assert (y.a, y.b, y.c) == (0, -7, 0)
         y.free()
 
+    def test_structure_single_longbit_bitfield(self):
+        import _rawffi
+        for s in [('I', 32), ('Q', 64)]:
+            Y = _rawffi.Structure([('a',) + s])
+            y = Y()
+            y.a = 10
+            assert y.a == 10
+            y.free()
+
     def test_invalid_bitfields(self):
         import _rawffi
         raises(TypeError, _rawffi.Structure, [('A', 'c', 1)])


More information about the pypy-commit mailing list