[pypy-commit] pypy default: fix for the bitmask calculation of bitfields in _rawffi and ctypes

bivab noreply at buildbot.pypy.org
Wed Jun 19 20:18:42 CEST 2013


Author: David Schneider <david.schneider at picle.org>
Branch: 
Changeset: r64940:fcd5bdf14412
Date: 2013-06-19 13:10 -0500
http://bitbucket.org/pypy/pypy/changeset/fcd5bdf14412/

Log:	fix for the bitmask calculation of bitfields in _rawffi and ctypes
	On 32 bit systems longlong bitfields need a bitmask that is larger
	than a word

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
@@ -15,7 +15,8 @@
 from pypy.module._rawffi.interp_rawffi import size_alignment, LL_TYPEMAP
 from pypy.module._rawffi.interp_rawffi import unroll_letters_for_numbers
 from rpython.rlib import clibffi
-from rpython.rlib.rarithmetic import intmask, r_uint, signedtype, widen
+from rpython.rlib.rarithmetic import intmask, signedtype, widen
+from rpython.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong
 
 def unpack_fields(space, w_fields):
     fields_w = space.unpackiterable(w_fields)
@@ -260,10 +261,17 @@
 
 def LOW_BIT(x):
     return x & 0xFFFF
+
 def NUM_BITS(x):
     return x >> 16
-def BIT_MASK(x):
-    return (1 << x) - 1
+
+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
+BIT_MASK._annspecialcase_ = 'specialize:arg(1)'
 
 def push_field(self, num, value):
     ptr = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[num])
@@ -279,8 +287,9 @@
             lowbit = LOW_BIT(bitsize)
             if numbits:
                 value = widen(value)
+                bitmask = BIT_MASK(numbits, TP)
+                #
                 current = widen(rffi.cast(T, ptr)[0])
-                bitmask = BIT_MASK(numbits)
                 current &= ~ (bitmask << lowbit)
                 current |= (value & bitmask) << lowbit
                 value = rffi.cast(TP, current)
@@ -301,13 +310,16 @@
             numbits = NUM_BITS(bitsize)
             lowbit = LOW_BIT(bitsize)
             if numbits:
-                value = widen(value)
+                value = widen(rffi.cast(ll_t, value))
+                bitmask = BIT_MASK(numbits, ll_t)
+                #
                 value >>= lowbit
-                value &= BIT_MASK(numbits)
+                value &= bitmask
                 if ll_t is lltype.Bool or signedtype(ll_t._type):
                     sign = (value >> (numbits - 1)) & 1
                     if sign:
-                        value = value - (1 << numbits)
+                        one = r_longlong(1) if ll_t is lltype.SignedLongLong else 1
+                        value = value - (one << numbits)
                 value = rffi.cast(ll_t, value)
             break
 


More information about the pypy-commit mailing list