[committed] d: Fix internal compiler error: Segmentation fault at gimple-expr.cc:88
Commit Message
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
@@ -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 <constructor_elt, va_gc> *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)
@@ -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);
@@ -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));
}
new file mode 100644
@@ -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);
+}