From 2ec580be156c39a87ea39c2f475565bd36d82dcc Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Mon, 31 Jul 2017 12:22:41 +0200 Subject: [PATCH] re PR target/25967 (Add attribute naked for x86) PR target/25967 * config/i386/i386.c (ix86_function_naked): New function. (ix86_can_use_return_insn_p): Return false for naked functions. (ix86_expand_prologue): Skip prologue for naked functions. (ix86_expand_epilogue): Skip epilogue for naked functions and emit trap instruction. (ix86_warn_func_return): New function. (ix86_attribute_table): Add "naked" attribute specification. (TARGET_WARN_FUNC_RETURN): Define. * doc/extend.texi (x86 Function Attributes) : Document it. testsuite/ChangeLog: PR target/25967 * gcc.target/i386/naked-1.c: New test. * gcc.target/i386/naked-2.c: Ditto. * gcc.target/i386/naked-3.c: Ditto. * gcc.target/x86_64/abi/ms-sysv/ms-sysv.c: Remove do_test_body0 stub function, use attribute "naked" instead. * gcc.dg/pr44290-1.c: Use naked_functions effective target. * gcc.dg/pr44290-2.c: Ditto. From-SVN: r250736 --- gcc/ChangeLog | 16 +++++++- gcc/config/i386/i386.c | 35 +++++++++++++++++ gcc/doc/extend.texi | 11 ++++++ gcc/testsuite/ChangeLog | 11 ++++++ gcc/testsuite/gcc.dg/pr44290-1.c | 3 +- gcc/testsuite/gcc.dg/pr44290-2.c | 3 +- gcc/testsuite/gcc.target/i386/naked-1.c | 14 +++++++ gcc/testsuite/gcc.target/i386/naked-2.c | 14 +++++++ gcc/testsuite/gcc.target/i386/naked-3.c | 39 +++++++++++++++++++ .../gcc.target/x86_64/abi/ms-sysv/ms-sysv.c | 15 ++----- 10 files changed, 145 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/naked-1.c create mode 100644 gcc/testsuite/gcc.target/i386/naked-2.c create mode 100644 gcc/testsuite/gcc.target/i386/naked-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ef014763332..54e9a2e6841 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,7 +1,19 @@ +2017-07-31 Uros Bizjak + + PR target/25967 + * config/i386/i386.c (ix86_function_naked): New function. + (ix86_can_use_return_insn_p): Return false for naked functions. + (ix86_expand_prologue): Skip prologue for naked functions. + (ix86_expand_epilogue): Skip epilogue for naked functions + and emit trap instruction. + (ix86_warn_func_return): New function. + (ix86_attribute_table): Add "naked" attribute specification. + (TARGET_WARN_FUNC_RETURN): Define. + * doc/extend.texi (x86 Function Attributes) : Document it. + 2017-07-31 Martin Liska - * gimple-pretty-print.c (dump_gimple_label): Never dump - BB info. + * gimple-pretty-print.c (dump_gimple_label): Never dump BB info. (dump_gimple_bb_header): Always dump BB info. (pp_cfg_jump): Do not append info about BB when dumping a jump. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 47e2ae8ce2e..9a35c995f26 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -8748,6 +8748,15 @@ ix86_function_ms_hook_prologue (const_tree fn) return false; } +static bool +ix86_function_naked (const_tree fn) +{ + if (fn && lookup_attribute ("naked", DECL_ATTRIBUTES (fn))) + return true; + + return false; +} + /* Write the extra assembler code needed to declare a function properly. */ void @@ -12249,6 +12258,9 @@ ix86_can_use_return_insn_p (void) { struct ix86_frame frame; + if (ix86_function_naked (current_function_decl)) + return false; + /* Don't use `ret' instruction in interrupt handler. */ if (! reload_completed || frame_pointer_needed @@ -14327,6 +14339,9 @@ ix86_expand_prologue (void) bool sse_registers_saved; rtx static_chain = NULL_RTX; + if (ix86_function_naked (current_function_decl)) + return; + ix86_finalize_stack_realign_flags (); /* DRAP should not coexist with stack_realign_fp */ @@ -15184,6 +15199,13 @@ ix86_expand_epilogue (int style) bool using_drap; bool restore_stub_is_tail = false; + if (ix86_function_naked (current_function_decl)) + { + /* The program should not reach this point. */ + emit_insn (gen_trap ()); + return; + } + ix86_finalize_stack_realign_flags (); frame = m->frame; @@ -31652,6 +31674,14 @@ ix86_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode); #endif } + +static bool +ix86_warn_func_return (tree decl) +{ + /* Naked functions are implemented entirely in assembly, including the + return sequence, so suppress warnings about this. */ + return !ix86_function_naked (decl); +} /* The following file contains several enumerations and data structures built from the definitions in i386-builtin-types.def. */ @@ -46486,6 +46516,8 @@ static const struct attribute_spec ix86_attribute_table[] = ix86_handle_interrupt_attribute, false }, { "no_caller_saved_registers", 0, 0, false, true, true, ix86_handle_no_caller_saved_registers_attribute, false }, + { "naked", 0, 0, true, false, false, + ix86_handle_fndecl_attribute, false }, /* End element. */ { NULL, 0, 0, false, false, false, NULL, false } @@ -52722,6 +52754,9 @@ ix86_run_selftests (void) #undef TARGET_RETURN_POPS_ARGS #define TARGET_RETURN_POPS_ARGS ix86_return_pops_args +#undef TARGET_WARN_FUNC_RETURN +#define TARGET_WARN_FUNC_RETURN ix86_warn_func_return + #undef TARGET_LEGITIMATE_COMBINED_INSN #define TARGET_LEGITIMATE_COMBINED_INSN ix86_legitimate_combined_insn diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 6934b4cde3e..34cb7d3dd22 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -5370,6 +5370,17 @@ this function attribute to make GCC generate the ``hot-patching'' function prologue used in Win32 API functions in Microsoft Windows XP Service Pack 2 and newer. +@item naked +@cindex @code{naked} function attribute, x86 +This attribute allows the compiler to construct the +requisite function declaration, while allowing the body of the +function to be assembly code. The specified function will not have +prologue/epilogue sequences generated by the compiler. Only basic +@code{asm} statements can safely be included in naked functions +(@pxref{Basic Asm}). While using extended @code{asm} or a mixture of +basic @code{asm} and C code may appear to work, they cannot be +depended upon to work reliably and are not supported. + @item regparm (@var{number}) @cindex @code{regparm} function attribute, x86 @cindex functions that are passed arguments in registers on x86-32 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f7e647c1863..68ef6fc9365 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2017-07-31 Uros Bizjak + + PR target/25967 + * gcc.target/i386/naked-1.c: New test. + * gcc.target/i386/naked-2.c: Ditto. + * gcc.target/i386/naked-3.c: Ditto. + * gcc.target/x86_64/abi/ms-sysv/ms-sysv.c: Remove + do_test_body0 stub function, use attribute "naked" instead. + * gcc.dg/pr44290-1.c: Use naked_functions effective target. + * gcc.dg/pr44290-2.c: Ditto. + 2017-07-31 Thomas Koenig PR fortran/81581 diff --git a/gcc/testsuite/gcc.dg/pr44290-1.c b/gcc/testsuite/gcc.dg/pr44290-1.c index c036db654f3..05d2454fc31 100644 --- a/gcc/testsuite/gcc.dg/pr44290-1.c +++ b/gcc/testsuite/gcc.dg/pr44290-1.c @@ -1,4 +1,5 @@ -/* { dg-do compile { target arm*-*-* avr-*-* mcore-*-* rx-*-* spu-*-* } } */ +/* { dg-do compile } */ +/* { dg-require-effective-target naked_functions } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ static void __attribute__((naked)) diff --git a/gcc/testsuite/gcc.dg/pr44290-2.c b/gcc/testsuite/gcc.dg/pr44290-2.c index 17615366267..07335109114 100644 --- a/gcc/testsuite/gcc.dg/pr44290-2.c +++ b/gcc/testsuite/gcc.dg/pr44290-2.c @@ -1,4 +1,5 @@ -/* { dg-do compile { target arm*-*-* avr-*-* mcore-*-* rx-*-* spu-*-* } } */ +/* { dg-do compile } */ +/* { dg-require-effective-target naked_functions } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ static unsigned long __attribute__((naked)) diff --git a/gcc/testsuite/gcc.target/i386/naked-1.c b/gcc/testsuite/gcc.target/i386/naked-1.c new file mode 100644 index 00000000000..440dbe9ee7a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/naked-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O0" } */ + +/* Verify that __attribute__((naked)) produces a naked function + that does not use ret to return but traps at the end. */ +void +__attribute__((naked)) +foo (void) +{ + __asm__ ("# naked"); +} +/* { dg-final { scan-assembler "# naked" } } */ +/* { dg-final { scan-assembler "ud2" } } */ +/* { dg-final { scan-assembler-not "ret" } } */ diff --git a/gcc/testsuite/gcc.target/i386/naked-2.c b/gcc/testsuite/gcc.target/i386/naked-2.c new file mode 100644 index 00000000000..adcd7121541 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/naked-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O0" } */ + +/* Verify that __attribute__((naked)) produces a naked function + that does not construct a frame. */ +void +__attribute__((naked)) +foo (void) +{ + __asm__ ("# naked"); +} +/* { dg-final { scan-assembler "# naked" } } */ +/* { dg-final { scan-assembler-not "push" } } */ +/* { dg-final { scan-assembler-not "pop" } } */ diff --git a/gcc/testsuite/gcc.target/i386/naked-3.c b/gcc/testsuite/gcc.target/i386/naked-3.c new file mode 100644 index 00000000000..845300d6e4a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/naked-3.c @@ -0,0 +1,39 @@ +/* { dg-do run { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-O2" } */ + +#include +#include +#include + +int data; + +/* Verify that naked function traps at the end. */ + +void +__attribute__((naked, noinline, noclone)) +naked (void) +{ + if (data == 0x12345678) + return; + asm ("ret"); +} + +void handler (int i) +{ + exit (0); +} + +int main () +{ + struct sigaction s; + + sigemptyset (&s.sa_mask); + s.sa_handler = handler; + s.sa_flags = 0; + sigaction (SIGILL, &s, NULL); + + data = 0x12345678; + naked (); + + abort (); +} diff --git a/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c b/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c index caf9e6b5deb..5fdd1e20674 100644 --- a/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c +++ b/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c @@ -169,15 +169,9 @@ static const char *argv0; #define TEST_DATA_OFFSET(f) ((int)__builtin_offsetof(struct test_data, f)) -void __attribute__((used)) -do_test_body0 (void) -{ - __asm__ ("\n" - " .globl " ASMNAME(do_test_body) "\n" -#ifdef __ELF__ - " .type " ASMNAME(do_test_body) ",@function\n" -#endif - ASMNAME(do_test_body) ":\n" +void __attribute__((naked)) +do_test_body (void) +{__asm__ ( " # rax, r10 and r11 are usable here.\n" "\n" " # Save registers.\n" @@ -212,9 +206,6 @@ do_test_body0 (void) " call " ASMNAME(mem_to_regs) "\n" "\n" " retq\n" -#ifdef __ELF__ - " .size " ASMNAME(do_test_body) ",.-" ASMNAME(do_test_body) "\n" -#endif :: "i"(TEST_DATA_OFFSET(regdata[REG_SET_SAVE])), "i"(TEST_DATA_OFFSET(regdata[REG_SET_INPUT])), -- 2.30.2