diff mbox

[RFC] Support -fsanitize=integer-arith-overflow even for vectors

Message ID 20161114095851.GV3541@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Nov. 14, 2016, 9:58 a.m. UTC
Hi!

Working virtually out of Samoa.

The following patch is an attempt to handle -fsanitize=undefined
for vectors.  We already diagnose out of bounds accesses for vector
subscripts, this patch adds expansion for vector UBSAN_CHECK_* and generates
those in ubsan.  Haven't finished up the many vect elements handling (want
to emit a loop for code size).  Is this something we want for GCC 7?


	Jakub
diff mbox

Patch

--- gcc/ubsan.h.jj	2016-01-07 09:42:39.000000000 +0100
+++ gcc/ubsan.h	2016-11-14 10:47:19.887637713 +0100
@@ -52,7 +52,8 @@  extern tree ubsan_create_data (const cha
 extern tree ubsan_type_descriptor (tree, enum ubsan_print_style = UBSAN_PRINT_NORMAL);
 extern tree ubsan_encode_value (tree, bool = false);
 extern bool is_ubsan_builtin_p (tree);
-extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree, tree);
+extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree,
+					  tree, tree *);
 extern tree ubsan_instrument_float_cast (location_t, tree, tree);
 extern tree ubsan_get_source_location_type (void);
 
--- gcc/internal-fn.c.jj	2016-11-07 11:58:43.000000000 +0100
+++ gcc/internal-fn.c	2016-11-14 10:54:46.854918596 +0100
@@ -513,7 +513,7 @@  expand_ubsan_result_store (rtx target, r
 static void
 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
 			tree arg0, tree arg1, bool unsr_p, bool uns0_p,
-			bool uns1_p, bool is_ubsan)
+			bool uns1_p, bool is_ubsan, tree *datap)
 {
   rtx res, target = NULL_RTX;
   tree fn;
@@ -929,7 +929,7 @@  expand_addsub_overflow (location_t loc,
       /* Expand the ubsan builtin call.  */
       push_temp_slots ();
       fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
-					 arg0, arg1);
+					 arg0, arg1, datap);
       expand_normal (fn);
       pop_temp_slots ();
       do_pending_stack_adjust ();
@@ -958,7 +958,8 @@  expand_addsub_overflow (location_t loc,
 /* Add negate overflow checking to the statement STMT.  */
 
 static void
-expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan)
+expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
+		     tree *datap)
 {
   rtx res, op1;
   tree fn;
@@ -1024,7 +1025,7 @@  expand_neg_overflow (location_t loc, tre
       /* Expand the ubsan builtin call.  */
       push_temp_slots ();
       fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
-					 arg1, NULL_TREE);
+					 arg1, NULL_TREE, datap);
       expand_normal (fn);
       pop_temp_slots ();
       do_pending_stack_adjust ();
@@ -1048,7 +1049,8 @@  expand_neg_overflow (location_t loc, tre
 
 static void
 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
-		     bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan)
+		     bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
+		     tree *datap)
 {
   rtx res, op0, op1;
   tree fn, type;
@@ -1685,7 +1687,7 @@  expand_mul_overflow (location_t loc, tre
       /* Expand the ubsan builtin call.  */
       push_temp_slots ();
       fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
-					 arg0, arg1);
+					 arg0, arg1, datap);
       expand_normal (fn);
       pop_temp_slots ();
       do_pending_stack_adjust ();
@@ -1734,6 +1736,81 @@  expand_mul_overflow (location_t loc, tre
     }
 }
 
+static void
+expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
+			      tree arg0, tree arg1)
+{
+  int cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
+  rtx_code_label *done_label = NULL, *beg_label = NULL;
+  rtx cntvar = NULL_RTX;
+  tree eltype = TREE_TYPE (TREE_TYPE (arg0));
+  tree sz = TYPE_SIZE (eltype);
+  tree data = NULL_TREE;
+
+  if (cnt > 4)
+    {
+      do_pending_stack_adjust ();
+      done_label = gen_label_rtx ();
+      beg_label = gen_label_rtx ();
+      cntvar = gen_reg_rtx (word_mode);
+      emit_move_insn (cntvar, const0_rtx);
+      emit_label (beg_label);
+    }
+  for (int i = 0; i < (cnt > 4 ? 1 : cnt); i++)
+    {
+      tree op0, op1;
+      if (cnt > 4)
+	{
+	  gcc_unreachable ();
+	}
+      else
+	{
+	  tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
+	  op0 = fold_build3 (BIT_FIELD_REF, eltype, arg0, sz, bitpos);
+	  op1 = fold_build3 (BIT_FIELD_REF, eltype, arg1, sz, bitpos);
+	}
+      switch (code)
+	{
+	case PLUS_EXPR:
+	  expand_addsub_overflow (loc, PLUS_EXPR, NULL_TREE, op0, op1,
+				  false, false, false, true, &data);
+	  break;
+	case MINUS_EXPR:
+	  if (integer_zerop (op0))
+	    expand_neg_overflow (loc, NULL_TREE, op1, true, &data);
+	  else
+	    expand_addsub_overflow (loc, MINUS_EXPR, NULL_TREE, op0, op1,
+				    false, false, false, true, &data);
+	  break;
+	case MULT_EXPR:
+	  expand_mul_overflow (loc, NULL_TREE, op0, op1, false, false, false,
+			       true, &data);
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+    }
+  if (cnt > 4)
+    {
+      emit_label (done_label);
+    }
+  if (lhs)
+    {
+      struct separate_ops ops;
+      ops.code = code;
+      ops.type = TREE_TYPE (arg0);
+      ops.op0 = arg0;
+      ops.op1 = arg1;
+      ops.op2 = NULL_TREE;
+      ops.location = loc;
+      rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
+      rtx ret = expand_expr_real_2 (&ops, target, TYPE_MODE (TREE_TYPE (arg0)),
+				    EXPAND_NORMAL);
+      if (ret != target)
+	emit_move_insn (target, ret);
+    }
+}
+
 /* Expand UBSAN_CHECK_ADD call STMT.  */
 
 static void
@@ -1743,8 +1820,11 @@  expand_UBSAN_CHECK_ADD (internal_fn, gca
   tree lhs = gimple_call_lhs (stmt);
   tree arg0 = gimple_call_arg (stmt, 0);
   tree arg1 = gimple_call_arg (stmt, 1);
-  expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
-			  false, false, false, true);
+  if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
+    expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
+  else
+    expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
+			    false, false, false, true, NULL);
 }
 
 /* Expand UBSAN_CHECK_SUB call STMT.  */
@@ -1756,11 +1836,13 @@  expand_UBSAN_CHECK_SUB (internal_fn, gca
   tree lhs = gimple_call_lhs (stmt);
   tree arg0 = gimple_call_arg (stmt, 0);
   tree arg1 = gimple_call_arg (stmt, 1);
-  if (integer_zerop (arg0))
-    expand_neg_overflow (loc, lhs, arg1, true);
+  if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
+    expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
+  else if (integer_zerop (arg0))
+    expand_neg_overflow (loc, lhs, arg1, true, NULL);
   else
     expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
-			    false, false, false, true);
+			    false, false, false, true, NULL);
 }
 
 /* Expand UBSAN_CHECK_MUL call STMT.  */
@@ -1772,7 +1854,11 @@  expand_UBSAN_CHECK_MUL (internal_fn, gca
   tree lhs = gimple_call_lhs (stmt);
   tree arg0 = gimple_call_arg (stmt, 0);
   tree arg1 = gimple_call_arg (stmt, 1);
-  expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true);
+  if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
+    expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
+  else
+    expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
+			 NULL);
 }
 
 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion.  */
@@ -1864,17 +1950,17 @@  expand_arith_overflow (enum tree_code co
 	    case MINUS_EXPR:
 	      if (integer_zerop (arg0) && !unsr_p)
 		{
-		  expand_neg_overflow (loc, lhs, arg1, false);
+		  expand_neg_overflow (loc, lhs, arg1, false, NULL);
 		  return;
 		}
 	      /* FALLTHRU */
 	    case PLUS_EXPR:
-	      expand_addsub_overflow (loc, code, lhs, arg0, arg1,
-				      unsr_p, unsr_p, unsr_p, false);
+	      expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
+				      unsr_p, unsr_p, false, NULL);
 	      return;
 	    case MULT_EXPR:
-	      expand_mul_overflow (loc, lhs, arg0, arg1,
-				   unsr_p, unsr_p, unsr_p, false);
+	      expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
+				   unsr_p, unsr_p, false, NULL);
 	      return;
 	    default:
 	      gcc_unreachable ();
@@ -1916,10 +2002,10 @@  expand_arith_overflow (enum tree_code co
 	  arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
 	  if (code != MULT_EXPR)
 	    expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
-				    uns0_p, uns1_p, false);
+				    uns0_p, uns1_p, false, NULL);
 	  else
 	    expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
-				 uns0_p, uns1_p, false);
+				 uns0_p, uns1_p, false, NULL);
 	  return;
 	}
 
--- gcc/ubsan.c.jj	2016-11-14 08:50:02.000000000 +0100
+++ gcc/ubsan.c	2016-11-14 10:48:09.106007948 +0100
@@ -1219,14 +1219,20 @@  instrument_null (gimple_stmt_iterator gs
 
 tree
 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
-			      tree op0, tree op1)
+			      tree op0, tree op1, tree *datap)
 {
   if (flag_sanitize_undefined_trap_on_error)
     return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
 
-  tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
-				 ubsan_type_descriptor (lhstype), NULL_TREE,
-				 NULL_TREE);
+  tree data;
+  if (datap && *datap)
+    data = *datap;
+  else
+    data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
+			      ubsan_type_descriptor (lhstype), NULL_TREE,
+			      NULL_TREE);
+  if (datap)
+    *datap = data;
   enum built_in_function fn_code;
 
   switch (code)
@@ -1272,14 +1278,15 @@  instrument_si_overflow (gimple_stmt_iter
   tree_code code = gimple_assign_rhs_code (stmt);
   tree lhs = gimple_assign_lhs (stmt);
   tree lhstype = TREE_TYPE (lhs);
+  tree lhsinner = VECTOR_TYPE_P (lhstype) ? TREE_TYPE (lhstype) : lhstype;
   tree a, b;
   gimple *g;
 
   /* If this is not a signed operation, don't instrument anything here.
      Also punt on bit-fields.  */
-  if (!INTEGRAL_TYPE_P (lhstype)
-      || TYPE_OVERFLOW_WRAPS (lhstype)
-      || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
+  if (!INTEGRAL_TYPE_P (lhsinner)
+      || TYPE_OVERFLOW_WRAPS (lhsinner)
+      || GET_MODE_BITSIZE (TYPE_MODE (lhsinner)) != TYPE_PRECISION (lhsinner))
     return;
 
   switch (code)
@@ -1316,7 +1323,7 @@  instrument_si_overflow (gimple_stmt_iter
 	 into
 	 _N = UBSAN_CHECK_SUB (0, u);
 	 i = ABS_EXPR<_N>;  */
-      a = build_int_cst (lhstype, 0);
+      a = build_zero_cst (lhstype);
       b = gimple_assign_rhs1 (stmt);
       g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
       a = make_ssa_name (lhstype);
--- gcc/tree-vrp.c.jj	2016-11-02 10:00:16.000000000 +0100
+++ gcc/tree-vrp.c	2016-11-14 10:41:37.928013197 +0100
@@ -10023,7 +10023,11 @@  simplify_internal_call_using_ranges (gim
   tree op1 = gimple_call_arg (stmt, 1);
   tree type;
   if (is_ubsan)
-    type = TREE_TYPE (op0);
+    {
+      type = TREE_TYPE (op0);
+      if (VECTOR_TYPE_P (type))
+	return false;
+    }
   else if (gimple_call_lhs (stmt) == NULL_TREE)
     return false;
   else