From 8cad5b143e23668e4b59596972b2249ce2d2d637 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Wed, 10 Jan 2018 23:00:38 +0000 Subject: [PATCH] RISC-V: Add naked function support. 2018-01-10 Kito Cheng gcc/ * config/riscv/riscv-protos.h (riscv_output_return): New. * config/riscv/riscv.c (struct machine_function): New naked_p field. (riscv_attribute_table, riscv_output_return), (riscv_handle_fndecl_attribute, riscv_naked_function_p), (riscv_allocate_stack_slots_for_args, riscv_warn_func_return): New. (riscv_compute_frame_info): Only compute frame->mask if not a naked function. (riscv_expand_prologue): Add early return for naked function. (riscv_expand_epilogue): Likewise. (riscv_function_ok_for_sibcall): Return false for naked function. (riscv_set_current_function): New. (TARGET_SET_CURRENT_FUNCTION, TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS), (TARGET_ATTRIBUTE_TABLE, TARGET_WARN_FUNC_RETURN): New. * config/riscv/riscv.md (simple_return): Call riscv_output_return. * doc/extend.texi (RISC-V Function Attributes): New. Co-Authored-By: Jim Wilson From-SVN: r256462 --- gcc/ChangeLog | 19 ++++ gcc/config/riscv/riscv-protos.h | 1 + gcc/config/riscv/riscv.c | 157 ++++++++++++++++++++++++++++---- gcc/config/riscv/riscv.md | 4 +- gcc/doc/extend.texi | 19 ++++ 5 files changed, 182 insertions(+), 18 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e7590526e0..3662659fee0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2018-01-10 Kito Cheng + Jim Wilson + + * config/riscv/riscv-protos.h (riscv_output_return): New. + * config/riscv/riscv.c (struct machine_function): New naked_p field. + (riscv_attribute_table, riscv_output_return), + (riscv_handle_fndecl_attribute, riscv_naked_function_p), + (riscv_allocate_stack_slots_for_args, riscv_warn_func_return): New. + (riscv_compute_frame_info): Only compute frame->mask if not a naked + function. + (riscv_expand_prologue): Add early return for naked function. + (riscv_expand_epilogue): Likewise. + (riscv_function_ok_for_sibcall): Return false for naked function. + (riscv_set_current_function): New. + (TARGET_SET_CURRENT_FUNCTION, TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS), + (TARGET_ATTRIBUTE_TABLE, TARGET_WARN_FUNC_RETURN): New. + * config/riscv/riscv.md (simple_return): Call riscv_output_return. + * doc/extend.texi (RISC-V Function Attributes): New. + 2018-01-10 Michael Meissner * config/rs6000/rs6000.c (is_complex_IBM_long_double): Explicitly diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 1cf016d850b..0538ede77e4 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -54,6 +54,7 @@ extern bool riscv_split_64bit_move_p (rtx, rtx); extern void riscv_split_doubleword_move (rtx, rtx); extern const char *riscv_output_move (rtx, rtx); extern const char *riscv_output_gpr_save (unsigned); +extern const char *riscv_output_return (); #ifdef RTX_CODE extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx); extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx); diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c index b6270f7bfd7..d260c0ebae1 100644 --- a/gcc/config/riscv/riscv.c +++ b/gcc/config/riscv/riscv.c @@ -127,6 +127,9 @@ struct GTY(()) machine_function { This area is allocated by the callee at the very top of the frame. */ int varargs_size; + /* True if current function is a naked function. */ + bool naked_p; + /* The current frame information, calculated by riscv_compute_frame_info. */ struct riscv_frame_info frame; }; @@ -269,6 +272,23 @@ static const struct riscv_tune_info optimize_size_tune_info = { false, /* slow_unaligned_access */ }; +static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *); + +/* Defining target-specific uses of __attribute__. */ +static const struct attribute_spec riscv_attribute_table[] = +{ + /* Syntax: { name, min_len, max_len, decl_required, type_required, + function_type_required, affects_type_identity, handler, + exclude } */ + + /* The attribute telling no prologue/epilogue. */ + { "naked", 0, 0, true, false, false, false, + riscv_handle_fndecl_attribute, NULL }, + + /* The last attribute spec is set to be NULL. */ + { NULL, 0, 0, false, false, false, false, NULL, NULL } +}; + /* A table describing all the processors GCC knows about. */ static const struct riscv_cpu_info riscv_cpu_info_table[] = { { "rocket", &rocket_tune_info }, @@ -1827,6 +1847,16 @@ riscv_output_move (rtx dest, rtx src) } gcc_unreachable (); } + +const char * +riscv_output_return () +{ + if (cfun->machine->naked_p) + return ""; + + return "ret"; +} + /* Return true if CMP1 is a suitable second operand for integer ordering test CODE. See also the *sCC patterns in riscv.md. */ @@ -2647,6 +2677,50 @@ riscv_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode, cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD; } +/* Handle an attribute requiring a FUNCTION_DECL; + arguments as in struct attribute_spec.handler. */ +static tree +riscv_handle_fndecl_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute only applies to functions", + name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Return true if func is a naked function. */ +static bool +riscv_naked_function_p (tree func) +{ + tree func_decl = func; + if (func == NULL_TREE) + func_decl = current_function_decl; + return NULL_TREE != lookup_attribute ("naked", DECL_ATTRIBUTES (func_decl)); +} + +/* Implement TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS. */ +static bool +riscv_allocate_stack_slots_for_args () +{ + /* Naked functions should not allocate stack slots for arguments. */ + return !riscv_naked_function_p (current_function_decl); +} + +/* Implement TARGET_WARN_FUNC_RETURN. */ +static bool +riscv_warn_func_return (tree decl) +{ + /* Naked functions are implemented entirely in assembly, including the + return sequence, so suppress warnings about this. */ + return !riscv_naked_function_p (decl); +} + /* Implement TARGET_EXPAND_BUILTIN_VA_START. */ static void @@ -3202,23 +3276,26 @@ riscv_compute_frame_info (void) frame = &cfun->machine->frame; memset (frame, 0, sizeof (*frame)); - /* Find out which GPRs we need to save. */ - for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) - if (riscv_save_reg_p (regno)) - frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; - - /* If this function calls eh_return, we must also save and restore the - EH data registers. */ - if (crtl->calls_eh_return) - for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++) - frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; - - /* Find out which FPRs we need to save. This loop must iterate over - the same space as its companion in riscv_for_each_saved_reg. */ - if (TARGET_HARD_FLOAT) - for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) - if (riscv_save_reg_p (regno)) - frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++; + if (!cfun->machine->naked_p) + { + /* Find out which GPRs we need to save. */ + for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) + if (riscv_save_reg_p (regno)) + frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; + + /* If this function calls eh_return, we must also save and restore the + EH data registers. */ + if (crtl->calls_eh_return) + for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++) + frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; + + /* Find out which FPRs we need to save. This loop must iterate over + the same space as its companion in riscv_for_each_saved_reg. */ + if (TARGET_HARD_FLOAT) + for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) + if (riscv_save_reg_p (regno)) + frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++; + } /* At the bottom of the frame are any outgoing stack arguments. */ offset = crtl->outgoing_args_size; @@ -3488,6 +3565,14 @@ riscv_expand_prologue (void) unsigned mask = frame->mask; rtx insn; + if (cfun->machine->naked_p) + { + if (flag_stack_usage_info) + current_function_static_stack_size = 0; + + return; + } + if (flag_stack_usage_info) current_function_static_stack_size = size; @@ -3600,6 +3685,15 @@ riscv_expand_epilogue (bool sibcall_p) bool need_barrier_p = (get_frame_size () + cfun->machine->frame.arg_pointer_offset) != 0; + if (cfun->machine->naked_p) + { + gcc_assert (!sibcall_p); + + emit_jump_insn (gen_return ()); + + return; + } + if (!sibcall_p && riscv_can_use_return_insn ()) { emit_jump_insn (gen_return ()); @@ -4183,9 +4277,27 @@ riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, if (TARGET_SAVE_RESTORE) return false; + /* Don't use sibcall for naked function. */ + if (cfun->machine->naked_p) + return false; + return true; } +/* Implement `TARGET_SET_CURRENT_FUNCTION'. */ +/* Sanity cheching for above function attributes. */ +static void +riscv_set_current_function (tree decl) +{ + if (decl == NULL_TREE + || current_function_decl == NULL_TREE + || current_function_decl == error_mark_node + || !cfun->machine) + return; + + cfun->machine->naked_p = riscv_naked_function_p (decl); +} + /* Implement TARGET_CANNOT_COPY_INSN_P. */ static bool @@ -4241,6 +4353,9 @@ riscv_constant_alignment (const_tree exp, HOST_WIDE_INT align) #undef TARGET_FUNCTION_OK_FOR_SIBCALL #define TARGET_FUNCTION_OK_FOR_SIBCALL riscv_function_ok_for_sibcall +#undef TARGET_SET_CURRENT_FUNCTION +#define TARGET_SET_CURRENT_FUNCTION riscv_set_current_function + #undef TARGET_REGISTER_MOVE_COST #define TARGET_REGISTER_MOVE_COST riscv_register_move_cost #undef TARGET_MEMORY_MOVE_COST @@ -4276,6 +4391,8 @@ riscv_constant_alignment (const_tree exp, HOST_WIDE_INT align) #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS riscv_setup_incoming_varargs +#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS +#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS riscv_allocate_stack_slots_for_args #undef TARGET_STRICT_ARGUMENT_NAMING #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true #undef TARGET_MUST_PASS_IN_STACK @@ -4377,6 +4494,12 @@ riscv_constant_alignment (const_tree exp, HOST_WIDE_INT align) #undef TARGET_CONSTANT_ALIGNMENT #define TARGET_CONSTANT_ALIGNMENT riscv_constant_alignment +#undef TARGET_ATTRIBUTE_TABLE +#define TARGET_ATTRIBUTE_TABLE riscv_attribute_table + +#undef TARGET_WARN_FUNC_RETURN +#define TARGET_WARN_FUNC_RETURN riscv_warn_func_return + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-riscv.h" diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 99341fa00b4..bffe78dd837 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1927,7 +1927,9 @@ (define_insn "simple_return" [(simple_return)] "" - "ret" +{ + return riscv_output_return (); +} [(set_attr "type" "jump") (set_attr "mode" "none")]) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 5f0f4b86cb2..84640f4fde6 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2319,6 +2319,7 @@ GCC plugins may provide their own attributes. * Nios II Function Attributes:: * Nvidia PTX Function Attributes:: * PowerPC Function Attributes:: +* RISC-V Function Attributes:: * RL78 Function Attributes:: * RX Function Attributes:: * S/390 Function Attributes:: @@ -5093,6 +5094,24 @@ function that has different target options than the caller, unless the callee has a subset of the target options of the caller. @end table +@node RISC-V Function Attributes +@subsection RISC-V Function Attributes + +These function attributes are supported by the RISC-V back end: + +@table @code +@item naked +@cindex @code{naked} function attribute, RISC-V +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. +@end table + @node RL78 Function Attributes @subsection RL78 Function Attributes -- 2.30.2