diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-06-14 15:56:59 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-06-15 12:33:42 +0200 |
commit | f4c3ce32fa54c1aefac0b3a825d8a3f73de95939 (patch) | |
tree | d7b38ef3868c7d1619c1d23c513fa43d2800507e /gcc/d | |
parent | 2636660b6f35423e0cfbf53bfad5c5fed6ae6471 (diff) | |
download | gcc-f4c3ce32fa54c1aefac0b3a825d8a3f73de95939.zip gcc-f4c3ce32fa54c1aefac0b3a825d8a3f73de95939.tar.gz gcc-f4c3ce32fa54c1aefac0b3a825d8a3f73de95939.tar.bz2 |
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().
Diffstat (limited to 'gcc/d')
-rw-r--r-- | gcc/d/d-attribs.cc | 7 | ||||
-rw-r--r-- | gcc/d/d-codegen.cc | 1 | ||||
-rw-r--r-- | gcc/d/d-compiler.cc | 20 | ||||
-rw-r--r-- | gcc/d/d-tree.h | 12 | ||||
-rw-r--r-- | gcc/d/decl.cc | 44 | ||||
-rw-r--r-- | 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 c271de0..b8ce30c 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 22090a8..0e14654 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 881f386..ada9721 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 5f6b9d6..48a40a6 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -57,6 +57,9 @@ typedef Array <Expression *> 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 <Expression *> 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 5d85006..518d84c 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 b17b153..0926715 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); } }; |