diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2018-01-06 22:29:55 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2018-01-07 08:54:24 -0800 |
commit | fdddac6289f5bb64a6180b40572cc084f5452aa8 (patch) | |
tree | a9c90cec7a08f8dc59b62ecee0cbbb2329c7df8a | |
parent | ce3c2faad7b9761171ccaa438212318e9063f916 (diff) | |
download | gcc-fdddac6289f5bb64a6180b40572cc084f5452aa8.tar.gz |
x86: Add -mindirect-branch-loop=
Add -mindirect-branch-loop= option to control loop filler in call and
return thunks generated by -mindirect-branch=. 'lfence' uses "lfence"
as loop filler. 'pause' uses "pause" as loop filler. 'nop' uses "nop"
as loop filler. The default is 'lfence'.
gcc/
* config/i386/i386-opts.h (indirect_branch_loop): New.
* config/i386/i386.c (output_indirect_thunk): Support
-mindirect-branch-loop=.
* config/i386/i386.opt (mindirect-branch-loop=): New option.
(indirect_branch_loop): New.
(lfence): Likewise.
(pause): Likewise.
(nop): Likewise.
* doc/invoke.texi: Document -mindirect-branch-loop= option.
gcc/testsuite/
* gcc.target/i386/indirect-thunk-loop-1.c: New test.
* gcc.target/i386/indirect-thunk-loop-2.c: Likewise.
* gcc.target/i386/indirect-thunk-loop-3.c: Likewise.
* gcc.target/i386/indirect-thunk-loop-4.c: Likewise.
* gcc.target/i386/indirect-thunk-loop-5.c: Likewise.
-rw-r--r-- | gcc/config/i386/i386-opts.h | 6 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 19 | ||||
-rw-r--r-- | gcc/config/i386/i386.opt | 17 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c | 19 |
9 files changed, 143 insertions, 3 deletions
diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h index f14cbeee7a1..52f7cb979cc 100644 --- a/gcc/config/i386/i386-opts.h +++ b/gcc/config/i386/i386-opts.h @@ -114,4 +114,10 @@ enum indirect_branch { indirect_branch_thunk_extern }; +enum indirect_branch_loop { + indirect_branch_loop_lfence, + indirect_branch_loop_pause, + indirect_branch_loop_nop +}; + #endif diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index ac4d1f62f50..f327a6b1b62 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10753,8 +10753,23 @@ output_indirect_thunk (bool need_bnd_p, int regno) ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1); - /* lfence . */ - fprintf (asm_out_file, "\tlfence\n"); + switch (ix86_indirect_branch_loop) + { + case indirect_branch_loop_lfence: + /* lfence. */ + fprintf (asm_out_file, "\tlfence\n"); + break; + case indirect_branch_loop_pause: + /* pause. */ + fprintf (asm_out_file, "\tpause\n"); + break; + case indirect_branch_loop_nop: + /* nop. */ + fprintf (asm_out_file, "\tnop\n"); + break; + default: + gcc_unreachable (); + } /* Jump. */ fputs ("\tjmp\t", asm_out_file); diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 22c806206e4..f3e43da0aed 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -1041,3 +1041,20 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline) EnumValue Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern) + +mindirect-branch-loop= +Target Report RejectNegative Joined Enum(indirect_branch_loop) Var(ix86_indirect_branch_loop) Init(indirect_branch_loop_lfence) +Control loop filler in call and return thunk for indirect call and jump. + +Enum +Name(indirect_branch_loop) Type(enum indirect_branch_loop) +Known looop choices (for use with the -mindirect-branch-loop= option): + +EnumValue +Enum(indirect_branch_loop) String(lfence) Value(indirect_branch_loop_lfence) + +EnumValue +Enum(indirect_branch_loop) String(pause) Value(indirect_branch_loop_pause) + +EnumValue +Enum(indirect_branch_loop) String(nop) Value(indirect_branch_loop_nop) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 46461d1ada3..ee5248aba59 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1227,7 +1227,7 @@ See RS/6000 and PowerPC Options. -mstack-protector-guard-offset=@var{offset} @gol -mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol -mgeneral-regs-only -mcall-ms2sysv-xlogues @gol --mindirect-branch=@var{choice}} +-mindirect-branch=@var{choice} -mindirect-branch-loop=@var{choice}} @emph{x86 Windows Options} @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol @@ -26776,6 +26776,13 @@ 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 @code{indirect_branch}. @xref{Function Attributes}. +@item -mindirect-branch-loop=@var{choice} +@opindex -mindirect-branch-boop +Control loop filler in call and return thunk for indirect call and jump. +@samp{lfence} uses @code{lfence} as loop filler. @samp{pause} uses +@code{pause} as loop filler. @samp{nop} uses @code{nop} as loop filler. +The default is @samp{lfence}. + @end table These @samp{-m} switches are supported in addition to the above diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c new file mode 100644 index 00000000000..1b0e2c58775 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=pause -fno-pic" } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch; + +void +male_indirect_jump (long offset) +{ + dispatch(offset); +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler {\tpause} } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c new file mode 100644 index 00000000000..feace47a765 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=nop -fno-pic" } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch[256]; + +void +male_indirect_jump (long offset) +{ + dispatch[offset](offset); +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler {\tnop} } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c new file mode 100644 index 00000000000..ad2165fa7aa --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=lfence -fno-pic" } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch; + +void +male_indirect_jump (long offset) +{ + dispatch(offset); +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler {\tlfence} } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c new file mode 100644 index 00000000000..4ba997da966 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk-inline -mindirect-branch-loop=pause -fno-pic" } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch; + +void +male_indirect_jump (long offset) +{ + dispatch(offset); +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler {\tpause} } } */ +/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */ +/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c new file mode 100644 index 00000000000..10fb2193f5e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk-extern -mindirect-branch-loop=pause -fno-pic" } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch; + +void +male_indirect_jump (long offset) +{ + dispatch(offset); +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ +/* { dg-final { scan-assembler-not {\t(lfence|pause|nop)} } } */ +/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */ |