> Add -mfunction-return= option to convert function return to call and > return thunks. The default is 'keep', which keeps function return > unmodified. 'thunk' converts function return to call and return thunk. > 'thunk-inline' converts function return to inlined call and return thunk. > 'thunk-extern' converts function return to external call and return > thunk provided in a separate object file. You can control this behavior > for a specific function by using the function attribute function_return. > > Function return thunk is the same as memory thunk for -mindirect-branch= > where the return address is at the top of the stack: > > __x86_return_thunk: > call L2 > L1: > pause > jmp L1 > L2: > lea 8(%rsp), %rsp|lea 4(%esp), %esp > ret > > and function return becomes > > jmp __x86_return_thunk > > -mindirect-branch= tests are updated with -mfunction-return=keep to > avoid false test failures when -mfunction-return=thunk is added to > RUNTESTFLAGS for "make check". > > gcc/ > > * config/i386/i386-protos.h (ix86_output_function_return): New. > * config/i386/i386.c (ix86_set_indirect_branch_type): Also > set function_return_type. > (indirect_thunk_name): Add ret_p to indicate thunk for function > return. > (output_indirect_thunk_function): Pass false to > indirect_thunk_name. > (ix86_output_indirect_branch): Likewise. > (output_indirect_thunk_function): Create alias for function > return thunk if regno < 0. > (ix86_output_function_return): New function. > (ix86_handle_fndecl_attribute): Handle function_return. > (ix86_attribute_table): Add function_return. > * config/i386/i386.h (machine_function): Add > function_return_type. > * config/i386/i386.md (simple_return_internal): Use > ix86_output_function_return. > (simple_return_internal_long): Likewise. > * config/i386/i386.opt (mfunction-return=): New option. > (indirect_branch): Mention -mfunction-return=. > * doc/extend.texi: Document function_return function attribute. > * doc/invoke.texi: Document -mfunction-return= option. > > gcc/testsuite/ > > * gcc.target/i386/indirect-thunk-1.c (dg-options): Add > -mfunction-return=keep. > * gcc.target/i386/indirect-thunk-2.c: Likewise. > * gcc.target/i386/indirect-thunk-3.c: Likewise. > * gcc.target/i386/indirect-thunk-4.c: Likewise. > * gcc.target/i386/indirect-thunk-5.c: Likewise. > * gcc.target/i386/indirect-thunk-6.c: Likewise. > * gcc.target/i386/indirect-thunk-7.c: Likewise. > * gcc.target/i386/indirect-thunk-attr-1.c: Likewise. > * gcc.target/i386/indirect-thunk-attr-2.c: Likewise. > * gcc.target/i386/indirect-thunk-attr-3.c: Likewise. > * gcc.target/i386/indirect-thunk-attr-4.c: Likewise. > * gcc.target/i386/indirect-thunk-attr-5.c: Likewise. > * gcc.target/i386/indirect-thunk-attr-6.c: Likewise. > * gcc.target/i386/indirect-thunk-attr-7.c: Likewise. > * gcc.target/i386/indirect-thunk-attr-8.c: Likewise. > * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise. > * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise. > * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise. > * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise. > * gcc.target/i386/indirect-thunk-extern-1.c: Likewise. > * gcc.target/i386/indirect-thunk-extern-2.c: Likewise. > * gcc.target/i386/indirect-thunk-extern-3.c: Likewise. > * gcc.target/i386/indirect-thunk-extern-4.c: Likewise. > * gcc.target/i386/indirect-thunk-extern-5.c: Likewise. > * gcc.target/i386/indirect-thunk-extern-6.c: Likewise. > * gcc.target/i386/indirect-thunk-extern-7.c: Likewise. > * gcc.target/i386/indirect-thunk-inline-1.c: Likewise. > * gcc.target/i386/indirect-thunk-inline-2.c: Likewise. > * gcc.target/i386/indirect-thunk-inline-3.c: Likewise. > * gcc.target/i386/indirect-thunk-inline-4.c: Likewise. > * gcc.target/i386/indirect-thunk-inline-5.c: Likewise. > * gcc.target/i386/indirect-thunk-inline-6.c: Likewise. > * gcc.target/i386/indirect-thunk-inline-7.c: Likewise. > * gcc.target/i386/ret-thunk-1.c: New test. > * gcc.target/i386/ret-thunk-10.c: Likewise. > * gcc.target/i386/ret-thunk-11.c: Likewise. > * gcc.target/i386/ret-thunk-12.c: Likewise. > * gcc.target/i386/ret-thunk-13.c: Likewise. > * gcc.target/i386/ret-thunk-14.c: Likewise. > * gcc.target/i386/ret-thunk-15.c: Likewise. > * gcc.target/i386/ret-thunk-16.c: Likewise. > * gcc.target/i386/ret-thunk-2.c: Likewise. > * gcc.target/i386/ret-thunk-3.c: Likewise. > * gcc.target/i386/ret-thunk-4.c: Likewise. > * gcc.target/i386/ret-thunk-5.c: Likewise. > * gcc.target/i386/ret-thunk-6.c: Likewise. > * gcc.target/i386/ret-thunk-7.c: Likewise. > * gcc.target/i386/ret-thunk-8.c: Likewise. > * gcc.target/i386/ret-thunk-9.c: Likewise. > > @@ -10846,6 +10888,35 @@ output_indirect_thunk_function (bool need_bnd_p, int > regno) > ASM_OUTPUT_LABEL (asm_out_file, name); > } > > + if (regno < 0) > + { > + /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */ > + char alias[32]; > + > + indirect_thunk_name (alias, regno, need_bnd_p, true); > + ASM_OUTPUT_DEF (asm_out_file, alias, name); > +#if TARGET_MACHO > + if (TARGET_MACHO) > + { > + fputs ("\t.weak_definition\t", asm_out_file); > + assemble_name (asm_out_file, alias); > + fputs ("\n\t.private_extern\t", asm_out_file); > + assemble_name (asm_out_file, alias); > + putc ('\n', asm_out_file); > + } > +#else > + if (USE_HIDDEN_LINKONCE) > + { > + fputs ("\t.globl\t", asm_out_file); > + assemble_name (asm_out_file, alias); > + putc ('\n', asm_out_file); > + fputs ("\t.hidden\t", asm_out_file); > + assemble_name (asm_out_file, alias); > + putc ('\n', asm_out_file); > + } > +#endif
Again, I would hope that using generic function output machinery will avoid dependency on used assembler here. > diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt > index 59e5cc8e7e4..7b17773592b 100644 > --- a/gcc/config/i386/i386.opt > +++ b/gcc/config/i386/i386.opt > @@ -1026,9 +1026,13 @@ mindirect-branch= > Target Report RejectNegative Joined Enum(indirect_branch) > Var(ix86_indirect_branch) Init(indirect_branch_keep) > Convert indirect call and jump to call and return thunks. > > +mfunction-return= > +Target Report RejectNegative Joined Enum(indirect_branch) > Var(ix86_function_return) Init(indirect_branch_keep) > +Convert function return to call and return thunk. I suppose you also want ix86_can_inline_p to check that caller&callee agree about thunk usage for calls/indirect jumps. For returns we do not care as optimized out return is safe? > > +@item function_return("@var{choice}") > +@cindex @code{function_return} function attribute, x86 > +On x86 targets, the @code{function_return} attribute causes the compiler > +to convert function return with @var{choice}. @samp{keep} keeps function > +return unmodified. @samp{thunk} converts function return to call and > +return thunk. @samp{thunk-inline} converts function return to inlined > +call and return thunk. @samp{thunk-extern} converts function return to > +external call and return thunk provided in a separate object file. Again please extend both documentation hunks so it is clear what is purpose of this hack. Honza