Commit 5bdebb51 by Iain Buclaw Committed by Iain Buclaw

[D] Fix identity comparison for structs with complex float fields.

gcc/d/ChangeLog:

2019-01-20  Iain Buclaw  <ibuclaw@gdcproject.org>

	* d-codegen.cc (identity_compare_p): Return false if seen built-in
	type with padding.
	(build_float_identity): Moved here from expr.cc.
	(lower_struct_comparison): Handle real and complex types.
	* d-tree.h (build_float_identity): New.
	* expr.cc (build_float_identity): Move to d-codegen.cc.

gcc/testsuite/ChangeLog:

2019-01-20  Iain Buclaw  <ibuclaw@gdcproject.org>

	* gdc.dg/runnable.d: Add more tests for comparing complex types.

From-SVN: r268104
parent 70d87497
2019-01-20 Iain Buclaw <ibuclaw@gdcproject.org>
* d-codegen.cc (identity_compare_p): Return false if seen built-in
type with padding.
(build_float_identity): Moved here from expr.cc.
(lower_struct_comparison): Handle real and complex types.
* d-tree.h (build_float_identity): New.
* expr.cc (build_float_identity): Move to d-codegen.cc.
2019-01-20 Johannes Pfau <johannespfau@gmail.com>
* expr.cc (build_float_identity): New function.
......
......@@ -798,15 +798,21 @@ identity_compare_p (StructDeclaration *sd)
for (size_t i = 0; i < sd->fields.dim; i++)
{
VarDeclaration *vd = sd->fields[i];
Type *tb = vd->type->toBasetype ();
/* Check inner data structures. */
if (vd->type->ty == Tstruct)
if (tb->ty == Tstruct)
{
TypeStruct *ts = (TypeStruct *) vd->type;
TypeStruct *ts = (TypeStruct *) tb;
if (!identity_compare_p (ts->sym))
return false;
}
/* Check for types that may have padding. */
if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80)
&& Target::realpad != 0)
return false;
if (offset <= vd->offset)
{
/* There's a hole in the struct. */
......@@ -824,6 +830,20 @@ identity_compare_p (StructDeclaration *sd)
return true;
}
/* Build a floating-point identity comparison between T1 and T2, ignoring any
excessive padding in the type. CODE is EQ_EXPR or NE_EXPR comparison. */
tree
build_float_identity (tree_code code, tree t1, tree t2)
{
tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
tree result = build_call_expr (tmemcmp, 3, build_address (t1),
build_address (t2), size);
return build_boolop (code, result, integer_zero_node);
}
/* Lower a field-by-field equality expression between T1 and T2 of type SD.
CODE is the EQ_EXPR or NE_EXPR comparison. */
......@@ -859,29 +879,45 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd,
for (size_t i = 0; i < sd->fields.dim; i++)
{
VarDeclaration *vd = sd->fields[i];
Type *type = vd->type->toBasetype ();
tree sfield = get_symbol_decl (vd);
tree t1ref = component_ref (t1, sfield);
tree t2ref = component_ref (t2, sfield);
tree tcmp;
if (vd->type->ty == Tstruct)
if (type->ty == Tstruct)
{
/* Compare inner data structures. */
StructDeclaration *decl = ((TypeStruct *) vd->type)->sym;
StructDeclaration *decl = ((TypeStruct *) type)->sym;
tcmp = lower_struct_comparison (code, decl, t1ref, t2ref);
}
else if (type->ty != Tvector && type->isintegral ())
{
/* Integer comparison, no special handling required. */
tcmp = build_boolop (code, t1ref, t2ref);
}
else if (type->ty != Tvector && type->isfloating ())
{
/* Floating-point comparison, don't compare padding in type. */
if (!type->iscomplex ())
tcmp = build_float_identity (code, t1ref, t2ref);
else
{
tree req = build_float_identity (code, real_part (t1ref),
real_part (t2ref));
tree ieq = build_float_identity (code, imaginary_part (t1ref),
imaginary_part (t2ref));
tcmp = build_boolop (tcode, req, ieq);
}
}
else
{
tree stype = build_ctype (vd->type);
tree stype = build_ctype (type);
opt_scalar_int_mode mode = int_mode_for_mode (TYPE_MODE (stype));
if (vd->type->ty != Tvector && vd->type->isintegral ())
{
/* Integer comparison, no special handling required. */
tcmp = build_boolop (code, t1ref, t2ref);
}
else if (mode.exists ())
if (mode.exists ())
{
/* Compare field bits as their corresponding integer type.
*((T*) &t1) == *((T*) &t2) */
......
......@@ -522,6 +522,7 @@ extern tree d_mark_addressable (tree);
extern tree d_mark_used (tree);
extern tree d_mark_read (tree);
extern bool identity_compare_p (StructDeclaration *);
extern tree build_float_identity (tree_code, tree, tree);
extern tree build_struct_comparison (tree_code, StructDeclaration *,
tree, tree);
extern tree build_array_struct_comparison (tree_code, StructDeclaration *,
......
......@@ -43,20 +43,6 @@ along with GCC; see the file COPYING3. If not see
#include "d-tree.h"
/* Build a floating-point identity comparison between T1 and T2, ignoring any
excessive padding in the type. CODE is EQ_EXPR or NE_EXPR comparison. */
static tree
build_float_identity (tree_code code, tree t1, tree t2)
{
tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
tree result = build_call_expr (tmemcmp, 3, build_address (t1),
build_address (t2), size);
return build_boolop (code, result, integer_zero_node);
}
/* Implements the visitor interface to build the GCC trees of all Expression
AST classes emitted from the D Front-end.
All visit methods accept one parameter E, which holds the frontend AST
......
2019-01-20 Iain Buclaw <ibuclaw@gdcproject.org>
* gdc.dg/runnable.d: Add more tests for comparing complex types.
2019-01-20 Johannes Pfau <johannespfau@gmail.com>
* gdc.dg/runnable.d: Add tests for comparing complex types.
......
......@@ -1553,6 +1553,26 @@ void test309()
assert(!(f1 is f3));
assert(!(f2 is f3));
assert(!(f1 !is f4));
struct CReal
{
creal value;
}
CReal s1 = CReal(+0.0 + 0.0i);
CReal s2 = CReal(+0.0 - 0.0i);
CReal s3 = CReal(-0.0 + 0.0i);
CReal s4 = CReal(+0.0 + 0.0i);
assert(s1 !is s2);
assert(s1 !is s3);
assert(s2 !is s3);
assert(s1 is s4);
assert(!(s1 is s2));
assert(!(s1 is s3));
assert(!(s2 is s3));
assert(!(s1 !is s4));
}
/******************************************/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment