On Wed, Jul 18, 2018 at 5:33 PM H.J. Lu <hongjiu...@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 >