|
@@ -60,7 +60,7 @@ class Worklist {
|
|
|
|
|
|
|
|
// Pushes the specified operand onto the worklist.
|
|
// Pushes the specified operand onto the worklist.
|
|
|
static auto PushOperand(Context& context, Worklist& worklist,
|
|
static auto PushOperand(Context& context, Worklist& worklist,
|
|
|
- SemIR::IdKind kind, int32_t arg) -> void {
|
|
|
|
|
|
|
+ SemIR::Inst::ArgAndKind arg) -> void {
|
|
|
auto push_block = [&](SemIR::InstBlockId block_id) {
|
|
auto push_block = [&](SemIR::InstBlockId block_id) {
|
|
|
for (auto inst_id :
|
|
for (auto inst_id :
|
|
|
context.inst_blocks().Get(SemIR::InstBlockId(block_id))) {
|
|
context.inst_blocks().Get(SemIR::InstBlockId(block_id))) {
|
|
@@ -74,45 +74,50 @@ static auto PushOperand(Context& context, Worklist& worklist,
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- switch (kind) {
|
|
|
|
|
|
|
+ switch (arg.kind) {
|
|
|
case SemIR::IdKind::For<SemIR::InstId>:
|
|
case SemIR::IdKind::For<SemIR::InstId>:
|
|
|
|
|
+ if (auto inst_id = arg.As<SemIR::InstId>(); inst_id.has_value()) {
|
|
|
|
|
+ worklist.Push(inst_id);
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
case SemIR::IdKind::For<SemIR::MetaInstId>:
|
|
case SemIR::IdKind::For<SemIR::MetaInstId>:
|
|
|
- if (SemIR::InstId inst_id(arg); inst_id.has_value()) {
|
|
|
|
|
|
|
+ if (auto inst_id = arg.As<SemIR::MetaInstId>(); inst_id.has_value()) {
|
|
|
worklist.Push(inst_id);
|
|
worklist.Push(inst_id);
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
case SemIR::IdKind::For<SemIR::TypeId>:
|
|
case SemIR::IdKind::For<SemIR::TypeId>:
|
|
|
- if (SemIR::TypeId type_id(arg); type_id.has_value()) {
|
|
|
|
|
|
|
+ if (auto type_id = arg.As<SemIR::TypeId>(); type_id.has_value()) {
|
|
|
worklist.Push(context.types().GetInstId(type_id));
|
|
worklist.Push(context.types().GetInstId(type_id));
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
case SemIR::IdKind::For<SemIR::InstBlockId>:
|
|
case SemIR::IdKind::For<SemIR::InstBlockId>:
|
|
|
- push_block(SemIR::InstBlockId(arg));
|
|
|
|
|
|
|
+ push_block(arg.As<SemIR::InstBlockId>());
|
|
|
break;
|
|
break;
|
|
|
case SemIR::IdKind::For<SemIR::StructTypeFieldsId>: {
|
|
case SemIR::IdKind::For<SemIR::StructTypeFieldsId>: {
|
|
|
- for (auto field :
|
|
|
|
|
- context.struct_type_fields().Get(SemIR::StructTypeFieldsId(arg))) {
|
|
|
|
|
|
|
+ for (auto field : context.struct_type_fields().Get(
|
|
|
|
|
+ arg.As<SemIR::StructTypeFieldsId>())) {
|
|
|
worklist.Push(context.types().GetInstId(field.type_id));
|
|
worklist.Push(context.types().GetInstId(field.type_id));
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case SemIR::IdKind::For<SemIR::TypeBlockId>:
|
|
case SemIR::IdKind::For<SemIR::TypeBlockId>:
|
|
|
- for (auto type_id : context.type_blocks().Get(SemIR::TypeBlockId(arg))) {
|
|
|
|
|
|
|
+ for (auto type_id :
|
|
|
|
|
+ context.type_blocks().Get(arg.As<SemIR::TypeBlockId>())) {
|
|
|
worklist.Push(context.types().GetInstId(type_id));
|
|
worklist.Push(context.types().GetInstId(type_id));
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
case SemIR::IdKind::For<SemIR::SpecificId>:
|
|
case SemIR::IdKind::For<SemIR::SpecificId>:
|
|
|
- push_specific(SemIR::SpecificId(arg));
|
|
|
|
|
|
|
+ push_specific(arg.As<SemIR::SpecificId>());
|
|
|
break;
|
|
break;
|
|
|
case SemIR::IdKind::For<SemIR::SpecificInterfaceId>: {
|
|
case SemIR::IdKind::For<SemIR::SpecificInterfaceId>: {
|
|
|
- auto interface =
|
|
|
|
|
- context.specific_interfaces().Get(SemIR::SpecificInterfaceId(arg));
|
|
|
|
|
|
|
+ auto interface = context.specific_interfaces().Get(
|
|
|
|
|
+ arg.As<SemIR::SpecificInterfaceId>());
|
|
|
push_specific(interface.specific_id);
|
|
push_specific(interface.specific_id);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case SemIR::IdKind::For<SemIR::FacetTypeId>: {
|
|
case SemIR::IdKind::For<SemIR::FacetTypeId>: {
|
|
|
const auto& facet_type_info =
|
|
const auto& facet_type_info =
|
|
|
- context.facet_types().Get(SemIR::FacetTypeId(arg));
|
|
|
|
|
|
|
+ context.facet_types().Get(arg.As<SemIR::FacetTypeId>());
|
|
|
for (auto interface : facet_type_info.impls_constraints) {
|
|
for (auto interface : facet_type_info.impls_constraints) {
|
|
|
push_specific(interface.specific_id);
|
|
push_specific(interface.specific_id);
|
|
|
}
|
|
}
|
|
@@ -137,16 +142,14 @@ static auto PushOperand(Context& context, Worklist& worklist,
|
|
|
static auto ExpandOperands(Context& context, Worklist& worklist,
|
|
static auto ExpandOperands(Context& context, Worklist& worklist,
|
|
|
SemIR::InstId inst_id) -> void {
|
|
SemIR::InstId inst_id) -> void {
|
|
|
auto inst = context.insts().Get(inst_id);
|
|
auto inst = context.insts().Get(inst_id);
|
|
|
- auto kinds = inst.ArgKinds();
|
|
|
|
|
- PushOperand(context, worklist, SemIR::IdKind::For<SemIR::TypeId>,
|
|
|
|
|
- inst.type_id().index);
|
|
|
|
|
- PushOperand(context, worklist, kinds.first, inst.arg0());
|
|
|
|
|
- PushOperand(context, worklist, kinds.second, inst.arg1());
|
|
|
|
|
|
|
+ PushOperand(context, worklist, inst.type_id_and_kind());
|
|
|
|
|
+ PushOperand(context, worklist, inst.arg0_and_kind());
|
|
|
|
|
+ PushOperand(context, worklist, inst.arg1_and_kind());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Pops the specified operand from the worklist and returns it.
|
|
// Pops the specified operand from the worklist and returns it.
|
|
|
-static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
|
|
|
|
|
- int32_t arg) -> int32_t {
|
|
|
|
|
|
|
+static auto PopOperand(Context& context, Worklist& worklist,
|
|
|
|
|
+ SemIR::Inst::ArgAndKind arg) -> int32_t {
|
|
|
auto pop_block_id = [&](SemIR::InstBlockId old_inst_block_id) {
|
|
auto pop_block_id = [&](SemIR::InstBlockId old_inst_block_id) {
|
|
|
auto size = context.inst_blocks().Get(old_inst_block_id).size();
|
|
auto size = context.inst_blocks().Get(old_inst_block_id).size();
|
|
|
SemIR::CopyOnWriteInstBlock new_inst_block(context.sem_ir(),
|
|
SemIR::CopyOnWriteInstBlock new_inst_block(context.sem_ir(),
|
|
@@ -166,27 +169,33 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
|
|
|
return context.specifics().GetOrAdd(specific.generic_id, args_id);
|
|
return context.specifics().GetOrAdd(specific.generic_id, args_id);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- switch (kind) {
|
|
|
|
|
- case SemIR::IdKind::For<SemIR::InstId>:
|
|
|
|
|
|
|
+ switch (arg.kind) {
|
|
|
|
|
+ case SemIR::IdKind::For<SemIR::InstId>: {
|
|
|
|
|
+ auto inst_id = arg.As<SemIR::InstId>();
|
|
|
|
|
+ if (!inst_id.has_value()) {
|
|
|
|
|
+ return arg.value;
|
|
|
|
|
+ }
|
|
|
|
|
+ return worklist.Pop().index;
|
|
|
|
|
+ }
|
|
|
case SemIR::IdKind::For<SemIR::MetaInstId>: {
|
|
case SemIR::IdKind::For<SemIR::MetaInstId>: {
|
|
|
- SemIR::InstId inst_id(arg);
|
|
|
|
|
|
|
+ auto inst_id = arg.As<SemIR::MetaInstId>();
|
|
|
if (!inst_id.has_value()) {
|
|
if (!inst_id.has_value()) {
|
|
|
- return arg;
|
|
|
|
|
|
|
+ return arg.value;
|
|
|
}
|
|
}
|
|
|
return worklist.Pop().index;
|
|
return worklist.Pop().index;
|
|
|
}
|
|
}
|
|
|
case SemIR::IdKind::For<SemIR::TypeId>: {
|
|
case SemIR::IdKind::For<SemIR::TypeId>: {
|
|
|
- SemIR::TypeId type_id(arg);
|
|
|
|
|
|
|
+ auto type_id = arg.As<SemIR::TypeId>();
|
|
|
if (!type_id.has_value()) {
|
|
if (!type_id.has_value()) {
|
|
|
- return arg;
|
|
|
|
|
|
|
+ return arg.value;
|
|
|
}
|
|
}
|
|
|
return context.types().GetTypeIdForTypeInstId(worklist.Pop()).index;
|
|
return context.types().GetTypeIdForTypeInstId(worklist.Pop()).index;
|
|
|
}
|
|
}
|
|
|
case SemIR::IdKind::For<SemIR::InstBlockId>: {
|
|
case SemIR::IdKind::For<SemIR::InstBlockId>: {
|
|
|
- return pop_block_id(SemIR::InstBlockId(arg)).index;
|
|
|
|
|
|
|
+ return pop_block_id(arg.As<SemIR::InstBlockId>()).index;
|
|
|
}
|
|
}
|
|
|
case SemIR::IdKind::For<SemIR::StructTypeFieldsId>: {
|
|
case SemIR::IdKind::For<SemIR::StructTypeFieldsId>: {
|
|
|
- SemIR::StructTypeFieldsId old_fields_id(arg);
|
|
|
|
|
|
|
+ auto old_fields_id = arg.As<SemIR::StructTypeFieldsId>();
|
|
|
auto old_fields = context.struct_type_fields().Get(old_fields_id);
|
|
auto old_fields = context.struct_type_fields().Get(old_fields_id);
|
|
|
SemIR::CopyOnWriteStructTypeFieldsBlock new_fields(context.sem_ir(),
|
|
SemIR::CopyOnWriteStructTypeFieldsBlock new_fields(context.sem_ir(),
|
|
|
old_fields_id);
|
|
old_fields_id);
|
|
@@ -198,7 +207,7 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
|
|
|
return new_fields.GetCanonical().index;
|
|
return new_fields.GetCanonical().index;
|
|
|
}
|
|
}
|
|
|
case SemIR::IdKind::For<SemIR::TypeBlockId>: {
|
|
case SemIR::IdKind::For<SemIR::TypeBlockId>: {
|
|
|
- SemIR::TypeBlockId old_type_block_id(arg);
|
|
|
|
|
|
|
+ auto old_type_block_id = arg.As<SemIR::TypeBlockId>();
|
|
|
auto size = context.type_blocks().Get(old_type_block_id).size();
|
|
auto size = context.type_blocks().Get(old_type_block_id).size();
|
|
|
SemIR::CopyOnWriteTypeBlock new_type_block(context.sem_ir(),
|
|
SemIR::CopyOnWriteTypeBlock new_type_block(context.sem_ir(),
|
|
|
old_type_block_id);
|
|
old_type_block_id);
|
|
@@ -209,11 +218,11 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
|
|
|
return new_type_block.GetCanonical().index;
|
|
return new_type_block.GetCanonical().index;
|
|
|
}
|
|
}
|
|
|
case SemIR::IdKind::For<SemIR::SpecificId>: {
|
|
case SemIR::IdKind::For<SemIR::SpecificId>: {
|
|
|
- return pop_specific(SemIR::SpecificId(arg)).index;
|
|
|
|
|
|
|
+ return pop_specific(arg.As<SemIR::SpecificId>()).index;
|
|
|
}
|
|
}
|
|
|
case SemIR::IdKind::For<SemIR::SpecificInterfaceId>: {
|
|
case SemIR::IdKind::For<SemIR::SpecificInterfaceId>: {
|
|
|
- auto interface =
|
|
|
|
|
- context.specific_interfaces().Get(SemIR::SpecificInterfaceId(arg));
|
|
|
|
|
|
|
+ auto interface = context.specific_interfaces().Get(
|
|
|
|
|
+ arg.As<SemIR::SpecificInterfaceId>());
|
|
|
auto specific_id = pop_specific(interface.specific_id);
|
|
auto specific_id = pop_specific(interface.specific_id);
|
|
|
return context.specific_interfaces()
|
|
return context.specific_interfaces()
|
|
|
.Add({
|
|
.Add({
|
|
@@ -224,7 +233,7 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
|
|
|
}
|
|
}
|
|
|
case SemIR::IdKind::For<SemIR::FacetTypeId>: {
|
|
case SemIR::IdKind::For<SemIR::FacetTypeId>: {
|
|
|
const auto& old_facet_type_info =
|
|
const auto& old_facet_type_info =
|
|
|
- context.facet_types().Get(SemIR::FacetTypeId(arg));
|
|
|
|
|
|
|
+ context.facet_types().Get(arg.As<SemIR::FacetTypeId>());
|
|
|
SemIR::FacetTypeInfo new_facet_type_info;
|
|
SemIR::FacetTypeInfo new_facet_type_info;
|
|
|
// Since these were added to a stack, we get them back in reverse order.
|
|
// Since these were added to a stack, we get them back in reverse order.
|
|
|
new_facet_type_info.rewrite_constraints.resize(
|
|
new_facet_type_info.rewrite_constraints.resize(
|
|
@@ -252,7 +261,7 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
|
|
|
return context.facet_types().Add(new_facet_type_info).index;
|
|
return context.facet_types().Add(new_facet_type_info).index;
|
|
|
}
|
|
}
|
|
|
default:
|
|
default:
|
|
|
- return arg;
|
|
|
|
|
|
|
+ return arg.value;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -261,14 +270,11 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
|
|
|
static auto Rebuild(Context& context, Worklist& worklist, SemIR::InstId inst_id,
|
|
static auto Rebuild(Context& context, Worklist& worklist, SemIR::InstId inst_id,
|
|
|
const SubstInstCallbacks& callbacks) -> SemIR::InstId {
|
|
const SubstInstCallbacks& callbacks) -> SemIR::InstId {
|
|
|
auto inst = context.insts().Get(inst_id);
|
|
auto inst = context.insts().Get(inst_id);
|
|
|
- auto kinds = inst.ArgKinds();
|
|
|
|
|
|
|
|
|
|
// Note that we pop in reverse order because we pushed them in forwards order.
|
|
// Note that we pop in reverse order because we pushed them in forwards order.
|
|
|
- int32_t arg1 = PopOperand(context, worklist, kinds.second, inst.arg1());
|
|
|
|
|
- int32_t arg0 = PopOperand(context, worklist, kinds.first, inst.arg0());
|
|
|
|
|
- int32_t type_id =
|
|
|
|
|
- PopOperand(context, worklist, SemIR::IdKind::For<SemIR::TypeId>,
|
|
|
|
|
- inst.type_id().index);
|
|
|
|
|
|
|
+ int32_t arg1 = PopOperand(context, worklist, inst.arg1_and_kind());
|
|
|
|
|
+ int32_t arg0 = PopOperand(context, worklist, inst.arg0_and_kind());
|
|
|
|
|
+ int32_t type_id = PopOperand(context, worklist, inst.type_id_and_kind());
|
|
|
if (type_id == inst.type_id().index && arg0 == inst.arg0() &&
|
|
if (type_id == inst.type_id().index && arg0 == inst.arg0() &&
|
|
|
arg1 == inst.arg1()) {
|
|
arg1 == inst.arg1()) {
|
|
|
return callbacks.ReuseUnchanged(inst_id);
|
|
return callbacks.ReuseUnchanged(inst_id);
|