[pypy-commit] pypy default: Provide rarithmetic.ovfcheck_int32_add/sub/mul, with a reasonable
arigo
pypy.commits at gmail.com
Mon Nov 28 12:24:29 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r88709:2b67d420c658
Date: 2016-11-28 18:23 +0100
http://bitbucket.org/pypy/pypy/changeset/2b67d420c658/
Log: Provide rarithmetic.ovfcheck_int32_add/sub/mul, with a reasonable
implementation (not special-cased by the JIT, but should generate
only two extra instructions)
diff --git a/rpython/rlib/rarithmetic.py b/rpython/rlib/rarithmetic.py
--- a/rpython/rlib/rarithmetic.py
+++ b/rpython/rlib/rarithmetic.py
@@ -25,6 +25,10 @@
lltype.Unsigned, widen it to lltype.Signed.
Useful because the translator doesn't support
arithmetic on the smaller types.
+ovfcheck_int32_add/sub/mul(x, y)
+ perform an add/sub/mul between two regular integers,
+ but assumes that they fit inside signed 32-bit ints
+ and raises OverflowError if the result no longer does
These are meant to be erased by translation, r_uint
in the process should mark unsigned values, ovfcheck should
@@ -796,6 +800,47 @@
return longlong2float(rffi.cast(rffi.LONGLONG, res))
return rffi.cast(T, res)
+if sys.maxint == 2147483647:
+ def ovfcheck_int32_add(x, y):
+ return ovfcheck(x + y)
+ def ovfcheck_int32_sub(x, y):
+ return ovfcheck(x - y)
+ def ovfcheck_int32_mul(x, y):
+ return ovfcheck(x * y)
+else:
+ def ovfcheck_int32_add(x, y):
+ """x and y are assumed to fit inside the 32-bit rffi.INT;
+ raises OverflowError if the result doesn't fit rffi.INT"""
+ from rpython.rtyper.lltypesystem import lltype, rffi
+ x = rffi.cast(lltype.Signed, x)
+ y = rffi.cast(lltype.Signed, y)
+ z = x + y
+ if z != rffi.cast(lltype.Signed, rffi.cast(rffi.INT, z)):
+ raise OverflowError
+ return z
+
+ def ovfcheck_int32_sub(x, y):
+ """x and y are assumed to fit inside the 32-bit rffi.INT;
+ raises OverflowError if the result doesn't fit rffi.INT"""
+ from rpython.rtyper.lltypesystem import lltype, rffi
+ x = rffi.cast(lltype.Signed, x)
+ y = rffi.cast(lltype.Signed, y)
+ z = x - y
+ if z != rffi.cast(lltype.Signed, rffi.cast(rffi.INT, z)):
+ raise OverflowError
+ return z
+
+ def ovfcheck_int32_mul(x, y):
+ """x and y are assumed to fit inside the 32-bit rffi.INT;
+ raises OverflowError if the result doesn't fit rffi.INT"""
+ from rpython.rtyper.lltypesystem import lltype, rffi
+ x = rffi.cast(lltype.Signed, x)
+ y = rffi.cast(lltype.Signed, y)
+ z = x * y
+ if z != rffi.cast(lltype.Signed, rffi.cast(rffi.INT, z)):
+ raise OverflowError
+ return z
+
# String parsing support
# ---------------------------
diff --git a/rpython/rlib/test/test_rarithmetic.py b/rpython/rlib/test/test_rarithmetic.py
--- a/rpython/rlib/test/test_rarithmetic.py
+++ b/rpython/rlib/test/test_rarithmetic.py
@@ -675,3 +675,11 @@
assert a ^ r_uint32(42) == "a^42"
assert r_uint32(42) ** a == "42**a"
assert a ** r_uint32(42) == "a**42"
+
+def test_ovfcheck_int32():
+ assert ovfcheck_int32_add(-2**30, -2**30) == -2**31
+ py.test.raises(OverflowError, ovfcheck_int32_add, 2**30, 2**30)
+ assert ovfcheck_int32_sub(-2**30, 2**30) == -2**31
+ py.test.raises(OverflowError, ovfcheck_int32_sub, 2**30, -2**30)
+ assert ovfcheck_int32_mul(-2**16, 2**15) == -2**31
+ py.test.raises(OverflowError, ovfcheck_int32_mul, -2**16, -2**15)
More information about the pypy-commit
mailing list