From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mout-p-202.mailbox.org (mout-p-202.mailbox.org [IPv6:2001:67c:2050:0:465::202]) by sourceware.org (Postfix) with ESMTPS id DDF6C385843E for ; Mon, 15 Aug 2022 20:39:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DDF6C385843E Received: from smtp102.mailbox.org (smtp102.mailbox.org [IPv6:2001:67c:2050:b231:465::102]) (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-202.mailbox.org (Postfix) with ESMTPS id 4M65jR0pm8z9sSr; Mon, 15 Aug 2022 22:39:07 +0200 (CEST) From: Iain Buclaw To: gcc-patches@gcc.gnu.org Subject: [committed] d: Fix internal compiler error: Segmentation fault at gimple-expr.cc:88 Date: Mon, 15 Aug 2022 22:39:05 +0200 Message-Id: <20220815203905.2828358-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 4M65jR0pm8z9sSr X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, WEIRD_PORT 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-List-Received-Date: Mon, 15 Aug 2022 20:39:13 -0000 Hi, This patch fixes an ICE in the middle-end caused by the D front-end's code generation for the special enum representing native complex types. Because complex types are deprecated in the language, the new way to expose native complex types is by defining an enum with a basetype of a library-defined struct that is implicitly treated as-if it is native. As casts are not implicitly added by the front-end when downcasting from enum to its underlying type, we must insert an explicit cast during the code generation pass. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, committed to mainline and backported to the releases/gcc-12 branch. Regards, Iain. --- PR d/106623 gcc/d/ChangeLog: * d-codegen.cc (underlying_complex_expr): New function. (d_build_call): Handle passing native complex objects as the library-defined equivalent. * d-tree.h (underlying_complex_expr): Declare. * expr.cc (ExprVisitor::visit (DotVarExp *)): Call underlying_complex_expr instead of build_vconvert. gcc/testsuite/ChangeLog: * gdc.dg/torture/pr106623.d: New test. --- gcc/d/d-codegen.cc | 34 +++++++++++++++++++++++++ gcc/d/d-tree.h | 1 + gcc/d/expr.cc | 2 +- gcc/testsuite/gdc.dg/torture/pr106623.d | 28 ++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gdc.dg/torture/pr106623.d diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index d02da1f81e3..aa6bc9e53e4 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -1588,6 +1588,32 @@ complex_expr (tree type, tree re, tree im) type, re, im); } +/* Build a two-field record TYPE representing the complex expression EXPR. */ + +tree +underlying_complex_expr (tree type, tree expr) +{ + gcc_assert (list_length (TYPE_FIELDS (type)) == 2); + + expr = d_save_expr (expr); + + /* Build a constructor from the real and imaginary parts. */ + if (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (expr)) && + (!INDIRECT_REF_P (expr) + || !CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (expr, 0))))) + { + vec *ve = NULL; + CONSTRUCTOR_APPEND_ELT (ve, TYPE_FIELDS (type), + real_part (expr)); + CONSTRUCTOR_APPEND_ELT (ve, TREE_CHAIN (TYPE_FIELDS (type)), + imaginary_part (expr)); + return build_constructor (type, ve); + } + + /* Replace type in the reinterpret cast with a cast to the record type. */ + return build_vconvert (type, expr); +} + /* Cast EXP (which should be a pointer) to TYPE* and then indirect. The back-end requires this cast in many cases. */ @@ -2214,6 +2240,14 @@ d_build_call (TypeFunction *tf, tree callable, tree object, build_address (targ)); } + /* Complex types are exposed as special types with an underlying + struct representation, if we are passing the native type to a + function that accepts the library-defined version, then ensure + it is properly reinterpreted as the underlying struct type. */ + if (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (targ)) + && arg->type->isTypeStruct ()) + targ = underlying_complex_expr (build_ctype (arg->type), targ); + /* Type `noreturn` is a terminator, as no other arguments can possibly be evaluated after it. */ if (TREE_TYPE (targ) == noreturn_type_node) diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index c3e95e4d2d2..809a242ea93 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -576,6 +576,7 @@ extern tree size_mult_expr (tree, tree); extern tree real_part (tree); extern tree imaginary_part (tree); extern tree complex_expr (tree, tree, tree); +extern tree underlying_complex_expr (tree, tree); extern tree indirect_ref (tree, tree); extern tree build_deref (tree); extern tree build_pointer_index (tree, tree); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 40c2689a3b9..140df7ee41d 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -1892,7 +1892,7 @@ public: underlying is really a complex type. */ if (e->e1->type->ty == TY::Tenum && e->e1->type->isTypeEnum ()->sym->isSpecial ()) - object = build_vconvert (build_ctype (tb), object); + object = underlying_complex_expr (build_ctype (tb), object); this->result_ = component_ref (object, get_symbol_decl (vd)); } diff --git a/gcc/testsuite/gdc.dg/torture/pr106623.d b/gcc/testsuite/gdc.dg/torture/pr106623.d new file mode 100644 index 00000000000..d782b236861 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/pr106623.d @@ -0,0 +1,28 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106623 +// { dg-do compile } +private struct _Complex(T) { T re; T im; } +enum __c_complex_double : _Complex!double; + +pragma(inline, true) +ulong hashOf()(scope const double val) +{ + return *cast(ulong*)&val; +} + +pragma(inline, true) +ulong hashOf()(scope const _Complex!double val, ulong seed = 0) +{ + return hashOf(val.re) + hashOf(val.im); +} + +pragma(inline, true) +ulong hashOf()(__c_complex_double val, ulong seed = 0) +{ + return hashOf(cast(_Complex!double) val, seed); +} + +ulong test106623() +{ + __c_complex_double val; + return hashOf(val); +} -- 2.34.1