aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKito Cheng <kito.cheng@gmail.com>2018-01-10 23:00:38 +0000
committerJim Wilson <wilson@gcc.gnu.org>2018-01-10 15:00:38 -0800
commit8cad5b143e23668e4b59596972b2249ce2d2d637 (patch)
tree25f9cc56191853d6733003431c1a581d6d5f80fa
parent3ec62f54062b50d0c9e0ed55f4d83147df56fc92 (diff)
downloadgcc-8cad5b143e23668e4b59596972b2249ce2d2d637.zip
gcc-8cad5b143e23668e4b59596972b2249ce2d2d637.tar.gz
gcc-8cad5b143e23668e4b59596972b2249ce2d2d637.tar.bz2
RISC-V: Add naked function support.
2018-01-10 Kito Cheng <kito.cheng@gmail.com> 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 <jimw@sifive.com> From-SVN: r256462
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/config/riscv/riscv-protos.h1
-rw-r--r--gcc/config/riscv/riscv.c157
-rw-r--r--gcc/config/riscv/riscv.md4
-rw-r--r--gcc/doc/extend.texi19
5 files changed, 182 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9e75905..3662659 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+2018-01-10 Kito Cheng <kito.cheng@gmail.com>
+ Jim Wilson <jimw@sifive.com>
+
+ * 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 <meissner@linux.vnet.ibm.com>
* 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 1cf016d..0538ede 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 b6270f7..d260c0e 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 99341fa..bffe78d 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 5f0f4b8..84640f4 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