From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1873) id 8041D3858D1E; Mon, 13 Mar 2023 21:16:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8041D3858D1E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1678742217; bh=D4npNsmYuBL5PyNdm6rfw2oT1RHhlCyXNr7eT9rk6y4=; h=From:To:Subject:Date:From; b=BpeXncEGtL8yZVec2bxphlEtsboe4C3o1JkusPdqKO53XFDYBxn35JkUfnht5Tu2G aPwGfh/cn9FYoR3dRNfoQipz4Q6s2//JhF7V6NliZD/adq/N8gTulbsD4Wj1xAvdtJ rln76uEUEqxS5OQPPMMywohsBSbSwtlOduUgc6+A= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Iain Buclaw To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-6645] d: Refactor DECL_ARGUMENT and DECL_RESULT generation to own function X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/heads/master X-Git-Oldrev: 6360bf9a2d08f08c151464c77c0da53cd702ff25 X-Git-Newrev: 499b07700f0e679a490c2e3b80ca7c382dd737ab Message-Id: <20230313211657.8041D3858D1E@sourceware.org> Date: Mon, 13 Mar 2023 21:16:57 +0000 (GMT) List-Id: https://gcc.gnu.org/g:499b07700f0e679a490c2e3b80ca7c382dd737ab commit r13-6645-g499b07700f0e679a490c2e3b80ca7c382dd737ab Author: Iain Buclaw Date: Sun Mar 12 21:43:31 2023 +0100 d: Refactor DECL_ARGUMENT and DECL_RESULT generation to own function 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. 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. Diff: --- 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);