[pypy-commit] pypy default: Change cffi's primitive integer type to use int_signext (via type casts)
arigo
noreply at buildbot.pypy.org
Wed Nov 26 18:49:03 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r74739:4af7cfa6d69c
Date: 2014-11-26 18:48 +0100
http://bitbucket.org/pypy/pypy/changeset/4af7cfa6d69c/
Log: Change cffi's primitive integer type to use int_signext (via type
casts)
diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -158,21 +158,14 @@
class W_CTypePrimitiveSigned(W_CTypePrimitive):
- _attrs_ = ['value_fits_long', 'vmin', 'vrangemax']
- _immutable_fields_ = ['value_fits_long', 'vmin', 'vrangemax']
+ _attrs_ = ['value_fits_long', 'value_smaller_than_long']
+ _immutable_fields_ = ['value_fits_long', 'value_smaller_than_long']
is_primitive_integer = True
def __init__(self, *args):
W_CTypePrimitive.__init__(self, *args)
self.value_fits_long = self.size <= rffi.sizeof(lltype.Signed)
- if self.size < rffi.sizeof(lltype.Signed):
- assert self.value_fits_long
- sh = self.size * 8
- self.vmin = r_uint(-1) << (sh - 1)
- self.vrangemax = (r_uint(1) << sh) - 1
- else:
- self.vmin = r_uint(0)
- self.vrangemax = r_uint(-1)
+ self.value_smaller_than_long = self.size < rffi.sizeof(lltype.Signed)
def cast_to_int(self, cdata):
return self.convert_to_object(cdata)
@@ -192,8 +185,17 @@
def convert_from_object(self, cdata, w_ob):
if self.value_fits_long:
value = misc.as_long(self.space, w_ob)
- if self.size < rffi.sizeof(lltype.Signed):
- if r_uint(value) - self.vmin > self.vrangemax:
+ if self.value_smaller_than_long:
+ size = self.size
+ if size == 1:
+ signextended = misc.signext(value, 1)
+ elif size == 2:
+ signextended = misc.signext(value, 2)
+ elif size == 4:
+ signextended = misc.signext(value, 4)
+ else:
+ raise AssertionError("unsupported size")
+ if value != signextended:
self._overflow(w_ob)
misc.write_raw_signed_data(cdata, value, self.size)
else:
@@ -221,7 +223,7 @@
length = w_cdata.get_array_length()
populate_list_from_raw_array(res, buf, length)
return res
- elif self.value_fits_long:
+ elif self.value_smaller_than_long:
res = [0] * w_cdata.get_array_length()
misc.unpack_list_from_raw_array(res, w_cdata._cdata, self.size)
return res
@@ -235,8 +237,8 @@
cdata = rffi.cast(rffi.LONGP, cdata)
copy_list_to_raw_array(int_list, cdata)
else:
- overflowed = misc.pack_list_to_raw_array_bounds(
- int_list, cdata, self.size, self.vmin, self.vrangemax)
+ overflowed = misc.pack_list_to_raw_array_bounds_signed(
+ int_list, cdata, self.size)
if overflowed != 0:
self._overflow(self.space.wrap(overflowed))
return True
@@ -314,8 +316,8 @@
def pack_list_of_items(self, cdata, w_ob):
int_list = self.space.listview_int(w_ob)
if int_list is not None:
- overflowed = misc.pack_list_to_raw_array_bounds(
- int_list, cdata, self.size, r_uint(0), self.vrangemax)
+ overflowed = misc.pack_list_to_raw_array_bounds_unsigned(
+ int_list, cdata, self.size, self.vrangemax)
if overflowed != 0:
self._overflow(self.space.wrap(overflowed))
return True
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -216,6 +216,19 @@
neg_msg = "can't convert negative number to unsigned"
ovf_msg = "long too big to convert"
+ at specialize.arg(1)
+def signext(value, size):
+ # 'value' is sign-extended from 'size' bytes to a full integer.
+ # 'size' should be a constant smaller than a full integer size.
+ if size == rffi.sizeof(rffi.SIGNEDCHAR):
+ return rffi.cast(lltype.Signed, rffi.cast(rffi.SIGNEDCHAR, value))
+ elif size == rffi.sizeof(rffi.SHORT):
+ return rffi.cast(lltype.Signed, rffi.cast(rffi.SHORT, value))
+ elif size == rffi.sizeof(rffi.INT):
+ return rffi.cast(lltype.Signed, rffi.cast(rffi.INT, value))
+ else:
+ raise AssertionError("unsupported size")
+
# ____________________________________________________________
class _NotStandardObject(Exception):
@@ -334,13 +347,26 @@
# ____________________________________________________________
-def pack_list_to_raw_array_bounds(int_list, target, size, vmin, vrangemax):
+def pack_list_to_raw_array_bounds_signed(int_list, target, size):
for TP, TPP in _prim_signed_types:
if size == rffi.sizeof(TP):
ptr = rffi.cast(TPP, target)
for i in range(len(int_list)):
x = int_list[i]
- if r_uint(x) - vmin > vrangemax:
+ y = rffi.cast(TP, x)
+ if x != rffi.cast(lltype.Signed, y):
+ return x # overflow
+ ptr[i] = y
+ return 0
+ raise NotImplementedError("bad integer size")
+
+def pack_list_to_raw_array_bounds_unsigned(int_list, target, size, vrangemax):
+ for TP, TPP in _prim_signed_types:
+ if size == rffi.sizeof(TP):
+ ptr = rffi.cast(TPP, target)
+ for i in range(len(int_list)):
+ x = int_list[i]
+ if r_uint(x) > vrangemax:
return x # overflow
ptr[i] = rffi.cast(TP, x)
return 0
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -340,13 +340,11 @@
guard_value(p166, ConstPtr(ptr72), descr=...)
p167 = call(ConstClass(_ll_0_alloc_with_del___), descr=<Callr . EF=4>)
guard_no_exception(descr=...)
- i112 = int_sub(i160, -32768)
+ i112 = int_signext(i160, 2)
setfield_gc(p167, ConstPtr(null), descr=<FieldP pypy.module._cffi_backend.cdataobj.W_CData.inst__lifeline_ .+>)
setfield_gc(p167, ConstPtr(ptr85), descr=<FieldP pypy.module._cffi_backend.cdataobj.W_CData.inst_ctype .+>)
- i114 = uint_gt(i112, 65535)
+ i114 = int_ne(i112, i160)
guard_false(i114, descr=...)
- i115 = int_and(i112, 65535)
- i116 = int_add(i115, -32768)
--TICK--
i119 = call(ConstClass(_ll_1_raw_malloc_varsize__Signed), 6, descr=<Calli . i EF=4 OS=110>)
raw_store(i119, 0, i116, descr=<ArrayS 2>)
More information about the pypy-commit
mailing list