mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 06:54:44 +01:00
Convert StructTypeField to a specific type. (#4492)
This converts `StructTypeField` from an instruction to a dedicated type, with its own store. This had originated from discussing how `.GetAs<SemIR::StructTypeField>` was more prevalent than for other instructions, but is probably more interesting for the storage savings (16 bytes StructTypeField + 4 byte LocId + 4 byte InstId -> 8 byte StructTypeField). Due to the different structure, these now have their own stack during construction, reducing (but not eliminating) `args_type_info_stack_` use-cases. The test changes of different InstIds is expected because structs and classes generate fewer instructions now. Other than that, results should remain the same. I'm generally trying to avoid unrelated cleanup here due to the PR size, though I did scrutinize the `VerifyOnFinish` calls, adding one and commenting others (putting them in member order because that's how I was checking what was verified and what wasn't).
This commit is contained in:
@@ -295,7 +295,7 @@ auto HandleParseNode(Context& context, Parse::ClassDefinitionStartId node_id)
|
||||
|
||||
context.inst_block_stack().Push();
|
||||
context.node_stack().Push(node_id, class_id);
|
||||
context.args_type_info_stack().Push();
|
||||
context.struct_type_fields_stack().PushArray();
|
||||
|
||||
// TODO: Handle the case where there's control flow in the class body. For
|
||||
// example:
|
||||
@@ -533,11 +533,10 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool {
|
||||
auto field_type_id =
|
||||
context.GetUnboundElementType(class_info.self_type_id, base_info.type_id);
|
||||
class_info.base_id = context.AddInst<SemIR::BaseDecl>(
|
||||
node_id,
|
||||
{.type_id = field_type_id,
|
||||
.base_type_id = base_info.type_id,
|
||||
.index = SemIR::ElementIndex(
|
||||
context.args_type_info_stack().PeekCurrentBlockContents().size())});
|
||||
node_id, {.type_id = field_type_id,
|
||||
.base_type_id = base_info.type_id,
|
||||
.index = SemIR::ElementIndex(
|
||||
context.struct_type_fields_stack().PeekArray().size())});
|
||||
|
||||
if (base_info.type_id != SemIR::TypeId::Error) {
|
||||
auto base_class_info = context.classes().Get(
|
||||
@@ -548,10 +547,8 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool {
|
||||
// Add a corresponding field to the object representation of the class.
|
||||
// TODO: Consider whether we want to use `partial T` here.
|
||||
// TODO: Should we diagnose if there are already any fields?
|
||||
context.args_type_info_stack().AddInstId(
|
||||
context.AddInstInNoBlock<SemIR::StructTypeField>(
|
||||
node_id, {.name_id = SemIR::NameId::Base,
|
||||
.field_type_id = base_info.type_id}));
|
||||
context.struct_type_fields_stack().AppendToTop(
|
||||
{.name_id = SemIR::NameId::Base, .type_id = base_info.type_id});
|
||||
|
||||
// Bind the name `base` in the class to the base field.
|
||||
context.decl_name_stack().AddNameOrDiagnoseDuplicate(
|
||||
@@ -576,7 +573,7 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool {
|
||||
static auto CheckCompleteAdapterClassType(Context& context,
|
||||
Parse::NodeId node_id,
|
||||
SemIR::ClassId class_id,
|
||||
SemIR::InstBlockId fields_id)
|
||||
SemIR::StructTypeFieldsId fields_id)
|
||||
-> SemIR::InstId {
|
||||
const auto& class_info = context.classes().Get(class_id);
|
||||
if (class_info.base_id.is_valid()) {
|
||||
@@ -589,14 +586,17 @@ static auto CheckCompleteAdapterClassType(Context& context,
|
||||
return SemIR::InstId::BuiltinError;
|
||||
}
|
||||
|
||||
if (!context.inst_blocks().Get(fields_id).empty()) {
|
||||
auto first_field_id = context.inst_blocks().Get(fields_id).front();
|
||||
if (auto fields = context.struct_type_fields().Get(fields_id);
|
||||
!fields.empty()) {
|
||||
auto [first_field_inst_id, _] = context.LookupNameInExactScope(
|
||||
node_id, fields.front().name_id, class_info.scope_id,
|
||||
context.name_scopes().Get(class_info.scope_id));
|
||||
CARBON_DIAGNOSTIC(AdaptWithFields, Error, "adapter with fields");
|
||||
CARBON_DIAGNOSTIC(AdaptWithFieldHere, Note,
|
||||
"first field declaration is here");
|
||||
context.emitter()
|
||||
.Build(class_info.adapt_id, AdaptWithFields)
|
||||
.Note(first_field_id, AdaptWithFieldHere)
|
||||
.Note(first_field_inst_id, AdaptWithFieldHere)
|
||||
.Emit();
|
||||
return SemIR::InstId::BuiltinError;
|
||||
}
|
||||
@@ -649,7 +649,9 @@ static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id,
|
||||
SemIR::ClassId class_id) -> SemIR::InstId {
|
||||
auto& class_info = context.classes().Get(class_id);
|
||||
if (class_info.adapt_id.is_valid()) {
|
||||
auto fields_id = context.args_type_info_stack().Pop();
|
||||
auto fields_id = context.struct_type_fields().AddCanonical(
|
||||
context.struct_type_fields_stack().PeekArray());
|
||||
context.struct_type_fields_stack().PopArray();
|
||||
|
||||
return CheckCompleteAdapterClassType(context, node_id, class_id, fields_id);
|
||||
}
|
||||
@@ -666,15 +668,15 @@ static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id,
|
||||
}
|
||||
|
||||
if (defining_vtable_ptr) {
|
||||
context.args_type_info_stack().AddFrontInstId(
|
||||
context.AddInstInNoBlock<SemIR::StructTypeField>(
|
||||
Parse::NodeId::Invalid,
|
||||
{.name_id = SemIR::NameId::Vptr,
|
||||
.field_type_id = context.GetPointerType(
|
||||
context.GetBuiltinType(SemIR::BuiltinInstKind::VtableType))}));
|
||||
context.struct_type_fields_stack().PrependToTop(
|
||||
{.name_id = SemIR::NameId::Vptr,
|
||||
.type_id = context.GetPointerType(
|
||||
context.GetBuiltinType(SemIR::BuiltinInstKind::VtableType))});
|
||||
}
|
||||
|
||||
auto fields_id = context.args_type_info_stack().Pop();
|
||||
auto fields_id = context.struct_type_fields().AddCanonical(
|
||||
context.struct_type_fields_stack().PeekArray());
|
||||
context.struct_type_fields_stack().PopArray();
|
||||
|
||||
return context.AddInst<SemIR::CompleteTypeWitness>(
|
||||
node_id,
|
||||
|
||||
Reference in New Issue
Block a user