diff mbox series

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

Message ID 20180718153329.GA13951@intel.com
State New
Headers show
Series None | expand

Commit Message

H.J. Lu July 18, 2018, 3:33 p.m. UTC
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

Comments

Richard Biener July 19, 2018, 8:35 a.m. UTC | #1
On Wed, Jul 18, 2018 at 5:33 PM H.J. Lu <hongjiu.lu@intel.com> wrote:
>
> 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?

OK.

Richard.

> 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
>
diff mbox series

Patch

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