| 1 | Extracted from this commit without the ChangeLog to avoid conflicts:
|
| 2 | http://git.savannah.gnu.org/cgit/smalltalk.git/commit/?id=72ada189aba0283c551ead16635c1983968080b8
|
| 3 |
|
| 4 | The upstream commit message is
|
| 5 | From 72ada189aba0283c551ead16635c1983968080b8 Mon Sep 17 00:00:00 2001
|
| 6 | From: Holger Hans Peter Freyther <[email protected]>
|
| 7 | Date: Sat, 7 Nov 2015 18:09:31 +0100
|
| 8 | Subject: libgst: Add alternative multiplication overflow check
|
| 9 |
|
| 10 | Apple clang on OSX and the version on FreeBSD optimize the
|
| 11 | multiplication check away. Clang introduced a family of
|
| 12 | builtins to do the multiplication and check for the overflow
|
| 13 | and GCC made the API usable. For clang we would need to know
|
| 14 | if intptr_t is of type int, long int, long long int and
|
| 15 | then use the smul, smull smulll.
|
| 16 | Luckily clang is adopting the better interface and this is
|
| 17 | what we are starting to use now. This means the new code
|
| 18 | will be used on GCC5 (and later) and some future versions of
|
| 19 | clang.
|
| 20 |
|
| 21 | 2015-11-07 Holger Hans Peter Freyther <[email protected]>
|
| 22 |
|
| 23 | * build-aux/overflow-builtins.m4: Add new macro.
|
| 24 | * configure.ac: Use GST_C_OVERFLOW_BUILTINS macro.
|
| 25 |
|
| 26 | 2015-11-07 Holger Hans Peter Freyther <[email protected]>
|
| 27 |
|
| 28 | * interp.inl: Add alternative mul_with_check implementation.
|
| 29 | ---
|
| 30 | ChangeLog | 5 +++++
|
| 31 | build-aux/overflow-builtins.m4 | 23 +++++++++++++++++++++++
|
| 32 | configure.ac | 1 +
|
| 33 | libgst/ChangeLog | 4 ++++
|
| 34 | libgst/interp.inl | 22 ++++++++++++++++++++++
|
| 35 | 5 files changed, 55 insertions(+)
|
| 36 | create mode 100644 build-aux/overflow-builtins.m4
|
| 37 |
|
| 38 | diff --git a/build-aux/overflow-builtins.m4 b/build-aux/overflow-builtins.m4
|
| 39 | new file mode 100644
|
| 40 | index 00000000..9d050196
|
| 41 | |
| 42 | |
| 43 | @@ -0,0 +1,23 @@
|
| 44 | +dnl Check whether the host supports synchronization builtins.
|
| 45 | +
|
| 46 | +AC_DEFUN([GST_C_OVERFLOW_BUILTINS], [
|
| 47 | + AC_REQUIRE([AC_CANONICAL_HOST])
|
| 48 | + AC_CACHE_CHECK([whether the host supports __builtin_mul_overflow],
|
| 49 | + gst_cv_have_builtin_mul_overflow, [
|
| 50 | + save_CFLAGS="$CFLAGS"
|
| 51 | + case $host in
|
| 52 | + i?86-apple-darwin*) ;;
|
| 53 | + i?86-*-*) CFLAGS="$CFLAGS -march=i486" ;;
|
| 54 | + esac
|
| 55 | + AC_LINK_IFELSE([AC_LANG_PROGRAM([[int foovar = 0;]], [[
|
| 56 | +if (__builtin_mul_overflow(44444, 55555, &foovar))
|
| 57 | + return 23;]])],
|
| 58 | + [gst_cv_have_builtin_mul_overflow=yes],
|
| 59 | + [gst_cv_have_builtin_mul_overflow=no])
|
| 60 | + CFLAGS="$save_CFLAGS"
|
| 61 | + ])
|
| 62 | + if test $gst_cv_have_builtin_mul_overflow = yes; then
|
| 63 | + AC_DEFINE(HAVE_OVERFLOW_BUILTINS, 1,
|
| 64 | + [Define to 1 if the host supports __builtin_*_overflow builtins])
|
| 65 | + fi
|
| 66 | +])
|
| 67 | diff --git a/configure.ac b/configure.ac
|
| 68 | index e789be45..0bac23ef 100644
|
| 69 | |
| 70 | |
| 71 | @@ -243,6 +243,7 @@ GST_C_SYNC_BUILTINS
|
| 72 | if test $gst_cv_have_sync_fetch_and_add = no; then
|
| 73 | AC_MSG_ERROR([Synchronization primitives not found, please use a newer compiler.])
|
| 74 | fi
|
| 75 | +GST_C_OVERFLOW_BUILTINS
|
| 76 |
|
| 77 | GST_LOCK
|
| 78 | AC_SYS_LARGEFILE
|
| 79 | diff --git a/libgst/interp.inl b/libgst/interp.inl
|
| 80 | index e18e27c7..dbc631bc 100644
|
| 81 | |
| 82 | |
| 83 | @@ -159,6 +159,27 @@ sub_with_check (OOP op1, OOP op2, mst_Boolean *overflow)
|
| 84 | OOP
|
| 85 | mul_with_check (OOP op1, OOP op2, mst_Boolean *overflow)
|
| 86 | {
|
| 87 | +#ifdef HAVE_OVERFLOW_BUILTINS
|
| 88 | + intptr_t a = TO_INT (op1);
|
| 89 | + intptr_t b = TO_INT (op2);
|
| 90 | + intptr_t result;
|
| 91 | +
|
| 92 | + if (__builtin_mul_overflow(a, b, &result))
|
| 93 | + {
|
| 94 | + *overflow = true;
|
| 95 | + return FROM_INT(0);
|
| 96 | + }
|
| 97 | +
|
| 98 | +
|
| 99 | + if (result < MIN_ST_INT || result > MAX_ST_INT)
|
| 100 | + {
|
| 101 | + *overflow = true;
|
| 102 | + return FROM_INT(0);
|
| 103 | + }
|
| 104 | +
|
| 105 | + *overflow = false;
|
| 106 | + return FROM_INT(result);
|
| 107 | +#else
|
| 108 | intptr_t a = TO_INT (op1);
|
| 109 | intptr_t b = TO_INT (op2);
|
| 110 | intmax_t result = (intmax_t)a * b;
|
| 111 | @@ -188,6 +209,7 @@ mul_with_check (OOP op1, OOP op2, mst_Boolean *overflow)
|
| 112 | }
|
| 113 |
|
| 114 | return FROM_INT (0);
|
| 115 | +#endif
|
| 116 | }
|
| 117 |
|
| 118 | /* State of the random generator.
|
| 119 | --
|
| 120 | 2.29.2
|
| 121 |
|