From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1873) id 26BBD385735A; Wed, 15 Jun 2022 10:34:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 26BBD385735A MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Iain Buclaw To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-1104] d: Delay completing aggregate and enum types until after attributes have been applied. X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/heads/master X-Git-Oldrev: 2636660b6f35423e0cfbf53bfad5c5fed6ae6471 X-Git-Newrev: f4c3ce32fa54c1aefac0b3a825d8a3f73de95939 Message-Id: <20220615103428.26BBD385735A@sourceware.org> Date: Wed, 15 Jun 2022 10:34:28 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Jun 2022 10:34:28 -0000 https://gcc.gnu.org/g:f4c3ce32fa54c1aefac0b3a825d8a3f73de95939 commit r13-1104-gf4c3ce32fa54c1aefac0b3a825d8a3f73de95939 Author: Iain Buclaw Date: Tue Jun 14 15:56:59 2022 +0200 d: Delay completing aggregate and enum types until after attributes have been applied. Because of forward/recursive references, the TYPE_SIZE, TYPE_ALIGN, and TYPE_MODE of structs and enums were set before laying out its members. This adds a new macro TYPE_FORWARD_REFERENCES for storing those forward references against the incomplete type, laying them out after the type has been completed. Construction of the TYPE_DECL has also been moved on earlier in the type generation pass, which will allow the possibility of adding gdc-specific type attributes to the D front-end in the future. gcc/d/ChangeLog: * d-attribs.cc (apply_user_attributes): Set ATTR_FLAG_TYPE_IN_PLACE only on incomplete types. * d-codegen.cc (copy_aggregate_type): Set TYPE_STUB_DECL after copy. * d-compiler.cc (Compiler::onParseModule): Adjust. * d-tree.h (AGGREGATE_OR_ENUM_TYPE_CHECK): Define. (TYPE_FORWARD_REFERENCES): Define. * decl.cc (gcc_attribute_p): Update documentation. (DeclVisitor::visit (StructDeclaration *)): Exit before building type node if gcc.attributes symbol. (DeclVisitor::visit (ClassDeclaration *)): Build type node and add TYPE_NAME to current binding level before emitting anything else. (DeclVisitor::visit (InterfaceDeclaration *)): Likewise. (DeclVisitor::visit (EnumDeclaration *)): Likewise. (build_type_decl): Move rest_of_decl_compilation() call to finish_aggregate_type(). * types.cc (insert_aggregate_field): Move layout_decl() call to finish_aggregate_type(). (insert_aggregate_bitfield): Likewise. (layout_aggregate_members): Adjust. (finish_incomplete_fields): New function. (finish_aggregate_type): Handle forward referenced field types. Call rest_of_type_compilation() after completing the aggregate. (TypeVisitor::visit (TypeEnum *)): Don't set size and alignment until after apply_user_attributes(). Call rest_of_type_compilation() after completing the enumeral. (TypeVisitor::visit (TypeStruct *)): Call build_type_decl() before apply_user_attributes(). Don't set size, alignment, and mode until after apply_user_attributes(). (TypeVisitor::visit (TypeClass *)): Call build_type_decl() before applly_user_attributes(). Diff: --- gcc/d/d-attribs.cc | 7 ++- gcc/d/d-codegen.cc | 1 + gcc/d/d-compiler.cc | 20 ++++---- gcc/d/d-tree.h | 12 +++++ gcc/d/decl.cc | 44 ++++++++-------- gcc/d/types.cc | 145 +++++++++++++++++++++++++++++++++++++++------------- 6 files changed, 159 insertions(+), 70 deletions(-) diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc index c271de0c77e..b8ce30cf3c9 100644 --- a/gcc/d/d-attribs.cc +++ b/gcc/d/d-attribs.cc @@ -424,9 +424,12 @@ apply_user_attributes (Dsymbol *sym, tree node) location_t saved_location = input_location; input_location = make_location_t (sym->loc); + int attr_flags = 0; + if (TYPE_P (node) && !COMPLETE_TYPE_P (node)) + attr_flags |= ATTR_FLAG_TYPE_IN_PLACE; + Expressions *attrs = sym->userAttribDecl->getAttributes (); - decl_attributes (&node, build_attributes (attrs), - TYPE_P (node) ? ATTR_FLAG_TYPE_IN_PLACE : 0); + decl_attributes (&node, build_attributes (attrs), attr_flags); input_location = saved_location; } diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 22090a8c755..0e14654e56b 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -115,6 +115,7 @@ tree copy_aggregate_type (tree type) { tree newtype = build_distinct_type_copy (type); + TYPE_STUB_DECL (newtype) = TYPE_NAME (newtype); TYPE_FIELDS (newtype) = copy_list (TYPE_FIELDS (type)); for (tree f = TYPE_FIELDS (newtype); f; f = DECL_CHAIN (f)) diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc index 881f3863d2a..ada9721541b 100644 --- a/gcc/d/d-compiler.cc +++ b/gcc/d/d-compiler.cc @@ -129,22 +129,22 @@ Compiler::onParseModule (Module *m) if (md && md->id) { if (md->packages.length == 0) - { - Identifier *id = (md && md->id) ? md->id : m->ident; - if (!strcmp (id->toChars (), "object")) + { + Identifier *id = (md && md->id) ? md->id : m->ident; + if (!strcmp (id->toChars (), "object")) { create_tinfo_types (m); return; } } else if (md->packages.length == 1) - { - if (!strcmp (md->packages.ptr[0]->toChars (), "gcc") - && !strcmp (md->id->toChars (), "builtins")) - { - d_build_builtins_module (m); - return; - } + { + if (!strcmp (md->packages.ptr[0]->toChars (), "gcc") + && !strcmp (md->id->toChars (), "builtins")) + { + d_build_builtins_module (m); + return; + } } } diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 5f6b9d61001..48a40a6afa4 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -57,6 +57,9 @@ typedef Array Expressions; 4: TYPE_DELEGATE (in RECORD_TYPE). 5: TYPE_ASSOCIATIVE_ARRAY (in RECORD_TYPE). + Usage of TYPE_LANG_SLOT_?: + 1: TYPE_FORWARD_REFERENCES (in RECORD_TYPE, UNION_TYPE). + Usage of DECL_LANG_FLAG_?: 0: LABEL_VARIABLE_CASE (in LABEL_DECL). DECL_BUILT_IN_CTFE (in FUNCTION_DECL). @@ -68,6 +71,10 @@ typedef Array Expressions; #define VAR_OR_FUNCTION_DECL_CHECK(NODE) \ TREE_CHECK2 (NODE, VAR_DECL, FUNCTION_DECL) +#define AGGREGATE_OR_ENUM_TYPE_CHECK(NODE) \ + TREE_CHECK4 (NODE, RECORD_TYPE, UNION_TYPE, \ + QUAL_UNION_TYPE, ENUMERAL_TYPE) + /* The kinds of scopes we recognize. */ enum level_kind @@ -378,6 +385,11 @@ lang_tree_node #define TYPE_ASSOCIATIVE_ARRAY(NODE) \ (TYPE_LANG_FLAG_5 (RECORD_TYPE_CHECK (NODE))) +/* In an incomplete RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE, a list of field + declarations whose type would be completed by completing that type. */ +#define TYPE_FORWARD_REFERENCES(NODE) \ + (TYPE_LANG_SLOT_1 (AGGREGATE_OR_ENUM_TYPE_CHECK (NODE))) + /* True if the decl is a variable case label decl. */ #define LABEL_VARIABLE_CASE(NODE) \ (DECL_LANG_FLAG_0 (LABEL_DECL_CHECK (NODE))) diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index 5d850065bf0..518d84c1a49 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -99,7 +99,7 @@ mangle_internal_decl (Dsymbol *decl, const char *name, const char *suffix) return ident; } -/* Returns true if DECL is from the gcc.attribute module. */ +/* Returns true if DECL is from the gcc.attributes module. */ static bool gcc_attribute_p (Dsymbol *decl) @@ -367,6 +367,10 @@ public: return; } + /* Don't emit any symbols from gcc.attributes module. */ + if (gcc_attribute_p (d)) + return; + /* Add this decl to the current binding level. */ tree ctype = build_ctype (d->type); if (TYPE_NAME (ctype)) @@ -377,10 +381,6 @@ public: if (d->isAnonymous () || !d->members) return; - /* Don't emit any symbols from gcc.attribute module. */ - if (gcc_attribute_p (d)) - return; - /* Generate TypeInfo. */ if (have_typeinfo_p (Type::dtypeinfo)) create_typeinfo (d->type, NULL); @@ -482,6 +482,11 @@ public: return; } + /* Add this decl to the current binding level. */ + tree ctype = TREE_TYPE (build_ctype (d->type)); + if (TYPE_NAME (ctype)) + d_pushdecl (TYPE_NAME (ctype)); + if (!d->members) return; @@ -533,11 +538,6 @@ public: = build_constructor (TREE_TYPE (vtblsym->csym), elms); d_finish_decl (vtblsym->csym); - /* Add this decl to the current binding level. */ - tree ctype = TREE_TYPE (build_ctype (d->type)); - if (TYPE_NAME (ctype)) - d_pushdecl (TYPE_NAME (ctype)); - d->semanticRun = PASS::obj; } @@ -556,6 +556,11 @@ public: return; } + /* Add this decl to the current binding level. */ + tree ctype = TREE_TYPE (build_ctype (d->type)); + if (TYPE_NAME (ctype)) + d_pushdecl (TYPE_NAME (ctype)); + if (!d->members) return; @@ -576,11 +581,6 @@ public: DECL_INITIAL (d->csym) = layout_classinfo (d); d_finish_decl (d->csym); - /* Add this decl to the current binding level. */ - tree ctype = TREE_TYPE (build_ctype (d->type)); - if (TYPE_NAME (ctype)) - d_pushdecl (TYPE_NAME (ctype)); - d->semanticRun = PASS::obj; } @@ -599,6 +599,11 @@ public: return; } + /* Add this decl to the current binding level. */ + tree ctype = build_ctype (d->type); + if (TREE_CODE (ctype) == ENUMERAL_TYPE && TYPE_NAME (ctype)) + d_pushdecl (TYPE_NAME (ctype)); + if (d->isAnonymous ()) return; @@ -615,11 +620,6 @@ public: d_finish_decl (d->sinit); } - /* Add this decl to the current binding level. */ - tree ctype = build_ctype (d->type); - if (TYPE_NAME (ctype)) - d_pushdecl (TYPE_NAME (ctype)); - d->semanticRun = PASS::obj; } @@ -776,7 +776,7 @@ public: if (d->semanticRun >= PASS::obj) return; - /* Don't emit any symbols from gcc.attribute module. */ + /* Don't emit any symbols from gcc.attributes module. */ if (gcc_attribute_p (d)) return; @@ -2336,8 +2336,6 @@ build_type_decl (tree type, Dsymbol *dsym) } else if (type != TYPE_MAIN_VARIANT (type)) DECL_ORIGINAL_TYPE (decl) = TYPE_MAIN_VARIANT (type); - - rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0); } /* Create a declaration for field NAME of a given TYPE, setting the flags diff --git a/gcc/d/types.cc b/gcc/d/types.cc index b17b15359c8..0926715b7dc 100644 --- a/gcc/d/types.cc +++ b/gcc/d/types.cc @@ -270,7 +270,6 @@ insert_aggregate_field (tree type, tree field, size_t offset) TREE_ADDRESSABLE (field) = TYPE_SHARED (TREE_TYPE (field)); - layout_decl (field, 0); TYPE_FIELDS (type) = chainon (TYPE_FIELDS (type), field); } @@ -326,17 +325,6 @@ insert_aggregate_bitfield (tree type, tree bitfield, size_t width, DECL_BIT_FIELD (bitfield) = 1; DECL_BIT_FIELD_TYPE (bitfield) = TREE_TYPE (bitfield); - layout_decl (bitfield, 0); - - /* Give bit-field its proper type after layout_decl. */ - tree orig_type = DECL_BIT_FIELD_TYPE (bitfield); - if (width != TYPE_PRECISION (orig_type)) - { - TREE_TYPE (bitfield) - = d_build_bitfield_integer_type (width, TYPE_UNSIGNED (orig_type)); - SET_DECL_MODE (bitfield, TYPE_MODE (TREE_TYPE (bitfield))); - } - TYPE_FIELDS (type) = chainon (TYPE_FIELDS (type), bitfield); } @@ -432,7 +420,7 @@ layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p) bf->offset, bf->bitOffset); } else - insert_aggregate_field (context, field, var->offset); + insert_aggregate_field (context, field, var->offset); /* Because the front-end shares field decls across classes, don't create the corresponding back-end symbol unless we are adding @@ -585,6 +573,35 @@ layout_aggregate_type (AggregateDeclaration *decl, tree type, } } +/* If the aggregate type TYPE completes the type of any previous field + declarations, lay them out now. */ + +static void +finish_incomplete_fields (tree type) +{ + for (tree fwdref = TYPE_FORWARD_REFERENCES (type); fwdref != NULL_TREE; + fwdref = TREE_CHAIN (fwdref)) + { + tree field = TREE_VALUE (fwdref); + tree basetype = TREE_TYPE (field); + + /* Arrays of TYPE have layout_type() called from build_array_type(), but + would skip over setting TYPE_SIZE. Try completing the type again. */ + if (TREE_CODE (basetype) == ARRAY_TYPE) + { + while (TREE_CODE (TREE_TYPE (basetype)) == ARRAY_TYPE) + basetype = TREE_TYPE (basetype); + + layout_type (basetype); + } + + relayout_decl (field); + } + + /* No more forward references to process. */ + TYPE_FORWARD_REFERENCES (type) = NULL_TREE; +} + /* Given a record type TYPE, whose size and alignment are determined by STRUCTSIZE and ALIGNSIZE. Apply any type attributes ATTRS and compute the finalized record mode. */ @@ -601,7 +618,51 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize, tree type) /* Set the back-end type mode. */ compute_record_mode (type); - /* Fix up all variants of this aggregate type. */ + /* Layout all fields now the type is complete. */ + for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + /* If the field type is still being constructed because of recursive + references, attach it to that class/struct type, so we can go back + and complete the field later. */ + if (!COMPLETE_TYPE_P (TREE_TYPE (field))) + { + tree basetype = TREE_TYPE (field); + while (TREE_CODE (basetype) == ARRAY_TYPE) + basetype = TREE_TYPE (basetype); + + basetype = TYPE_MAIN_VARIANT (basetype); + if (RECORD_OR_UNION_TYPE_P (basetype) + || TREE_CODE (basetype) == ENUMERAL_TYPE) + { + gcc_assert (!COMPLETE_TYPE_P (basetype)); + tree fwdrefs = tree_cons (NULL_TREE, field, + TYPE_FORWARD_REFERENCES (basetype)); + TYPE_FORWARD_REFERENCES (basetype) = fwdrefs; + } + + continue; + } + + layout_decl (field, 0); + + /* Give bit-field its proper type after layout_decl. */ + if (DECL_BIT_FIELD (field)) + { + tree orig_type = DECL_BIT_FIELD_TYPE (field); + unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_SIZE (field)); + + if (width != TYPE_PRECISION (orig_type)) + { + bool unsignedp = TYPE_UNSIGNED (orig_type); + + TREE_TYPE (field) + = d_build_bitfield_integer_type (width, unsignedp); + SET_DECL_MODE (field, TYPE_MODE (TREE_TYPE (field))); + } + } + } + + /* Fix up all forward-referenced variants of this aggregate type. */ for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) { if (t == type) @@ -609,10 +670,21 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize, tree type) TYPE_FIELDS (t) = TYPE_FIELDS (type); TYPE_LANG_SPECIFIC (t) = TYPE_LANG_SPECIFIC (type); + TYPE_SIZE (t) = TYPE_SIZE (type); + TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type); + TYPE_PACKED (type) = TYPE_PACKED (type); + SET_TYPE_MODE (t, TYPE_MODE (type)); SET_TYPE_ALIGN (t, TYPE_ALIGN (type)); TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (type); - gcc_assert (TYPE_MODE (t) == TYPE_MODE (type)); } + + /* Finish debugging output for this type. */ + rest_of_type_compilation (type, TYPE_FILE_SCOPE_P (type)); + finish_incomplete_fields (type); + + /* Finish processing of TYPE_DECL. */ + rest_of_decl_compilation (TYPE_NAME (type), + DECL_FILE_SCOPE_P (TYPE_NAME (type)), 0); } /* Returns true if the class or struct type TYPE has already been layed out by @@ -1021,13 +1093,6 @@ public: if (flag_short_enums) TYPE_PACKED (t->ctype) = 1; - TYPE_PRECISION (t->ctype) = t->size (t->sym->loc) * 8; - TYPE_SIZE (t->ctype) = 0; - - TYPE_MIN_VALUE (t->ctype) = TYPE_MIN_VALUE (basetype); - TYPE_MAX_VALUE (t->ctype) = TYPE_MAX_VALUE (basetype); - layout_type (t->ctype); - tree values = NULL_TREE; if (t->sym->members) { @@ -1057,11 +1122,31 @@ public: } TYPE_VALUES (t->ctype) = values; - TYPE_UNSIGNED (t->ctype) = TYPE_UNSIGNED (basetype); build_type_decl (t->ctype, t->sym); } apply_user_attributes (t->sym, t->ctype); + + /* Finish the enumeration type. */ + if (TREE_CODE (t->ctype) == ENUMERAL_TYPE) + { + TYPE_MIN_VALUE (t->ctype) = TYPE_MIN_VALUE (basetype); + TYPE_MAX_VALUE (t->ctype) = TYPE_MAX_VALUE (basetype); + TYPE_UNSIGNED (t->ctype) = TYPE_UNSIGNED (basetype); + SET_TYPE_ALIGN (t->ctype, TYPE_ALIGN (basetype)); + TYPE_SIZE (t->ctype) = NULL_TREE; + TYPE_PRECISION (t->ctype) = t->size (t->sym->loc) * 8; + + layout_type (t->ctype); + + /* Finish debugging output for this type. */ + rest_of_type_compilation (t->ctype, TYPE_FILE_SCOPE_P (t->ctype)); + finish_incomplete_fields (t->ctype); + + /* Finish processing of TYPE_DECL. */ + rest_of_decl_compilation (TYPE_NAME (t->ctype), + DECL_FILE_SCOPE_P (TYPE_NAME (t->ctype)), 0); + } } /* Build a struct or union type. Layout should be exactly represented @@ -1092,21 +1177,13 @@ public: unsigned alignsize = t->sym->alignment.isDefault () ? t->sym->alignsize : t->sym->alignment.get (); - TYPE_SIZE (t->ctype) = bitsize_int (structsize * BITS_PER_UNIT); - TYPE_SIZE_UNIT (t->ctype) = size_int (structsize); - SET_TYPE_ALIGN (t->ctype, alignsize * BITS_PER_UNIT); - TYPE_PACKED (t->ctype) = (alignsize == 1); - compute_record_mode (t->ctype); - /* Put out all fields. */ layout_aggregate_type (t->sym, t->ctype, t->sym); + build_type_decl (t->ctype, t->sym); apply_user_attributes (t->sym, t->ctype); finish_aggregate_type (structsize, alignsize, t->ctype); } - TYPE_CONTEXT (t->ctype) = d_decl_context (t->sym); - build_type_decl (t->ctype, t->sym); - /* For structs with a user defined postblit, copy constructor, or a destructor, also set TREE_ADDRESSABLE on the type and all variants. This will make the struct be passed around by reference. */ @@ -1146,6 +1223,7 @@ public: /* Put out all fields, including from each base class. */ layout_aggregate_type (t->sym, basetype, t->sym); + build_type_decl (basetype, t->sym); apply_user_attributes (t->sym, basetype); finish_aggregate_type (t->sym->structsize, t->sym->alignsize, basetype); @@ -1183,9 +1261,6 @@ public: && !chain_member (method, TYPE_FIELDS (basetype))) TYPE_FIELDS (basetype) = chainon (TYPE_FIELDS (basetype), method); } - - TYPE_CONTEXT (basetype) = d_decl_context (t->sym); - build_type_decl (basetype, t->sym); } };