From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1873) id A661B3858410; Wed, 28 Jun 2023 18:52:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A661B3858410 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1687978373; bh=1w3ZadKBisLWWTNYdcMpM+V3mwTVRBET3R6UJve/VUc=; h=From:To:Subject:Date:From; b=boeWtCYk6h7jg+AANWoDXRfS/CXYAAprVU3KotstziyLdDzw0yVS2ZXtQABB3BXWw OWF75URYIAtsBgloVNaNhtjEivTL9FhzfnfJDu8pL38087y4cqUmZvD+pb9G0qeNnq iIXH50nMLbPG9zBs4brkYuqK7M15nQ5gYDyTSE+U= 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-7496] d: Fix wrong code-gen when returning structs by value. X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/heads/releases/gcc-13 X-Git-Oldrev: 09124b7ed7709721e86556b4083ef40925d7489b X-Git-Newrev: f2eeda5652438fe783d4e3878139481a1b8606b6 Message-Id: <20230628185253.A661B3858410@sourceware.org> Date: Wed, 28 Jun 2023 18:52:53 +0000 (GMT) List-Id: https://gcc.gnu.org/g:f2eeda5652438fe783d4e3878139481a1b8606b6 commit r13-7496-gf2eeda5652438fe783d4e3878139481a1b8606b6 Author: Iain Buclaw Date: Wed Jun 28 18:30:31 2023 +0200 d: Fix wrong code-gen when returning structs by value. Since r13-1104, structs have have compute_record_mode called too early on them, causing them to return differently depending on the order that types are generated in, and whether there are forward references. This patch moves the call to compute_record_mode into its own function, and calls it after all fields have been given a size. PR d/106977 PR target/110406 gcc/d/ChangeLog: * types.cc (finish_aggregate_mode): New function. (finish_incomplete_fields): Call finish_aggregate_mode. (finish_aggregate_type): Replace call to compute_record_mode with finish_aggregate_mode. gcc/testsuite/ChangeLog: * gdc.dg/torture/pr110406.d: New test. (cherry picked from commit c201cd3be0d9ab887fafb0c33a9fc287c405c21c) Diff: --- gcc/d/types.cc | 39 +++++++++++++++++++++++++++++---- gcc/testsuite/gdc.dg/torture/pr110406.d | 25 +++++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/gcc/d/types.cc b/gcc/d/types.cc index a4c05bfb75f..f19779fec7d 100644 --- a/gcc/d/types.cc +++ b/gcc/d/types.cc @@ -573,6 +573,35 @@ layout_aggregate_type (AggregateDeclaration *decl, tree type, } } +/* Given a record type TYPE compute the finalized record mode if all fields have + had their types resolved and sizes determined. */ + +void +finish_aggregate_mode (tree type) +{ + for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + /* Fields of type `typeof(*null)' have no size, so let them force the + record type mode to be computed as BLKmode. */ + if (TYPE_MAIN_VARIANT (TREE_TYPE (field)) == noreturn_type_node) + break; + + if (DECL_SIZE (field) == NULL_TREE) + return; + } + + compute_record_mode (type); + + /* Propagate computed mode to all variants of this aggregate type. */ + for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) + { + if (t == type) + continue; + + SET_TYPE_MODE (t, TYPE_MODE (type)); + } +} + /* If the aggregate type TYPE completes the type of any previous field declarations, lay them out now. */ @@ -596,6 +625,9 @@ finish_incomplete_fields (tree type) } relayout_decl (field); + + /* Relayout of field may change the mode of its RECORD_TYPE. */ + finish_aggregate_mode (DECL_FIELD_CONTEXT (field)); } /* No more forward references to process. */ @@ -615,9 +647,6 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize, tree type) SET_TYPE_ALIGN (type, alignsize * BITS_PER_UNIT); TYPE_PACKED (type) = (alignsize == 1); - /* Set the back-end type mode. */ - compute_record_mode (type); - /* Layout all fields now the type is complete. */ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) { @@ -662,6 +691,9 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize, tree type) } } + /* Set the back-end type mode after all fields have had their size set. */ + finish_aggregate_mode (type); + /* Fix up all forward-referenced variants of this aggregate type. */ for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) { @@ -673,7 +705,6 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize, tree type) TYPE_SIZE (t) = TYPE_SIZE (type); TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type); TYPE_PACKED (type) = TYPE_PACKED (type); - SET_TYPE_MODE (t, TYPE_MODE (type)); SET_TYPE_ALIGN (t, TYPE_ALIGN (type)); TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (type); } diff --git a/gcc/testsuite/gdc.dg/torture/pr110406.d b/gcc/testsuite/gdc.dg/torture/pr110406.d new file mode 100644 index 00000000000..c380e4bdec8 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/pr110406.d @@ -0,0 +1,25 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110406 +// { dg-do compile { target i?86-*-* x86_64-*-* } } +// { dg-options "-fdump-tree-optimized" } +struct cpuid_abcd_t +{ + uint eax; + uint ebx; + uint ecx; + uint edx; +}; + +cpuid_abcd_t cpuid_insn(const uint in_eax) +{ + cpuid_abcd_t ret = void; + asm { "cpuid" + : "=a" (ret.eax), + "=b" (ret.ebx), + "=c" (ret.ecx), + "=d" (ret.edx) + : "a" (in_eax) + :; + } + return ret; +} +// { dg-final { scan-tree-dump-not "MEM " "optimized" } }