Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 129981) +++ gcc/doc/extend.texi (working copy) @@ -2477,7 +2477,13 @@ defined by shared libraries. @cindex function without a prologue/epilogue code Use this attribute on the ARM, AVR, C4x, IP2K and SPU ports to indicate that the specified function does not need prologue/epilogue sequences generated by -the compiler. It is up to the programmer to provide these sequences. +the compiler. It is up to the programmer to provide these sequences. The +only statements that can be safely included in naked functions are +@code{asm} statements that do not have operands. All other statements, +including declarations of local variables, @code{if} statements, and so +forth, should be avoided. Naked functions should be used to implement the +body of an assembly function, while allowing the compiler to construct +the requisite function declaration for the assembler. @item near @cindex functions which do not handle memory bank switching on 68HC11/68HC12 Index: gcc/doc/tm.texi =================================================================== --- gcc/doc/tm.texi (revision 129981) +++ gcc/doc/tm.texi (working copy) @@ -4297,6 +4297,18 @@ or 3-byte structure is returned at the m @code{SImode} rtx. @end deftypefn +@deftypefn {Target Hook} bool TARGET_USE_REG_FOR_FUNC (void) +When optimization is disabled most decls (including function arguments) +will be allocated local stack slots. + +This hook should return true if they should be allocated pseudo registers +for the current function. Typically this is desirable for functions +annotated with @code{__attribute__((naked))}. This avoids generating +stores to a non-existant stack frame. + +Under normal curcumstances this hook should return false. +@end deftypefn + @node Aggregate Return @subsection How Large Values Are Returned @cindex aggregates as return values Index: gcc/target.h =================================================================== --- gcc/target.h (revision 129981) +++ gcc/target.h (working copy) @@ -827,6 +827,11 @@ struct gcc_target /* Return an rtx for the argument pointer incoming to the current function. */ rtx (*internal_arg_pointer) (void); + + /* Return true if all function parameters should remain in registers, + rather than being spilled to the stack. */ + bool (*use_reg_for_func) (void); + } calls; /* Return the diagnostic message string if conversion from FROMTYPE Index: gcc/testsuite/gcc.target/arm/naked-1.c =================================================================== --- gcc/testsuite/gcc.target/arm/naked-1.c (revision 0) +++ gcc/testsuite/gcc.target/arm/naked-1.c (revision 0) @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* Check that function arguments aren't assigned and copied to stack slots + in naked functions. This ususally happens at -O0 (presumably for + better debugging), but is highly undesirable if we haven't created + a stack frame. */ +void __attribute__((naked)) +foo(int n) +{ + __asm__ volatile ("frob r0\n"); +} + +/* { dg-final { scan-assembler-not "\tstr" } } */ Index: gcc/function.c =================================================================== --- gcc/function.c (revision 129981) +++ gcc/function.c (working copy) @@ -1850,7 +1850,8 @@ use_register_for_decl (const_tree decl) if (DECL_IGNORED_P (decl)) return true; - return (optimize || DECL_REGISTER (decl)); + return (optimize || DECL_REGISTER (decl) + || targetm.calls.use_reg_for_func ()); } /* Return true if TYPE should be passed by invisible reference. */ Index: gcc/target-def.h =================================================================== --- gcc/target-def.h (revision 129981) +++ gcc/target-def.h (working copy) @@ -565,6 +565,7 @@ #define TARGET_FUNCTION_VALUE default_function_value #define TARGET_INTERNAL_ARG_POINTER default_internal_arg_pointer +#define TARGET_USE_REG_FOR_FUNC hook_bool_void_false #define TARGET_CALLS { \ TARGET_PROMOTE_FUNCTION_ARGS, \ @@ -584,7 +585,8 @@ TARGET_ARG_PARTIAL_BYTES, \ TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN, \ TARGET_FUNCTION_VALUE, \ - TARGET_INTERNAL_ARG_POINTER \ + TARGET_INTERNAL_ARG_POINTER, \ + TARGET_USE_REG_FOR_FUNC \ } #ifndef TARGET_UNWIND_TABLES_DEFAULT Index: gcc/config/arm/arm.c =================================================================== --- gcc/config/arm/arm.c (revision 129981) +++ gcc/config/arm/arm.c (working copy) @@ -189,6 +189,7 @@ static unsigned HOST_WIDE_INT arm_shift_ static bool arm_cannot_copy_insn_p (rtx); static bool arm_tls_symbol_p (rtx x); static void arm_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; +static bool arm_use_reg_for_func (void); /* Initialize the GCC target structure. */ @@ -289,6 +290,9 @@ static void arm_output_dwarf_dtprel (FIL #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS arm_setup_incoming_varargs +#undef TARGET_USE_REG_FOR_FUNC +#define TARGET_USE_REG_FOR_FUNC arm_use_reg_for_func + #undef TARGET_DEFAULT_SHORT_ENUMS #define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums @@ -1614,6 +1618,15 @@ arm_current_func_type (void) return cfun->machine->func_type; } + +bool +arm_use_reg_for_func (void) +{ + /* Never spill function parameters to the stack if the function + is naked. */ + return IS_NAKED (arm_current_func_type ()); +} + /* Return 1 if it is possible to return using a single instruction. If SIBLING is non-null, this is a test for a return before a sibling