public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PATCH, Pointer Bounds Checker, Builtins instrumentation 3/5] Expand instrumented builtin calls
@ 2014-11-17 18:41 David Edelsohn
  2014-11-17 19:07 ` Jeff Law
  2014-11-17 20:26 ` Ilya Enkovich
  0 siblings, 2 replies; 28+ messages in thread
From: David Edelsohn @ 2014-11-17 18:41 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: GCC Patches

Ilya,

Thanks for fixing the reference to BNDmode.

However, the patch causes another problem that breaks bootstrap on
AIX.  All of the builtins are emitted as an enum in debug information
and the CHKP enums now cause an overflow in the debug data on AIX.
AIX continues to use stabstrings debugging and does not permit stabs
continuation lines.

This also is failing while building stage1 GCC -- all currently
deployed GCC compilers will fail when building GCC trunk.  No change
to the debugging information produced by GCC trunk will fix this.

Over half of the enum list now contains CHKP.

the first _CHKP builtin is 1156
END_CHKP_BUILTINS is 2381
END_BUILTINS is 2388

All of the normal builtins now appear to be duplicated with CHKP versions.

This is a huge amount of bloat in the common parts of GCC for a
feature that only is available on Intel.  Can you please disable the
feature that creates duplicate CHKP versions of builtins on non-Intel
architectures or at least on AIX (_AIX macro defined)?

Thanks for your earlier fixes, but can we please adjust the
implementation so that it does not break other platforms?

Thanks, David

^ permalink raw reply	[flat|nested] 28+ messages in thread
* [PATCH, Pointer Bounds Checker, Builtins instrumentation 3/5] Expand instrumented builtin calls
@ 2014-11-06 12:25 Ilya Enkovich
  2014-11-14  7:06 ` Jeff Law
  0 siblings, 1 reply; 28+ messages in thread
From: Ilya Enkovich @ 2014-11-06 12:25 UTC (permalink / raw)
  To: gcc-patches

Hi,

This patch adds support of instrumented builtin calls in expand.  Calls are mostly expanded as calls.  But some of them reuse existing string function calls expand functions (memcpy expand was slightly refactored for that).

This is the last enabling patch in this series.  Remaining two patches are performance ones.

Thanks,
Ilya
--
2014-11-06  Ilya Enkovich  <ilya.enkovich@intel.com>

	* builtins.c (expand_builtin_memcpy_args): New.
	(expand_builtin_memcpy): Call expand_builtin_memcpy_args.
	(expand_builtin_memcpy_with_bounds): New.
	(expand_builtin_mempcpy_with_bounds): New.
	(expand_builtin_mempcpy_args): Add orig_exp arg. Support
	BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK
	(expand_builtin_memset_with_bounds): New.
	(expand_builtin_memset_args): Support BUILT_IN_CHKP_MEMSET_NOBND_NOCHK.
	(expand_builtin_with_bounds): New.
	* builtins.h (expand_builtin_with_bounds): New.
	* expr.c (expand_expr_real_1): Support instrumented builtin calls.


diff --git a/gcc/builtins.c b/gcc/builtins.c
index 71fbf09..b34f855 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -133,15 +133,19 @@ static rtx expand_builtin_strcmp (tree, rtx);
 static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
 static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, machine_mode);
 static rtx expand_builtin_memcpy (tree, rtx);
+static rtx expand_builtin_memcpy_with_bounds (tree, rtx);
+static rtx expand_builtin_memcpy_args (tree, tree, tree, rtx, tree);
 static rtx expand_builtin_mempcpy (tree, rtx, machine_mode);
+static rtx expand_builtin_mempcpy_with_bounds (tree, rtx, machine_mode);
 static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
-					machine_mode, int);
+					machine_mode, int, tree);
 static rtx expand_builtin_strcpy (tree, rtx);
 static rtx expand_builtin_strcpy_args (tree, tree, rtx);
 static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
 static rtx expand_builtin_strncpy (tree, rtx);
 static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, machine_mode);
 static rtx expand_builtin_memset (tree, rtx, machine_mode);
+static rtx expand_builtin_memset_with_bounds (tree, rtx, machine_mode);
 static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
 static rtx expand_builtin_bzero (tree);
 static rtx expand_builtin_strlen (tree, rtx, machine_mode);
@@ -3176,6 +3180,81 @@ determine_block_size (tree len, rtx len_rtx,
 			  GET_MODE_MASK (GET_MODE (len_rtx)));
 }
 
+/* Helper function to do the actual work for expand_builtin_memcpy.  */
+
+static rtx
+expand_builtin_memcpy_args (tree dest, tree src, tree len, rtx target, tree exp)
+{
+  const char *src_str;
+  unsigned int src_align = get_pointer_alignment (src);
+  unsigned int dest_align = get_pointer_alignment (dest);
+  rtx dest_mem, src_mem, dest_addr, len_rtx;
+  HOST_WIDE_INT expected_size = -1;
+  unsigned int expected_align = 0;
+  unsigned HOST_WIDE_INT min_size;
+  unsigned HOST_WIDE_INT max_size;
+  unsigned HOST_WIDE_INT probable_max_size;
+
+  /* If DEST is not a pointer type, call the normal function.  */
+  if (dest_align == 0)
+    return NULL_RTX;
+
+  /* If either SRC is not a pointer type, don't do this
+     operation in-line.  */
+  if (src_align == 0)
+    return NULL_RTX;
+
+  if (currently_expanding_gimple_stmt)
+    stringop_block_profile (currently_expanding_gimple_stmt,
+			    &expected_align, &expected_size);
+
+  if (expected_align < dest_align)
+    expected_align = dest_align;
+  dest_mem = get_memory_rtx (dest, len);
+  set_mem_align (dest_mem, dest_align);
+  len_rtx = expand_normal (len);
+  determine_block_size (len, len_rtx, &min_size, &max_size,
+			&probable_max_size);
+  src_str = c_getstr (src);
+
+  /* If SRC is a string constant and block move would be done
+     by pieces, we can avoid loading the string from memory
+     and only stored the computed constants.  */
+  if (src_str
+      && CONST_INT_P (len_rtx)
+      && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
+      && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
+			      CONST_CAST (char *, src_str),
+			      dest_align, false))
+    {
+      dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
+				  builtin_memcpy_read_str,
+				  CONST_CAST (char *, src_str),
+				  dest_align, false, 0);
+      dest_mem = force_operand (XEXP (dest_mem, 0), target);
+      dest_mem = convert_memory_address (ptr_mode, dest_mem);
+      return dest_mem;
+    }
+
+  src_mem = get_memory_rtx (src, len);
+  set_mem_align (src_mem, src_align);
+
+  /* Copy word part most expediently.  */
+  dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
+				     CALL_EXPR_TAILCALL (exp)
+				     ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
+				     expected_align, expected_size,
+				     min_size, max_size, probable_max_size);
+
+  if (dest_addr == 0)
+    {
+      dest_addr = force_operand (XEXP (dest_mem, 0), target);
+      dest_addr = convert_memory_address (ptr_mode, dest_addr);
+    }
+
+  return dest_addr;
+}
+
 /* Expand a call EXP to the memcpy builtin.
    Return NULL_RTX if we failed, the caller should emit a normal call,
    otherwise try to get the result in TARGET, if convenient (and in
@@ -3192,73 +3271,38 @@ expand_builtin_memcpy (tree exp, rtx target)
       tree dest = CALL_EXPR_ARG (exp, 0);
       tree src = CALL_EXPR_ARG (exp, 1);
       tree len = CALL_EXPR_ARG (exp, 2);
-      const char *src_str;
-      unsigned int src_align = get_pointer_alignment (src);
-      unsigned int dest_align = get_pointer_alignment (dest);
-      rtx dest_mem, src_mem, dest_addr, len_rtx;
-      HOST_WIDE_INT expected_size = -1;
-      unsigned int expected_align = 0;
-      unsigned HOST_WIDE_INT min_size;
-      unsigned HOST_WIDE_INT max_size;
-      unsigned HOST_WIDE_INT probable_max_size;
-
-      /* If DEST is not a pointer type, call the normal function.  */
-      if (dest_align == 0)
-	return NULL_RTX;
-
-      /* If either SRC is not a pointer type, don't do this
-	 operation in-line.  */
-      if (src_align == 0)
-	return NULL_RTX;
-
-      if (currently_expanding_gimple_stmt)
-        stringop_block_profile (currently_expanding_gimple_stmt,
-				&expected_align, &expected_size);
-
-      if (expected_align < dest_align)
-	expected_align = dest_align;
-      dest_mem = get_memory_rtx (dest, len);
-      set_mem_align (dest_mem, dest_align);
-      len_rtx = expand_normal (len);
-      determine_block_size (len, len_rtx, &min_size, &max_size,
-			    &probable_max_size);
-      src_str = c_getstr (src);
-
-      /* If SRC is a string constant and block move would be done
-	 by pieces, we can avoid loading the string from memory
-	 and only stored the computed constants.  */
-      if (src_str
-	  && CONST_INT_P (len_rtx)
-	  && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
-	  && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
-				  CONST_CAST (char *, src_str),
-				  dest_align, false))
-	{
-	  dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
-				      builtin_memcpy_read_str,
-				      CONST_CAST (char *, src_str),
-				      dest_align, false, 0);
-	  dest_mem = force_operand (XEXP (dest_mem, 0), target);
-	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
-	  return dest_mem;
-	}
+      return expand_builtin_memcpy_args (dest, src, len, target, exp);
+    }
+}
 
-      src_mem = get_memory_rtx (src, len);
-      set_mem_align (src_mem, src_align);
+/* Expand an instrumented call EXP to the memcpy builtin.
+   Return NULL_RTX if we failed, the caller should emit a normal call,
+   otherwise try to get the result in TARGET, if convenient (and in
+   mode MODE if that's convenient).  */
 
-      /* Copy word part most expediently.  */
-      dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
-				         CALL_EXPR_TAILCALL (exp)
-				         ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
-					 expected_align, expected_size,
-					 min_size, max_size, probable_max_size);
+static rtx
+expand_builtin_memcpy_with_bounds (tree exp, rtx target)
+{
+  if (!validate_arglist (exp,
+			 POINTER_TYPE, POINTER_BOUNDS_TYPE,
+			 POINTER_TYPE, POINTER_BOUNDS_TYPE,
+			 INTEGER_TYPE, VOID_TYPE))
+    return NULL_RTX;
+  else
+    {
+      tree dest = CALL_EXPR_ARG (exp, 0);
+      tree src = CALL_EXPR_ARG (exp, 2);
+      tree len = CALL_EXPR_ARG (exp, 4);
+      rtx res = expand_builtin_memcpy_args (dest, src, len, target, exp);
 
-      if (dest_addr == 0)
+      /* Return src bounds with the result.  */
+      if (res)
 	{
-	  dest_addr = force_operand (XEXP (dest_mem, 0), target);
-	  dest_addr = convert_memory_address (ptr_mode, dest_addr);
+	  rtx bnd = force_reg (BNDmode,
+			       expand_normal (CALL_EXPR_ARG (exp, 1)));
+	  res = chkp_join_splitted_slot (res, bnd);
 	}
-      return dest_addr;
+      return res;
     }
 }
 
@@ -3282,7 +3326,40 @@ expand_builtin_mempcpy (tree exp, rtx target, machine_mode mode)
       tree src = CALL_EXPR_ARG (exp, 1);
       tree len = CALL_EXPR_ARG (exp, 2);
       return expand_builtin_mempcpy_args (dest, src, len,
-					  target, mode, /*endp=*/ 1);
+					  target, mode, /*endp=*/ 1,
+					  exp);
+    }
+}
+
+/* Expand an instrumented call EXP to the mempcpy builtin.
+   Return NULL_RTX if we failed, the caller should emit a normal call,
+   otherwise try to get the result in TARGET, if convenient (and in
+   mode MODE if that's convenient).  */
+
+static rtx
+expand_builtin_mempcpy_with_bounds (tree exp, rtx target, machine_mode mode)
+{
+  if (!validate_arglist (exp,
+			 POINTER_TYPE, POINTER_BOUNDS_TYPE,
+			 POINTER_TYPE, POINTER_BOUNDS_TYPE,
+			 INTEGER_TYPE, VOID_TYPE))
+    return NULL_RTX;
+  else
+    {
+      tree dest = CALL_EXPR_ARG (exp, 0);
+      tree src = CALL_EXPR_ARG (exp, 2);
+      tree len = CALL_EXPR_ARG (exp, 4);
+      rtx res = expand_builtin_mempcpy_args (dest, src, len, target,
+					     mode, 1, exp);
+
+      /* Return src bounds with the result.  */
+      if (res)
+	{
+	  rtx bnd = force_reg (BNDmode,
+			       expand_normal (CALL_EXPR_ARG (exp, 1)));
+	  res = chkp_join_splitted_slot (res, bnd);
+	}
+      return res;
     }
 }
 
@@ -3294,10 +3371,23 @@ expand_builtin_mempcpy (tree exp, rtx target, machine_mode mode)
 
 static rtx
 expand_builtin_mempcpy_args (tree dest, tree src, tree len,
-			     rtx target, machine_mode mode, int endp)
+			     rtx target, machine_mode mode, int endp,
+			     tree orig_exp)
 {
+  tree fndecl = get_callee_fndecl (orig_exp);
+
     /* If return value is ignored, transform mempcpy into memcpy.  */
-  if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
+  if (target == const0_rtx
+      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP
+      && builtin_decl_implicit_p (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP))
+    {
+      tree fn = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP);
+      tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
+					   dest, src, len);
+      return expand_expr (result, target, mode, EXPAND_NORMAL);
+    }
+  else if (target == const0_rtx
+	   && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
     {
       tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
       tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
@@ -3482,7 +3572,8 @@ expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
 
       lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
       ret = expand_builtin_mempcpy_args (dst, src, lenp1,
- 					 target, mode, /*endp=*/2);
+					 target, mode, /*endp=*/2,
+					 exp);
 
       if (ret)
 	return ret;
@@ -3648,6 +3739,36 @@ expand_builtin_memset (tree exp, rtx target, machine_mode mode)
     }
 }
 
+/* Expand expression EXP, which is an instrumented call to the memset builtin.
+   Return NULL_RTX if we failed the caller should emit a normal call, otherwise
+   try to get the result in TARGET, if convenient (and in mode MODE if that's
+   convenient).  */
+
+static rtx
+expand_builtin_memset_with_bounds (tree exp, rtx target, machine_mode mode)
+{
+  if (!validate_arglist (exp,
+			 POINTER_TYPE, POINTER_BOUNDS_TYPE,
+			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
+    return NULL_RTX;
+  else
+    {
+      tree dest = CALL_EXPR_ARG (exp, 0);
+      tree val = CALL_EXPR_ARG (exp, 2);
+      tree len = CALL_EXPR_ARG (exp, 3);
+      rtx res = expand_builtin_memset_args (dest, val, len, target, mode, exp);
+
+      /* Return src bounds with the result.  */
+      if (res)
+	{
+	  rtx bnd = force_reg (BNDmode,
+			       expand_normal (CALL_EXPR_ARG (exp, 1)));
+	  res = chkp_join_splitted_slot (res, bnd);
+	}
+      return res;
+    }
+}
+
 /* Helper function to do the actual work for expand_builtin_memset.  The
    arguments to the builtin_memset call DEST, VAL, and LEN are broken out
    so that this can also be called without constructing an actual CALL_EXPR.
@@ -3776,7 +3897,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
  do_libcall:
   fndecl = get_callee_fndecl (orig_exp);
   fcode = DECL_FUNCTION_CODE (fndecl);
-  if (fcode == BUILT_IN_MEMSET)
+  if (fcode == BUILT_IN_MEMSET
+      || fcode == BUILT_IN_CHKP_MEMSET_NOBND_NOCHK_CHKP)
     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
 				dest, val, len);
   else if (fcode == BUILT_IN_BZERO)
@@ -5849,6 +5971,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
 	}
     }
 
+  /* expand_builtin_with_bounds is supposed to be used for
+     instrumented builtin calls.  */
   gcc_assert (!CALL_WITH_BOUNDS_P (exp));
 
   switch (fcode)
@@ -6909,6 +7033,53 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
   return expand_call (exp, target, ignore);
 }
 
+/* Similar to expand_builtin but is used for instrumented calls.  */
+
+rtx
+expand_builtin_with_bounds (tree exp, rtx target,
+			    rtx subtarget ATTRIBUTE_UNUSED,
+			    machine_mode mode, int ignore)
+{
+  tree fndecl = get_callee_fndecl (exp);
+  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+
+  gcc_assert (CALL_WITH_BOUNDS_P (exp));
+
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+    return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
+
+  gcc_assert (fcode > BEGIN_CHKP_BUILTINS
+	      && fcode < END_CHKP_BUILTINS);
+
+  switch (fcode)
+    {
+    case BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP:
+      target = expand_builtin_memcpy_with_bounds (exp, target);
+      if (target)
+	return target;
+      break;
+
+    case BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP:
+      target = expand_builtin_mempcpy_with_bounds (exp, target, mode);
+      if (target)
+	return target;
+      break;
+
+    case BUILT_IN_CHKP_MEMSET_NOBND_NOCHK_CHKP:
+      target = expand_builtin_memset_with_bounds (exp, target, mode);
+      if (target)
+	return target;
+      break;
+
+    default:
+      break;
+    }
+
+  /* The switch statement above can drop through to cause the function
+     to be called normally.  */
+  return expand_call (exp, target, ignore);
+ }
+
 /* Determine whether a tree node represents a call to a built-in
    function.  If the tree T is a call to a built-in function with
    the right number of arguments of the appropriate types, return
diff --git a/gcc/builtins.h b/gcc/builtins.h
index 7960b01..44bc5df 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -69,6 +69,7 @@ extern tree std_canonical_va_list_type (tree);
 extern void std_expand_builtin_va_start (tree, rtx);
 extern void expand_builtin_trap (void);
 extern rtx expand_builtin (tree, rtx, rtx, machine_mode, int);
+extern rtx expand_builtin_with_bounds (tree, rtx, rtx, machine_mode, int);
 extern enum built_in_function builtin_mathfn_code (const_tree);
 extern tree fold_builtin_expect (location_t, tree, tree, tree);
 extern tree fold_fma (location_t, tree, tree, tree, tree);
diff --git a/gcc/expr.c b/gcc/expr.c
index f824cef..2868f8c 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -10443,7 +10443,11 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 	if (fndecl && DECL_BUILT_IN (fndecl))
 	  {
 	    gcc_assert (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_FRONTEND);
-	    return expand_builtin (exp, target, subtarget, tmode, ignore);
+	    if (CALL_WITH_BOUNDS_P (exp))
+	      return expand_builtin_with_bounds (exp, target, subtarget,
+						 tmode, ignore);
+	    else
+	      return expand_builtin (exp, target, subtarget, tmode, ignore);
 	  }
       }
       return expand_call (exp, target, ignore);

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2014-11-18 18:47 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-17 18:41 [PATCH, Pointer Bounds Checker, Builtins instrumentation 3/5] Expand instrumented builtin calls David Edelsohn
2014-11-17 19:07 ` Jeff Law
2014-11-17 19:12   ` David Edelsohn
2014-11-17 20:06     ` Mike Stump
2014-11-17 20:36     ` Jeff Law
2014-11-17 21:13   ` Ilya Enkovich
2014-11-18  0:53     ` Joseph Myers
2014-11-18  2:06     ` David Edelsohn
2014-11-18  3:00       ` Jeff Law
2014-11-18  2:46     ` David Edelsohn
2014-11-18  2:56       ` Jeff Law
2014-11-18  3:01     ` Jeff Law
2014-11-18 10:57       ` Ilya Enkovich
2014-11-18 12:18         ` Richard Biener
2014-11-18 12:34           ` Ilya Enkovich
2014-11-18 12:38             ` Richard Biener
2014-11-18 13:42               ` Ilya Enkovich
2014-11-18 14:07                 ` David Edelsohn
2014-11-18 14:33                   ` Richard Biener
2014-11-18 14:42                     ` David Edelsohn
2014-11-18 19:09               ` Jeff Law
2014-11-18 19:12                 ` David Edelsohn
2014-11-17 20:26 ` Ilya Enkovich
2014-11-18  3:14   ` Jeff Law
2014-11-18 10:05     ` Richard Biener
2014-11-18 16:33       ` Jeff Law
  -- strict thread matches above, loose matches on Subject: below --
2014-11-06 12:25 Ilya Enkovich
2014-11-14  7:06 ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).