+2020-03-31 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/94424
+ * d-codegen.cc (build_alignment_field): Remove.
+ (build_struct_literal): Don't insert alignment padding.
+ * expr.cc (ExprVisitor::visit (AssignExp *)): Call memset before
+ assigning struct literals.
+
2020-03-31 Iain Buclaw <ibuclaw@gdcproject.org>
* typeinfo.cc (TypeInfoVisitor::internal_reference): Call
return compound_expr (body, result);
}
-/* Create an anonymous field of type ubyte[T] at OFFSET to fill
- the alignment hole between OFFSET and FIELDPOS. */
-
-static tree
-build_alignment_field (tree type, HOST_WIDE_INT offset, HOST_WIDE_INT fieldpos)
-{
- tree atype = make_array_type (Type::tuns8, fieldpos - offset);
- tree field = create_field_decl (atype, NULL, 1, 1);
-
- SET_DECL_OFFSET_ALIGN (field, TYPE_ALIGN (atype));
- DECL_FIELD_OFFSET (field) = size_int (offset);
- DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
- DECL_FIELD_CONTEXT (field) = type;
- DECL_PADDING_P (field) = 1;
-
- layout_decl (field, 0);
-
- return field;
-}
-
/* Build a constructor for a variable of aggregate type TYPE using the
initializer INIT, an ordered flat list of fields and values provided
by the frontend. The returned constructor should be a value that
vec<constructor_elt, va_gc> *ve = NULL;
HOST_WIDE_INT offset = 0;
bool constant_p = true;
- bool fillholes = true;
bool finished = false;
- /* Filling alignment holes this only applies to structs. */
- if (TREE_CODE (type) != RECORD_TYPE
- || CLASS_TYPE_P (type) || TYPE_PACKED (type))
- fillholes = false;
-
/* Walk through each field, matching our initializer list. */
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
HOST_WIDE_INT fieldpos = int_byte_position (field);
gcc_assert (value != NULL_TREE);
- /* Insert anonymous fields in the constructor for padding out
- alignment holes in-place between fields. */
- if (fillholes && offset < fieldpos)
- {
- tree pfield = build_alignment_field (type, offset, fieldpos);
- tree pvalue = build_zero_cst (TREE_TYPE (pfield));
- CONSTRUCTOR_APPEND_ELT (ve, pfield, pvalue);
- }
-
/* Must not initialize fields that overlap. */
if (fieldpos < offset)
{
break;
}
- /* Finally pad out the end of the record. */
- if (fillholes && offset < int_size_in_bytes (type))
- {
- tree pfield = build_alignment_field (type, offset,
- int_size_in_bytes (type));
- tree pvalue = build_zero_cst (TREE_TYPE (pfield));
- CONSTRUCTOR_APPEND_ELT (ve, pfield, pvalue);
- }
-
/* Ensure that we have consumed all values. */
gcc_assert (vec_safe_is_empty (init) || ANON_AGGR_TYPE_P (type));
tree t1 = build_expr (e->e1);
tree t2 = convert_for_assignment (build_expr (e->e2),
e->e2->type, e->e1->type);
+ StructDeclaration *sd = ((TypeStruct *) tb1)->sym;
/* Look for struct = 0. */
if (e->e2->op == TOKint64)
{
/* Use memset to fill struct. */
gcc_assert (e->op == TOKblit);
- StructDeclaration *sd = ((TypeStruct *) tb1)->sym;
-
tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
tree result = build_call_expr (tmemset, 3, build_address (t1),
t2, size_int (sd->structsize));
this->result_ = compound_expr (result, t1);
}
else
- this->result_ = build_assign (modifycode, t1, t2);
+ {
+ /* Simple struct literal assignment. */
+ tree init = NULL_TREE;
+
+ /* Fill any alignment holes in the struct using memset. */
+ if (e->op == TOKconstruct && !identity_compare_p (sd))
+ {
+ tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
+ init = build_call_expr (tmemset, 3, build_address (t1),
+ integer_zero_node,
+ size_int (sd->structsize));
+ }
+
+ tree result = build_assign (modifycode, t1, t2);
+ this->result_ = compound_expr (init, result);
+ }
return;
}
+2020-03-31 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/94424
+ * gdc.dg/pr94424.d: New test.
+
2020-03-31 Felix Yang <felix.yang@huawei.com>
PR tree-optimization/94398
--- /dev/null
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94424
+// { dg-additional-options "-fmain -funittest" }
+// { dg-do run { target hw } }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+@safe unittest
+{
+ struct C
+ {
+ ubyte i;
+ this(ubyte i) { this.i = i; }
+ }
+
+ auto c1 = C(1);
+ auto c2 = C(2);
+
+ assert(__cmp([c1, c1][], [c2, c2][]) < 0);
+ assert(__cmp([c2, c2], [c1, c1]) > 0);
+ assert(__cmp([c2, c2], [c2, c1]) > 0);
+}