public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Ilya Enkovich <enkovich.gnu@gmail.com>
To: gcc-patches@gcc.gnu.org
Subject: [PATCH, Pointer Bounds Checker, Builtins instrumentation 3/5] Expand instrumented builtin calls
Date: Thu, 06 Nov 2014 12:25:00 -0000	[thread overview]
Message-ID: <20141106122459.GB44122@msticlxl57.ims.intel.com> (raw)

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);

             reply	other threads:[~2014-11-06 12:25 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-06 12:25 Ilya Enkovich [this message]
2014-11-14  7:06 ` Jeff Law
2014-11-17 15:12 ` [BUILDROBOT] Build breakage in builtin.c (was: [PATCH, Pointer Bounds Checker, Builtins instrumentation 3/5] Expand instrumented builtin calls) Jan-Benedict Glaw
2014-11-17 15:24   ` Markus Trippelsdorf
2014-11-17 15:27     ` Jan-Benedict Glaw
2014-11-17 16:43       ` Ilya Enkovich
2014-11-17 16:49         ` Jan-Benedict Glaw
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141106122459.GB44122@msticlxl57.ims.intel.com \
    --to=enkovich.gnu@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).