From patchwork Wed Jan 10 23:06:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jim Wilson X-Patchwork-Id: 858624 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-470757-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="vFbipSNu"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zH4QN3801z9ryk for ; Thu, 11 Jan 2018 10:06:50 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; q=dns; s=default; b=vkXHfPc7vsVm NR+M2vOCjV5mrW+xgCEkSz9VqOqFdt2vlghzhXKvd9iIu+92uLeHLWFCCV6oV1kE wFSxjzCb8t16BxrAYduiCxEMpmIfquOadVQzeUWRgQB09lcjBzWIJ6z0aO8VAc7r YQektP5FHakpvzEkZdUiDSIEOxP6tNo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; s=default; bh=f22v5JJZexcSCn82Wg q4gCNWEg8=; b=vFbipSNu6jkT+PD1vcaVZwb+p0mcs8Br9zZuuCe92QSz3b1W02 qDeB/SrgNIZoe5v54enysWdhZrugTN7NTE60/uAQz7B3OdVrEBQ9I5jAtVoOE9+A KH/eBohJmq30E3GWrU4jLTjBN4/ey9UGbRVLmLcx6ikfGTsa4XG0l1I/Q= Received: (qmail 51267 invoked by alias); 10 Jan 2018 23:06:43 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 51254 invoked by uid 89); 10 Jan 2018 23:06:41 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=cum, nios, Nvidia X-HELO: mail-pg0-f53.google.com Received: from mail-pg0-f53.google.com (HELO mail-pg0-f53.google.com) (74.125.83.53) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 10 Jan 2018 23:06:39 +0000 Received: by mail-pg0-f53.google.com with SMTP id m20so943310pgc.11 for ; Wed, 10 Jan 2018 15:06:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=nDruED5DVZq+ZhKQs0MYYh40zdrdVsTEYZzvtRRxWWY=; b=tfPb9qqjWrxGcBMLUzYMDahyL9oP3piYNBQo6NtIvil6uJma0CSnhDiBcRj6AYHh8A iEqsyDfyLD+gDXSvEz0andIeZo9O3uYwnKNs5D9nNVcEI4qWsoGthXTY3ajlDJwcxg9m Q8cFF5Fr+nYIBZVgjL0arJANazecSrNBEru3n+TTPCfTVsxHZ0793w938FShf2f6nqFK 79epAgtfA6Ri2XIS2JhvlbRfPzxOJJ/mQ6+BfLMmKKxgtekgLhYLV4xbuXIyvH7+FHnb M3rfADfJEd43Y8WRpj+2J/QZmmC4WyjVMLUOBCAjrT3Hqxxu+AbS+JffwzK716ECQJV7 zleg== X-Gm-Message-State: AKGB3mJPuGDBcBMYFjGDcdKzTOuI6sBdhjqajD6/Xq9n0sOYk0aY3JsK P2/N4myof6gFOGgXNaiRasL5zBjVHx0= X-Google-Smtp-Source: ACJfBosQdBCZ4S0qoMg8d4u/KkCC1OSCq2/vjpta0t52v01PX3UjEHs74KJX5fVHNgQF4F5Yv/5Ufw== X-Received: by 10.159.244.3 with SMTP id x3mr20989125plr.192.1515625597464; Wed, 10 Jan 2018 15:06:37 -0800 (PST) Received: from rohan.internal.sifive.com ([12.206.222.5]) by smtp.gmail.com with ESMTPSA id 196sm15675104pfv.74.2018.01.10.15.06.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 10 Jan 2018 15:06:36 -0800 (PST) From: Jim Wilson To: gcc-patches@gcc.gnu.org Cc: Jim Wilson Subject: [PATCH] RISC-V: Add naked function support. Date: Wed, 10 Jan 2018 15:06:29 -0800 Message-Id: <20180110230629.22201-1-jimw@sifive.com> This adds naked function support to the RISC-V port. The basic structure was copied from other ports, so there should be nothing unexpected here. This was tested with a riscv64-linux build and make check. There were no regressions. I also hand checked the info docs to make sure the extend.texi change looked OK. 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. --- gcc/config/riscv/riscv-protos.h | 1 + gcc/config/riscv/riscv.c | 157 +++++++++++++++++++++++++++++++++++----- gcc/config/riscv/riscv.md | 4 +- gcc/doc/extend.texi | 19 +++++ 4 files changed, 163 insertions(+), 18 deletions(-) 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