Hello. I have added support for naked functions on the OpenRISC 1200 target it practically inhibits the generation of a function epilogue and prologue and will warn about variables that might use the stack (to prevent unintended code being generated).
As well added a table for attributes where the attribute can only be applied functions, like in the other backends. gcc/ChangeLog: * config/or1k/or1k.cc (or1k_handle_naked_attribute): (has_func_attr): Likewise. (callee_saved_regno_p): Likewise. (or1k_save_reg): Likewise. (or1k_restore_reg): Likewise. (or1k_expand_prologue): Likewise. (or1k_expand_epilogue): Likewise. (or1k_frame_pointer_required): Likewise. (TARGET_ATTRIBUTE_TABLE): Define. --- gcc/config/or1k/or1k.cc | 58 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/gcc/config/or1k/or1k.cc b/gcc/config/or1k/or1k.cc index da2f59062ba..c41ac5ab099 100644 --- a/gcc/config/or1k/or1k.cc +++ b/gcc/config/or1k/or1k.cc @@ -79,6 +79,41 @@ struct GTY(()) machine_function rtx_insn *set_mcount_arg_insn; }; +static tree +or1k_handle_naked_attribute(tree *node, tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + gcc_assert(DECL_P(*node)); + + if (TREE_CODE(*node) != FUNCTION_DECL) + { + warning(OPT_Wattributes, "%qE attribute only applies to functions", + name); + *no_add_attrs = true; + } + return NULL_TREE; +} + +static const struct attribute_spec or1k_attribute_table[] = { + { "naked", 0, 0, true, false, false, false, + or1k_handle_naked_attribute, NULL }, + + /* End element. */ + { NULL, 0, 0, false, false, false, false, NULL, NULL } +}; + +/* Returns true if the provided function has the specified attribute. */ + +static inline bool +has_func_attr(const_tree decl, const char *func_attr) +{ + if (decl == NULL_TREE) + decl = current_function_decl; + + return lookup_attribute(func_attr, DECL_ATTRIBUTES(decl)) != NULL_TREE; +} + /* Zero initialization is OK for all current fields. */ static struct machine_function * @@ -103,6 +138,10 @@ or1k_option_override (void) static bool callee_saved_regno_p (int regno) { + /* Naked functions do not save anything, so let's say NO! */ + if (has_func_attr(NULL_TREE, "naked")) + return false; + /* Check call-saved registers. */ if (!call_used_or_fixed_reg_p (regno) && df_regs_ever_live_p (regno)) return true; @@ -185,6 +224,9 @@ or1k_compute_frame_layout (void) static void or1k_save_reg (int regno, HOST_WIDE_INT offset) { + if (has_func_attr(NULL_TREE, "naked")) + warning(0, "stack usage on naked function %s", current_function_name()); + rtx reg = gen_rtx_REG (Pmode, regno); rtx mem = gen_frame_mem (SImode, plus_constant (Pmode, stack_pointer_rtx, offset)); @@ -198,6 +240,9 @@ or1k_save_reg (int regno, HOST_WIDE_INT offset) static rtx or1k_restore_reg (int regno, HOST_WIDE_INT offset, rtx cfa_restores) { + if (has_func_attr(NULL_TREE, "naked")) + warning(0, "stack usage on naked function %s", current_function_name()); + rtx reg = gen_rtx_REG (Pmode, regno); rtx mem = gen_frame_mem (SImode, plus_constant (Pmode, stack_pointer_rtx, offset)); @@ -217,8 +262,8 @@ or1k_expand_prologue (void) if (flag_stack_usage_info) current_function_static_stack_size = -sp_offset; - /* Early exit for frameless functions. */ - if (sp_offset == 0) + /* Early exit for frameless functions */ + if (sp_offset == 0 || has_func_attr(NULL_TREE, "naked")) goto fini; /* Adjust the stack pointer. For large stack offsets we will @@ -325,7 +370,7 @@ or1k_expand_epilogue (void) rtx insn, cfa_restores = NULL; sp_offset = cfun->machine->total_size; - if (sp_offset == 0) + if (sp_offset == 0 || has_func_attr(NULL_TREE, "naked")) return; reg_offset = cfun->machine->local_vars_size + cfun->machine->args_size; @@ -509,6 +554,10 @@ or1k_return_addr (int, rtx frame) static bool or1k_frame_pointer_required () { + /* Frame pointer is not required for naked functions */ + if (has_func_attr(NULL_TREE, "naked")) + return false; + /* ??? While IRA checks accesses_prior_frames, reload does not. We do want the frame pointer for this case. */ return (crtl->accesses_prior_frames); @@ -2212,6 +2261,9 @@ or1k_output_mi_thunk (FILE *file, tree thunk_fndecl, #undef TARGET_HAVE_SPECULATION_SAFE_VALUE #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed +#undef TARGET_ATTRIBUTE_TABLE +#define TARGET_ATTRIBUTE_TABLE or1k_attribute_table + /* Calling Conventions. */ #undef TARGET_FUNCTION_VALUE #define TARGET_FUNCTION_VALUE or1k_function_value -- 2.30.2