diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index ea1d7d5c896..9a3fbfa7c56 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,11 @@ +2020-03-31 Iain Buclaw + + 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 * typeinfo.cc (TypeInfoVisitor::internal_reference): Call diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 3895a59c224..66af2b4da30 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -1076,26 +1076,6 @@ build_array_struct_comparison (tree_code code, StructDeclaration *sd, 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 @@ -1111,14 +1091,8 @@ build_struct_literal (tree type, vec *init) vec *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)) { @@ -1163,15 +1137,6 @@ build_struct_literal (tree type, vec *init) 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) { @@ -1214,15 +1179,6 @@ build_struct_literal (tree type, vec *init) 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)); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index fcf9bc5880a..0ed50ee2d9e 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -1054,14 +1054,13 @@ public: 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)); @@ -1079,7 +1078,22 @@ public: 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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1d97d6b5219..008acc6e231 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-03-31 Iain Buclaw + + PR d/94424 + * gdc.dg/pr94424.d: New test. + 2020-03-31 Felix Yang PR tree-optimization/94398 diff --git a/gcc/testsuite/gdc.dg/pr94424.d b/gcc/testsuite/gdc.dg/pr94424.d new file mode 100644 index 00000000000..b9f9fac8957 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr94424.d @@ -0,0 +1,19 @@ +// 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); +}