aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-06-14 15:56:59 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-06-15 12:33:42 +0200
commitf4c3ce32fa54c1aefac0b3a825d8a3f73de95939 (patch)
treed7b38ef3868c7d1619c1d23c513fa43d2800507e /gcc/d
parent2636660b6f35423e0cfbf53bfad5c5fed6ae6471 (diff)
downloadgcc-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.cc7
-rw-r--r--gcc/d/d-codegen.cc1
-rw-r--r--gcc/d/d-compiler.cc20
-rw-r--r--gcc/d/d-tree.h12
-rw-r--r--gcc/d/decl.cc44
-rw-r--r--gcc/d/types.cc145
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);
}
};