Skip to content

Commit 14ac7e5

Browse files
committed
Rewrite generic binding imports to use AddLoadedImportRef
1 parent b5bdfdd commit 14ac7e5

File tree

3 files changed

+81
-64
lines changed

3 files changed

+81
-64
lines changed

toolchain/check/import_ref.cpp

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -434,15 +434,13 @@ class ImportRefResolver : public ImportContext {
434434

435435
// Performs resolution for one instruction and then performs all work we
436436
// deferred.
437-
// NOLINTNEXTLINE(misc-no-recursion)
438437
auto Resolve(SemIR::InstId inst_id) -> SemIR::ConstantId {
439438
auto const_id = ResolveOneInst(inst_id);
440439
PerformPendingWork();
441440
return const_id;
442441
}
443442

444443
// Wraps constant evaluation with logic to handle constants.
445-
// NOLINTNEXTLINE(misc-no-recursion)
446444
auto ResolveConstant(SemIR::ConstantId import_const_id) -> SemIR::ConstantId {
447445
return Resolve(GetInstWithConstantValue(import_ir(), import_const_id));
448446
}
@@ -511,6 +509,18 @@ static auto AddImportRef(ImportContext& context, SemIR::InstId inst_id,
511509
entity_name_id);
512510
}
513511

512+
// Handles setting a constant on instructions related to an import.
513+
static auto SetIndirectConstantValues(
514+
Context& context, llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,
515+
SemIR::ConstantId constant_id) -> void {
516+
for (const auto& import_ir_inst : indirect_insts) {
517+
auto ir_index =
518+
context.sem_ir().import_irs().GetRawIndex(import_ir_inst.ir_id());
519+
context.import_ir_constant_values()[ir_index].Set(import_ir_inst.inst_id(),
520+
constant_id);
521+
}
522+
}
523+
514524
// Adds an import_ref instruction for an instruction that we have already loaded
515525
// from an imported IR, with a known constant value. This is useful when the
516526
// instruction has a symbolic constant value, in order to produce an instruction
@@ -622,7 +632,7 @@ static auto GetLocalTypeInstId(ImportRefResolver& resolver,
622632
// The input instruction is a TypeInstId, and import does not change the type
623633
// of instructions, so the result is also a valid TypeInstId.
624634
return SemIR::TypeInstId::UnsafeMake(
625-
GetLocalConstantInstId(resolver, static_cast<SemIR::InstId>(inst_id)));
635+
GetLocalConstantInstId(resolver, inst_id));
626636
}
627637

628638
// Returns the ConstantId for a TypeId. Adds unresolved constants to
@@ -777,31 +787,65 @@ static auto MakeIncompleteGeneric(ImportContext& context, SemIR::InstId decl_id,
777787
namespace {
778788
// Local information associated with an imported generic.
779789
struct GenericData {
780-
// TODO: Delete `GenericData` if we still don't use it once generic import is
781-
// more stable.
790+
struct Binding {
791+
// The attached type's constant, which may differ from the type on the
792+
// constant. This needs to be preserved for the ImportRef.
793+
SemIR::ConstantId type_constant_id;
794+
SemIR::ConstantId inst_constant_id;
795+
};
796+
llvm::SmallVector<Binding> bindings;
782797
};
783798
} // namespace
784799

785800
// Gets a local version of the data associated with a generic.
786-
static auto GetLocalGenericData(ImportRefResolver& /*resolver*/,
787-
SemIR::GenericId /*generic_id*/)
801+
static auto GetLocalGenericData(ImportRefResolver& resolver,
802+
SemIR::GenericId import_generic_id)
788803
-> GenericData {
789-
return {};
804+
GenericData generic_data;
805+
if (import_generic_id.has_value()) {
806+
const auto& import_generic =
807+
resolver.import_generics().Get(import_generic_id);
808+
809+
if (import_generic.bindings_id.has_value()) {
810+
auto import_bindings =
811+
resolver.import_inst_blocks().Get(import_generic.bindings_id);
812+
generic_data.bindings.reserve(import_bindings.size());
813+
for (auto import_inst_id : import_bindings) {
814+
generic_data.bindings.push_back(
815+
{.type_constant_id = GetLocalConstantId(
816+
resolver,
817+
resolver.import_insts().GetAttachedType(import_inst_id)),
818+
.inst_constant_id = GetLocalConstantId(resolver, import_inst_id)});
819+
}
820+
}
821+
}
822+
return generic_data;
790823
}
791824

792825
// Adds the given local generic data to the given generic.
793826
static auto SetGenericData(ImportContext& context,
794827
SemIR::GenericId import_generic_id,
795828
SemIR::GenericId new_generic_id,
796-
const GenericData& /*generic_data*/) -> void {
829+
const GenericData& generic_data) -> void {
797830
if (!import_generic_id.has_value()) {
798831
return;
799832
}
800833

801834
const auto& import_generic = context.import_generics().Get(import_generic_id);
802835
auto& new_generic = context.local_generics().Get(new_generic_id);
803-
new_generic.bindings_id =
804-
GetLocalImportRefInstBlock(context, import_generic.bindings_id);
836+
837+
auto import_bindings =
838+
context.import_inst_blocks().Get(import_generic.bindings_id);
839+
llvm::SmallVector<SemIR::InstId> new_bindings;
840+
new_bindings.reserve(import_bindings.size());
841+
for (auto [import_binding_id, binding] :
842+
llvm::zip_equal(import_bindings, generic_data.bindings)) {
843+
auto local_type_id = context.local_types().GetTypeIdForTypeConstantId(
844+
binding.type_constant_id);
845+
new_bindings.push_back(AddLoadedImportRef(
846+
context, local_type_id, import_binding_id, binding.inst_constant_id));
847+
}
848+
new_generic.bindings_id = context.local_inst_blocks().Add(new_bindings);
805849

806850
// Track that we need to fill in the remaining information in
807851
// FinishPendingGeneric.
@@ -3388,10 +3432,6 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
33883432
// `None` if more has been added to the stack. This is the same as
33893433
// TryResolveInst, except that it may resolve symbolic constants as canonical
33903434
// constants instead of as constants associated with a particular generic.
3391-
//
3392-
// TODO: Consider refactoring the body to a helper in order to eliminate
3393-
// recursion.
3394-
// NOLINTNEXTLINE(misc-no-recursion)
33953435
static auto TryResolveInstCanonical(ImportRefResolver& resolver,
33963436
SemIR::InstId inst_id,
33973437
SemIR::ConstantId const_id)
@@ -3767,7 +3807,6 @@ auto ImportRefResolver::ResolveOneInst(SemIR::InstId inst_id)
37673807
return constant_id;
37683808
}
37693809

3770-
// NOLINTNEXTLINE(misc-no-recursion)
37713810
auto ImportRefResolver::ResolveType(SemIR::TypeId import_type_id)
37723811
-> SemIR::TypeId {
37733812
if (!import_type_id.has_value()) {
@@ -3865,13 +3904,7 @@ auto ImportRefResolver::SetResolvedConstId(
38653904
SemIR::InstId inst_id, llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,
38663905
SemIR::ConstantId const_id) -> void {
38673906
local_constant_values_for_import_insts().Set(inst_id, const_id);
3868-
for (auto indirect_inst : indirect_insts) {
3869-
local_context()
3870-
.import_ir_constant_values()
3871-
[local_context().sem_ir().import_irs().GetRawIndex(
3872-
indirect_inst.ir_id())]
3873-
.Set(indirect_inst.inst_id(), const_id);
3874-
}
3907+
SetIndirectConstantValues(local_context(), indirect_insts, const_id);
38753908
}
38763909

38773910
// Resolves and returns the local contents for an imported instruction block
@@ -3918,22 +3951,13 @@ static auto ResolveLocalEvalBlock(ImportRefResolver& resolver,
39183951
}
39193952

39203953
// Fills in the remaining information in a partially-imported generic.
3921-
// NOLINTNEXTLINE(misc-no-recursion)
39223954
static auto FinishPendingGeneric(ImportRefResolver& resolver,
39233955
ImportContext::PendingGeneric pending)
39243956
-> void {
39253957
const auto& import_generic =
39263958
resolver.import_generics().Get(pending.import_id);
39273959
auto& local_generic = resolver.local_generics().Get(pending.local_id);
39283960

3929-
// Load the bindings for the generic eagerly; they're used to form the self
3930-
// specific.
3931-
// TODO: Avoid recursion.
3932-
for (auto binding_id :
3933-
resolver.local_inst_blocks().Get(local_generic.bindings_id)) {
3934-
LoadImportRef(resolver.local_context(), binding_id);
3935-
}
3936-
39373961
local_generic.decl_block_id =
39383962
ResolveLocalEvalBlock(resolver, import_generic, pending.local_id,
39393963
SemIR::GenericInstIndex::Region::Declaration);
@@ -3983,7 +4007,6 @@ static auto FinishPendingSpecific(ImportRefResolver& resolver,
39834007
}
39844008

39854009
// Perform any work that we deferred until the end of the main Resolve loop.
3986-
// NOLINTNEXTLINE(misc-no-recursion)
39874010
auto ImportRefResolver::PerformPendingWork() -> void {
39884011
// Note that the individual Finish steps can add new pending work, so keep
39894012
// going until we have no more work to do.
@@ -4047,7 +4070,6 @@ static auto GetInstForLoad(Context& context,
40474070
}
40484071
}
40494072

4050-
// NOLINTNEXTLINE(misc-no-recursion)
40514073
auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void {
40524074
auto inst = context.insts().TryGetAs<SemIR::ImportRefUnloaded>(inst_id);
40534075
if (!inst) {
@@ -4092,12 +4114,7 @@ auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void {
40924114

40934115
// Store the constant for both the ImportRefLoaded and indirect instructions.
40944116
context.constant_values().Set(inst_id, constant_id);
4095-
for (const auto& import_ir_inst : indirect_insts) {
4096-
context
4097-
.import_ir_constant_values()[context.sem_ir().import_irs().GetRawIndex(
4098-
import_ir_inst.ir_id())]
4099-
.Set(import_ir_inst.inst_id(), constant_id);
4100-
}
4117+
SetIndirectConstantValues(context, indirect_insts, constant_id);
41014118
}
41024119

41034120
auto ImportImplsFromApiFile(Context& context) -> void {

0 commit comments

Comments
 (0)