From 3e3b665cc77791f2e088aeee124d8a9fb7f6eb41 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 9 Apr 2025 14:49:14 +0200 Subject: [PATCH] d: Use CONSTRUCTOR_ZERO_PADDING_BITS in the D FE [PR117832] Adds a new wrapper function for `build_constructor', and calls it instead to ensure that all CONSTRUCTOR nodes explicitly created by the front-end have CONSTRUCTOR_ZERO_PADDING_BITS set. Some places may not be necessary as it's guaranteed for there to be no padding in the type, such as D dynamic arrays. Other places this gets turned into a double-memset when optimizations are turned off, as the front-end already generates a memset call to zero out all padding on initializing a variable. The optimizer sees through this so will correctly clear all bits once, so this can be improved later as-needed. PR d/117832 gcc/d/ChangeLog: * d-tree.h (build_padded_constructor): New prototype. * d-codegen.cc (build_padded_constructor): New function. (d_array_value): Call it. (build_memset_call): Likewise. (build_struct_literal): Likewise. (underlying_complex_expr): Likewise. (build_array_from_val): Likewise. (build_array_from_exprs): Likewise. (d_build_call): Likewise. (get_frame_for_symbol): Likewise. * d-convert.cc (convert_for_rvalue): Likewise. (convert_for_assignment): Likewise. * decl.cc (class DeclVisitor): Likewise. * expr.cc (class ExprVisitor): Likewise. * modules.cc (layout_moduleinfo): Likewise. * typeinfo.cc (class TypeInfoVisitor): Likewise. --- gcc/d/d-codegen.cc | 32 +++++++++++++++++++++++--------- gcc/d/d-convert.cc | 4 ++-- gcc/d/d-tree.h | 1 + gcc/d/decl.cc | 2 +- gcc/d/expr.cc | 22 ++++++++++++---------- gcc/d/modules.cc | 4 ++-- gcc/d/typeinfo.cc | 8 ++++---- 7 files changed, 45 insertions(+), 28 deletions(-) diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index ad71486e3ba..1a7575aac22 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -317,7 +317,7 @@ d_array_value (tree type, tree len, tree data) CONSTRUCTOR_APPEND_ELT (ce, len_field, len); CONSTRUCTOR_APPEND_ELT (ce, ptr_field, data); - return build_constructor (type, ce); + return build_padded_constructor (type, ce); } /* Returns value representing the array length of expression EXP. @@ -898,7 +898,10 @@ build_memset_call (tree ptr, tree num) { tree cst = build_zero_cst (valtype); if (TREE_CODE (cst) == CONSTRUCTOR) - return build_memcpy_call (ptr, build_address (cst), num); + { + CONSTRUCTOR_ZERO_PADDING_BITS (cst) = 1; + return build_memcpy_call (ptr, build_address (cst), num); + } return modify_expr (build_deref (ptr), cst); } @@ -1205,7 +1208,7 @@ build_struct_literal (tree type, vec *init) { /* If the initializer was empty, use default zero initialization. */ if (vec_safe_is_empty (init)) - return build_constructor (type, NULL); + return build_padded_constructor (type, NULL); /* Struct literals can be seen for special enums representing `_Complex', make sure to reinterpret the literal as the correct type. */ @@ -1306,7 +1309,7 @@ build_struct_literal (tree type, vec *init) /* Ensure that we have consumed all values. */ gcc_assert (vec_safe_is_empty (init) || ANON_AGGR_TYPE_P (type)); - tree ctor = build_constructor (type, ve); + tree ctor = build_padded_constructor (type, ve); if (constant_p) TREE_CONSTANT (ctor) = 1; @@ -1314,6 +1317,17 @@ build_struct_literal (tree type, vec *init) return ctor; } +/* Return a new zero padded CONSTRUCTOR node whose type is TYPE and values are + in the vec pointed to by VALS. */ + +tree +build_padded_constructor (tree type, vec *vals) +{ + tree ctor = build_constructor (type, vals); + CONSTRUCTOR_ZERO_PADDING_BITS (ctor) = 1; + return ctor; +} + /* Given the TYPE of an anonymous field inside T, return the FIELD_DECL for the field. If not found return NULL_TREE. Because anonymous types can nest, we must also search all @@ -1647,7 +1661,7 @@ underlying_complex_expr (tree type, tree expr) real_part (expr)); CONSTRUCTOR_APPEND_ELT (ve, TREE_CHAIN (TYPE_FIELDS (type)), imaginary_part (expr)); - return build_constructor (type, ve); + return build_padded_constructor (type, ve); } /* Replace type in the reinterpret cast with a cast to the record type. */ @@ -1852,7 +1866,7 @@ build_array_from_val (Type *type, tree val) for (size_t i = 0; i < dims; i++) CONSTRUCTOR_APPEND_ELT (elms, size_int (i), val); - return build_constructor (build_ctype (type), elms); + return build_padded_constructor (build_ctype (type), elms); } /* Build a static array of type TYPE from an array of EXPS. @@ -1886,7 +1900,7 @@ build_array_from_exprs (Type *type, Expressions *exps, bool const_p) init = build_memset_call (var); /* Initialize the temporary. */ - tree assign = modify_expr (var, build_constructor (satype, elms)); + tree assign = modify_expr (var, build_padded_constructor (satype, elms)); return compound_expr (compound_expr (init, assign), var); } @@ -2301,7 +2315,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object, if (empty_aggregate_p (TREE_TYPE (targ)) && !TREE_ADDRESSABLE (targ) && TREE_CODE (targ) != CONSTRUCTOR) { - tree t = build_constructor (TREE_TYPE (targ), NULL); + tree t = build_padded_constructor (TREE_TYPE (targ), NULL); targ = build2 (COMPOUND_EXPR, TREE_TYPE (t), targ, t); } @@ -2613,7 +2627,7 @@ get_frame_for_symbol (Dsymbol *sym) framefields = DECL_CHAIN (framefields); } - frame_ref = build_address (build_constructor (type, ve)); + frame_ref = build_address (build_padded_constructor (type, ve)); } } diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc index 4b195841c49..c5b0d653e87 100644 --- a/gcc/d/d-convert.cc +++ b/gcc/d/d-convert.cc @@ -688,7 +688,7 @@ convert_for_rvalue (tree expr, Type *etype, Type *totype) CONSTRUCTOR_APPEND_ELT (elms, index, value); } - return build_constructor (build_ctype (totype), elms); + return build_padded_constructor (build_ctype (totype), elms); } } @@ -788,7 +788,7 @@ convert_for_assignment (Expression *expr, Type *totype, bool literalp) TypeSArray *sa_type = tbtype->isTypeSArray (); uinteger_t count = sa_type->dim->toUInteger (); - tree ctor = build_constructor (build_ctype (totype), NULL); + tree ctor = build_padded_constructor (build_ctype (totype), NULL); if (count) { vec *ce = NULL; diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 42d01e45595..ebbbe715dac 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -575,6 +575,7 @@ extern tree build_struct_comparison (tree_code, StructDeclaration *, extern tree build_array_struct_comparison (tree_code, StructDeclaration *, tree, tree, tree); extern tree build_struct_literal (tree, vec *); +extern tree build_padded_constructor (tree, vec *); extern tree component_ref (tree, tree); extern tree build_assign (tree_code, tree, tree); extern tree modify_expr (tree, tree); diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index 250d148e56f..136f78b32ff 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -651,7 +651,7 @@ public: } DECL_INITIAL (vtblsym->csym) - = build_constructor (TREE_TYPE (vtblsym->csym), elms); + = build_padded_constructor (TREE_TYPE (vtblsym->csym), elms); d_finish_decl (vtblsym->csym); d->semanticRun (PASS::obj); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 46e65145791..1c1ecf2c6db 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -2457,7 +2457,7 @@ public: CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem); result = build_nop (build_ctype (e->type), - build_constructor (aatype, ce)); + build_padded_constructor (aatype, ce)); } else gcc_unreachable (); @@ -2530,7 +2530,7 @@ public: CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value); } - tree ctor = build_constructor (type, elms); + tree ctor = build_padded_constructor (type, elms); TREE_CONSTANT (ctor) = 1; this->result_ = ctor; return; @@ -2612,8 +2612,10 @@ public: this->result_ = d_array_value (build_ctype (e->type), size_int (0), null_pointer_node); else - this->result_ = build_constructor (make_array_type (tb->nextOf (), 0), - NULL); + { + tree arrtype = make_array_type (tb->nextOf (), 0); + this->result_ = build_padded_constructor (arrtype, NULL); + } return; } @@ -2654,7 +2656,7 @@ public: /* Now return the constructor as the correct type. For static arrays there is nothing else to do. For dynamic arrays, return a two field struct. For pointers, return the address. */ - tree ctor = build_constructor (satype, elms); + tree ctor = build_padded_constructor (satype, elms); tree type = build_ctype (e->type); /* Nothing else to do for static arrays. */ @@ -2755,7 +2757,7 @@ public: TypeAArray *ta = tb->isTypeAArray (); if (e->keys->length == 0) { - this->result_ = build_constructor (build_ctype (ta), NULL); + this->result_ = build_padded_constructor (build_ctype (ta), NULL); return; } @@ -2787,7 +2789,7 @@ public: CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem); tree result = build_nop (build_ctype (e->type), - build_constructor (aatype, ce)); + build_padded_constructor (aatype, ce)); this->result_ = compound_expr (init, result); } @@ -2798,7 +2800,7 @@ public: /* Handle empty struct literals. */ if (e->elements == NULL || e->sd->fields.length == 0) { - this->result_ = build_constructor (build_ctype (e->type), NULL); + this->result_ = build_padded_constructor (build_ctype (e->type), NULL); return; } @@ -2849,7 +2851,7 @@ public: elem = d_save_expr (elem); if (initializer_zerop (elem)) - value = build_constructor (build_ctype (ftype), NULL); + value = build_padded_constructor (build_ctype (ftype), NULL); else value = build_array_from_val (ftype, elem); } @@ -2948,7 +2950,7 @@ public: if (constant_p) this->result_ = build_vector_from_ctor (type, elms); else - this->result_ = build_constructor (type, elms); + this->result_ = build_padded_constructor (type, elms); } else if (e->e1->type->toBasetype ()->ty == TY::Tsarray) { diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc index 471ac43cbea..813d94bc5c4 100644 --- a/gcc/d/modules.cc +++ b/gcc/d/modules.cc @@ -667,7 +667,7 @@ layout_moduleinfo (Module *decl) CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, size_int (aimports_dim)); CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, - build_constructor (satype, elms)); + build_padded_constructor (satype, elms)); } if (flags & MIlocalClasses) @@ -684,7 +684,7 @@ layout_moduleinfo (Module *decl) CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, size_int (aclasses.length)); CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, - build_constructor (satype, elms)); + build_padded_constructor (satype, elms)); } if (flags & MIname) diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc index e81b2f0157f..4c3e9e40b48 100644 --- a/gcc/d/typeinfo.cc +++ b/gcc/d/typeinfo.cc @@ -489,14 +489,14 @@ class TypeInfoVisitor : public Visitor CONSTRUCTOR_APPEND_ELT (v, size_int (3), size_int (b->offset)); /* Add to the array of interfaces. */ - value = build_constructor (vtbl_interface_type_node, v); + value = build_padded_constructor (vtbl_interface_type_node, v); CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value); } tree domain = size_int (cd->vtblInterfaces->length - 1); tree arrtype = build_array_type (vtbl_interface_type_node, build_index_type (domain)); - return build_constructor (arrtype, elms); + return build_padded_constructor (arrtype, elms); } /* Write out the interfacing vtable[] of base class BCD that will be accessed @@ -542,7 +542,7 @@ class TypeInfoVisitor : public Visitor tree vtbldomain = build_index_type (size_int (id->vtbl.length - 1)); tree vtbltype = build_array_type (vtable_entry_type, vtbldomain); - tree value = build_constructor (vtbltype, elms); + tree value = build_padded_constructor (vtbltype, elms); this->layout_field (value); } @@ -1160,7 +1160,7 @@ public: CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_typeinfo (d->loc, arg->type)); } - tree ctor = build_constructor (build_ctype (satype), elms); + tree ctor = build_padded_constructor (build_ctype (satype), elms); tree decl = this->internal_reference (ctor); tree length = size_int (ti->arguments->length);