From patchwork Mon Mar 13 21:27:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 66323 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E6A543858C5F for ; Mon, 13 Mar 2023 21:27:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E6A543858C5F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1678742875; bh=Mwg3CROWBl5Pufop29dIwAMnccXRxnFiesmmnpxZkW0=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=kFsSTseBla/8ARSyNp6IVAfhv8teDZ+Nd3ipkq3utyTsHqYTzGHXlWgSjCmTUr+Ow W20BRQKcIQ44v3POHqA2K/KlTGFXAvzhlR7omqbcKFbKA2OotfKz1PLkwBvKNsoKKq Qi9ICo128Zs5HtXhgmClNtW42eXUwFjtb1xI8CII= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) by sourceware.org (Postfix) with ESMTPS id 6775638582AB for ; Mon, 13 Mar 2023 21:27:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6775638582AB Received: from smtp202.mailbox.org (smtp202.mailbox.org [IPv6:2001:67c:2050:b231:465::202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4Pb8rB0FmHz9swK; Mon, 13 Mar 2023 22:27:22 +0100 (CET) To: gcc-patches@gcc.gnu.org Cc: Iain Buclaw Subject: [committed] d: Refactor DECL_ARGUMENT and DECL_RESULT generation to own function Date: Mon, 13 Mar 2023 22:27:19 +0100 Message-Id: <20230313212719.1269-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4Pb8rB0FmHz9swK X-Spam-Status: No, score=-13.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, When looking into PR109108, the reason why things go awry is because of the logic around functions with thunks - they have their definitions generated even when they are external. This subsequently then relied on the detection of whether a function receiving codegen really is extern or not, and this check ultimately prunes too much. This is a first step to both removing the call to `build_decl_tree' from `make_thunk' and the pruning of symbols within the `build_decl_tree' visitor method for functions. Move the generation of DECL_ARGUMENT and DECL_RESULT out of `build_decl_tree' and into their own functions. Bootstrapped and regression tested on x86_64-linux/-m32/-mx32, committed to mainline and backported to the releases/gcc-11 and gcc-12 branches. Regards, Iain. --- gcc/d/ChangeLog: * decl.cc (get_fndecl_result): New function. (get_fndecl_arguments): New function. (DeclVisitor::visit (FuncDeclaration *)): Adjust to call get_fndecl_arguments. (make_thunk): Adjust to call get_fndecl_arguments and get_fndecl_result. (start_function): Adjust to call get_fndecl_result. --- gcc/d/decl.cc | 206 +++++++++++++++++++++++++++++--------------------- 1 file changed, 118 insertions(+), 88 deletions(-) diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index 990ac4016b8..d4e936d0f83 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -117,6 +117,113 @@ gcc_attribute_p (Dsymbol *decl) return false; } +/* Return the DECL_RESULT for the function declaration DECL, create it if it + doesn't already exist. */ + +static tree +get_fndecl_result (FuncDeclaration *decl) +{ + tree fndecl = get_symbol_decl (decl); + tree resdecl = DECL_RESULT (fndecl); + + if (resdecl != NULL_TREE) + return resdecl; + + resdecl = build_decl (make_location_t (decl->loc), RESULT_DECL, + NULL_TREE, TREE_TYPE (TREE_TYPE (fndecl))); + + DECL_ARTIFICIAL (resdecl) = 1; + DECL_IGNORED_P (resdecl) = 1; + DECL_CONTEXT (resdecl) = fndecl; + DECL_RESULT (fndecl) = resdecl; + return resdecl; +} + +/* Return the list of PARAM_DECLs for the function declaration DECL, create it + if it doesn't already exist. */ + +static tree +get_fndecl_arguments (FuncDeclaration *decl) +{ + tree fndecl = get_symbol_decl (decl); + tree param_list = DECL_ARGUMENTS (fndecl); + + if (param_list != NULL_TREE) + return param_list; + + if (decl->fbody) + { + /* Handle special arguments first. */ + + /* `this' parameter: + For nested functions, D still generates a vthis, but it + should not be referenced in any expression. */ + if (decl->vthis) + { + tree parm_decl = get_symbol_decl (decl->vthis); + DECL_ARTIFICIAL (parm_decl) = 1; + TREE_READONLY (parm_decl) = 1; + + if (decl->vthis->type == Type::tvoidptr) + { + /* Replace generic pointer with back-end closure type + (this wins for gdb). */ + tree frame_type = FRAMEINFO_TYPE (get_frameinfo (decl)); + gcc_assert (frame_type != NULL_TREE); + TREE_TYPE (parm_decl) = build_pointer_type (frame_type); + } + + param_list = chainon (param_list, parm_decl); + } + + /* `_arguments' parameter. */ + if (decl->v_arguments) + { + tree parm_decl = get_symbol_decl (decl->v_arguments); + param_list = chainon (param_list, parm_decl); + } + + /* Now add on formal function parameters. */ + size_t n_parameters = decl->parameters ? decl->parameters->length : 0; + + for (size_t i = 0; i < n_parameters; i++) + { + VarDeclaration *param = (*decl->parameters)[i]; + tree parm_decl = get_symbol_decl (param); + + /* Type `noreturn` is a terminator, as no other arguments can possibly + be evaluated after it. */ + if (TREE_TYPE (parm_decl) == noreturn_type_node) + break; + + /* Chain them in the correct order. */ + param_list = chainon (param_list, parm_decl); + } + } + else + { + /* Build parameters from the function type. */ + tree fntype = TREE_TYPE (fndecl); + + for (tree t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t)) + { + if (t == void_list_node) + break; + + tree param = build_decl (DECL_SOURCE_LOCATION (fndecl), + PARM_DECL, NULL_TREE, TREE_VALUE (t)); + DECL_ARG_TYPE (param) = TREE_TYPE (param); + DECL_ARTIFICIAL (param) = 1; + DECL_IGNORED_P (param) = 1; + DECL_CONTEXT (param) = fndecl; + param_list = chainon (param_list, param); + } + } + + DECL_ARGUMENTS (fndecl) = param_list; + return param_list; +} + /* Implements the visitor interface to lower all Declaration AST classes emitted from the D Front-end to GCC trees. All visit methods accept one parameter D, which holds the frontend AST @@ -861,66 +968,17 @@ public: message ("function %s", d->toPrettyChars ()); tree old_context = start_function (d); + tree param_list = get_fndecl_arguments (d); - tree parm_decl = NULL_TREE; - tree param_list = NULL_TREE; - - /* Special arguments... */ - - /* `this' parameter: - For nested functions, D still generates a vthis, but it - should not be referenced in any expression. */ - if (d->vthis) - { - parm_decl = get_symbol_decl (d->vthis); - DECL_ARTIFICIAL (parm_decl) = 1; - TREE_READONLY (parm_decl) = 1; - - if (d->vthis->type == Type::tvoidptr) - { - /* Replace generic pointer with back-end closure type - (this wins for gdb). */ - tree frame_type = FRAMEINFO_TYPE (get_frameinfo (d)); - gcc_assert (frame_type != NULL_TREE); - TREE_TYPE (parm_decl) = build_pointer_type (frame_type); - } - - param_list = chainon (param_list, parm_decl); - d_function_chain->static_chain = parm_decl; - } - - /* _arguments parameter. */ - if (d->v_arguments) - { - parm_decl = get_symbol_decl (d->v_arguments); - param_list = chainon (param_list, parm_decl); - } - - /* formal function parameters. */ - const size_t n_parameters = d->parameters ? d->parameters->length : 0; - - for (size_t i = 0; i < n_parameters; i++) - { - VarDeclaration *param = (*d->parameters)[i]; - - parm_decl = get_symbol_decl (param); - - /* Type `noreturn` is a terminator, as no other arguments can possibly - be evaluated after it. */ - if (TREE_TYPE (parm_decl) == noreturn_type_node) - break; - - /* Chain them in the correct order. */ - param_list = chainon (param_list, parm_decl); - } - - DECL_ARGUMENTS (fndecl) = param_list; DECL_IN_UNITTEST_CONDITION_P (fndecl) = this->in_version_unittest_; rest_of_decl_compilation (fndecl, 1, 0); /* If this is a member function that nested (possibly indirectly) in another function, construct an expession for this member function's static chain by going through parent link of nested classes. */ + if (d->vthis) + d_function_chain->static_chain = get_symbol_decl (d->vthis); + if (d->isThis ()) { AggregateDeclaration *ad = d->isThis (); @@ -935,7 +993,7 @@ public: ad = pd->isAggregateDeclaration (); if (ad == NULL) { - cfun->language->static_chain = this_tree; + d_function_chain->static_chain = this_tree; break; } } @@ -996,7 +1054,7 @@ public: var = build_address (var); tree init = build_call_expr (builtin_decl_explicit (BUILT_IN_VA_START), - 2, var, parm_decl); + 2, var, tree_last (param_list)); declare_local_var (d->v_argptr); add_stmt (init); @@ -1879,34 +1937,12 @@ make_thunk (FuncDeclaration *decl, int offset) { /* Build parameters for functions that are not being compiled, so that they can be correctly cloned in finish_thunk. */ - tree fntype = TREE_TYPE (function); - tree params = NULL_TREE; - - for (tree t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t)) - { - if (t == void_list_node) - break; - - tree param = build_decl (DECL_SOURCE_LOCATION (function), - PARM_DECL, NULL_TREE, TREE_VALUE (t)); - DECL_ARG_TYPE (param) = TREE_TYPE (param); - DECL_ARTIFICIAL (param) = 1; - DECL_IGNORED_P (param) = 1; - DECL_CONTEXT (param) = function; - params = chainon (params, param); - } - - DECL_ARGUMENTS (function) = params; + tree function = get_symbol_decl (decl); + DECL_ARGUMENTS (function) = get_fndecl_arguments (decl); /* Also build the result decl, which is needed when force creating the thunk in gimple inside cgraph_node::expand_thunk. */ - tree resdecl = build_decl (DECL_SOURCE_LOCATION (function), - RESULT_DECL, NULL_TREE, - TREE_TYPE (fntype)); - DECL_ARTIFICIAL (resdecl) = 1; - DECL_IGNORED_P (resdecl) = 1; - DECL_CONTEXT (resdecl) = function; - DECL_RESULT (function) = resdecl; + DECL_RESULT (function) = get_fndecl_result (decl); } } @@ -2018,14 +2054,8 @@ start_function (FuncDeclaration *fd) /* Let GCC know the current scope is this function. */ current_function_decl = fndecl; - tree restype = TREE_TYPE (TREE_TYPE (fndecl)); - tree resdecl = build_decl (make_location_t (fd->loc), RESULT_DECL, - NULL_TREE, restype); - - DECL_RESULT (fndecl) = resdecl; - DECL_CONTEXT (resdecl) = fndecl; - DECL_ARTIFICIAL (resdecl) = 1; - DECL_IGNORED_P (resdecl) = 1; + /* Build the result decl before calling allocate_struct_function. */ + DECL_RESULT (fndecl) = get_fndecl_result (fd); /* Initialize the RTL code for the function. */ allocate_struct_function (fndecl, false);