diff options
Diffstat (limited to 'gcc/internal-fn.c')
-rw-r--r-- | gcc/internal-fn.c | 60 |
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. */ |