+2017-07-31 Uros Bizjak <ubizjak@gmail.com>
+
+ 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) <naked>: Document it.
+
2017-07-31 Martin Liska <mliska@suse.cz>
- * 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.
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
{
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
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 */
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;
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);
+}
\f
/* The following file contains several enumerations and data structures
built from the definitions in i386-builtin-types.def. */
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 }
#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
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
+2017-07-31 Uros Bizjak <ubizjak@gmail.com>
+
+ 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 <tkoenig@gcc.gnu.org>
PR fortran/81581
-/* { 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))
-/* { 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))
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-options "-O2" } */
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+
+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 ();
+}
#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"
" 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])),