summaryrefslogtreecommitdiff
path: root/gcc/internal-fn.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/internal-fn.c')
-rw-r--r--gcc/internal-fn.c60
1 files changed, 45 insertions, 15 deletions
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index d64e20da6fd..6008bc0fb21 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -20,8 +20,8 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "internal-fn.h"
#include "tree.h"
+#include "internal-fn.h"
#include "stor-layout.h"
#include "expr.h"
#include "optabs.h"
@@ -181,6 +181,38 @@ expand_ASAN_CHECK (gimple stmt ATTRIBUTE_UNUSED)
gcc_unreachable ();
}
+/* This should get expanded in the sanopt pass. */
+
+static void
+expand_UBSAN_BOUNDS (gimple stmt ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable ();
+}
+
+/* This should get expanded in the sanopt pass. */
+
+static void
+expand_UBSAN_OBJECT_SIZE (gimple stmt ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable ();
+}
+
+
+/* Helper for expand_*_overflow. Store RES into TARGET. */
+
+static void
+expand_ubsan_result_store (rtx target, rtx res)
+{
+ if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
+ /* If this is a scalar in a register that is stored in a wider mode
+ than the declared mode, compute the result into its declared mode
+ and then convert to the wider mode. Our value is the computed
+ expression. */
+ convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
+ else
+ emit_move_insn (target, res);
+}
+
/* Add sub/add overflow checking to the statement STMT.
CODE says whether the operation is +, or -. */
@@ -327,7 +359,7 @@ ubsan_expand_si_overflow_addsub_check (tree_code code, gimple stmt)
emit_label (done_label);
if (lhs)
- emit_move_insn (target, res);
+ expand_ubsan_result_store (target, res);
}
/* Add negate overflow checking to the statement STMT. */
@@ -403,7 +435,7 @@ ubsan_expand_si_overflow_neg_check (gimple stmt)
emit_label (done_label);
if (lhs)
- emit_move_insn (target, res);
+ expand_ubsan_result_store (target, res);
}
/* Add mul overflow checking to the statement STMT. */
@@ -500,7 +532,7 @@ ubsan_expand_si_overflow_mul_check (gimple stmt)
rtx do_overflow = gen_label_rtx ();
rtx hipart_different = gen_label_rtx ();
- int hprec = GET_MODE_PRECISION (hmode);
+ unsigned int hprec = GET_MODE_PRECISION (hmode);
rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
NULL_RTX, 0);
hipart0 = gen_lowpart (hmode, hipart0);
@@ -535,12 +567,11 @@ ubsan_expand_si_overflow_mul_check (gimple stmt)
double_int arg0_min, arg0_max;
if (get_range_info (arg0, &arg0_min, &arg0_max) == VR_RANGE)
{
- if (arg0_max.sle (double_int::max_value (hprec, false))
- && double_int::min_value (hprec, false).sle (arg0_min))
+ unsigned int mprec0 = wi::min_precision (arg0_min, SIGNED);
+ unsigned int mprec1 = wi::min_precision (arg0_max, SIGNED);
+ if (mprec0 <= hprec && mprec1 <= hprec)
op0_small_p = true;
- else if (arg0_max.sle (double_int::max_value (hprec, true))
- && (~double_int::max_value (hprec,
- true)).sle (arg0_min))
+ else if (mprec0 <= hprec + 1 && mprec1 <= hprec + 1)
op0_medium_p = true;
if (!arg0_min.is_negative ())
op0_sign = 0;
@@ -553,12 +584,11 @@ ubsan_expand_si_overflow_mul_check (gimple stmt)
double_int arg1_min, arg1_max;
if (get_range_info (arg1, &arg1_min, &arg1_max) == VR_RANGE)
{
- if (arg1_max.sle (double_int::max_value (hprec, false))
- && double_int::min_value (hprec, false).sle (arg1_min))
+ unsigned int mprec0 = wi::min_precision (arg1_min, SIGNED);
+ unsigned int mprec1 = wi::min_precision (arg1_max, SIGNED);
+ if (mprec0 <= hprec && mprec1 <= hprec)
op1_small_p = true;
- else if (arg1_max.sle (double_int::max_value (hprec, true))
- && (~double_int::max_value (hprec,
- true)).sle (arg1_min))
+ else if (mprec0 <= hprec + 1 && mprec1 <= hprec + 1)
op1_medium_p = true;
if (!arg1_min.is_negative ())
op1_sign = 0;
@@ -798,7 +828,7 @@ ubsan_expand_si_overflow_mul_check (gimple stmt)
emit_label (done_label);
if (lhs)
- emit_move_insn (target, res);
+ expand_ubsan_result_store (target, res);
}
/* Expand UBSAN_CHECK_ADD call STMT. */