This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/3] i386: Change indirect_return to function type attribute


In

struct ucontext;
typedef struct ucontext ucontext_t;

extern int (*bar) (ucontext_t *__restrict __oucp,
                   const ucontext_t *__restrict __ucp)
  __attribute__((__indirect_return__));

extern int res;

void
foo (ucontext_t *oucp, ucontext_t *ucp)
{
  res = bar (oucp, ucp);
}

bar() may return via indirect branch.  This patch changes indirect_return
to type attribute to allow indirect_return attribute on variable or type
of function pointer so that ENDBR can be inserted after call to bar().

Tested on i386 and x86-64.  OK for trunk?

Thanks.


H.J.
---
gcc/

	PR target/86560
	* config/i386/i386.c (rest_of_insert_endbranch): Lookup
	indirect_return as function type attribute.
	(ix86_attribute_table): Change indirect_return to function
	type attribute.
	* doc/extend.texi: Update indirect_return attribute.

gcc/testsuite/

	PR target/86560
	* gcc.target/i386/pr86560-1.c: New test.
	* gcc.target/i386/pr86560-2.c: Likewise.
	* gcc.target/i386/pr86560-3.c: Likewise.
---
 gcc/config/i386/i386.c                    | 23 +++++++++++++++--------
 gcc/doc/extend.texi                       |  5 +++--
 gcc/testsuite/gcc.target/i386/pr86560-1.c | 16 ++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr86560-2.c | 16 ++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr86560-3.c | 17 +++++++++++++++++
 5 files changed, 67 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr86560-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr86560-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr86560-3.c

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index aec739c3974..ac27248370b 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2627,16 +2627,23 @@ rest_of_insert_endbranch (void)
 		{
 		  rtx call = get_call_rtx_from (insn);
 		  rtx fnaddr = XEXP (call, 0);
+		  tree fndecl = NULL_TREE;
 
 		  /* Also generate ENDBRANCH for non-tail call which
 		     may return via indirect branch.  */
-		  if (MEM_P (fnaddr)
-		      && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
+		  if (GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
+		    fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
+		  if (fndecl == NULL_TREE)
+		    fndecl = MEM_EXPR (fnaddr);
+		  if (fndecl
+		      && TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
+		      && TREE_CODE (TREE_TYPE (fndecl)) != METHOD_TYPE)
+		    fndecl = NULL_TREE;
+		  if (fndecl && TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
 		    {
-		      tree fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
-		      if (fndecl
-			  && lookup_attribute ("indirect_return",
-					       DECL_ATTRIBUTES (fndecl)))
+		      tree fntype = TREE_TYPE (fndecl);
+		      if (lookup_attribute ("indirect_return",
+					    TYPE_ATTRIBUTES (fntype)))
 			need_endbr = true;
 		    }
 		}
@@ -46101,8 +46108,8 @@ static const struct attribute_spec ix86_attribute_table[] =
     ix86_handle_fndecl_attribute, NULL },
   { "function_return", 1, 1, true, false, false, false,
     ix86_handle_fndecl_attribute, NULL },
-  { "indirect_return", 0, 0, true, false, false, false,
-    ix86_handle_fndecl_attribute, NULL },
+  { "indirect_return", 0, 0, false, true, true, false,
+    NULL, NULL },
 
   /* End element.  */
   { NULL, 0, 0, false, false, false, false, NULL, NULL }
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 8b4d3fd9de3..edeaec6d872 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -5861,8 +5861,9 @@ foo (void)
 @item indirect_return
 @cindex @code{indirect_return} function attribute, x86
 
-The @code{indirect_return} attribute on a function is used to inform
-the compiler that the function may return via indirect branch.
+The @code{indirect_return} attribute can be applied to a function,
+as well as variable or type of function pointer to inform the
+compiler that the function may return via indirect branch.
 
 @end table
 
diff --git a/gcc/testsuite/gcc.target/i386/pr86560-1.c b/gcc/testsuite/gcc.target/i386/pr86560-1.c
new file mode 100644
index 00000000000..a2b702695c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr86560-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection" } */
+/* { dg-final { scan-assembler-times {\mendbr} 2 } } */
+
+struct ucontext;
+
+extern int (*bar) (struct ucontext *)
+  __attribute__((__indirect_return__));
+
+extern int res;
+
+void
+foo (struct ucontext *oucp)
+{
+  res = bar (oucp);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr86560-2.c b/gcc/testsuite/gcc.target/i386/pr86560-2.c
new file mode 100644
index 00000000000..6f01b385afd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr86560-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection" } */
+/* { dg-final { scan-assembler-times {\mendbr} 2 } } */
+
+struct ucontext;
+
+typedef int (*bar_p) (struct ucontext *)
+  __attribute__((__indirect_return__));
+
+extern int res;
+
+void
+foo (bar_p bar, struct ucontext *oucp)
+{
+  res = bar (oucp);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr86560-3.c b/gcc/testsuite/gcc.target/i386/pr86560-3.c
new file mode 100644
index 00000000000..05328e24509
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr86560-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection" } */
+/* { dg-final { scan-assembler-times {\mendbr} 2 } } */
+
+struct ucontext;
+
+extern int (*bar) (struct ucontext *);
+
+extern int res;
+
+void
+foo (struct ucontext *oucp)
+{
+  int (*f) (struct ucontext *) __attribute__((__indirect_return__))
+    = bar;
+  res = f (oucp);
+}
-- 
2.17.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]