From bf4d59bc20d55f2cdab3e5c84d8f1e33a0fd9cd2 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Wed, 12 Nov 2025 10:18:31 -0800 Subject: [PATCH] Move ImportRefResolver function bodies out-of-line (#6355) This is intended to be a rote refactoring, also dropping a couple forward declarations that moving function bodies out-of-line renders unnecessary. --- toolchain/check/import_ref.cpp | 298 +++++++++++++++++---------------- 1 file changed, 153 insertions(+), 145 deletions(-) diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 606a01285a8f..63c94d7bfe33 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -143,8 +143,6 @@ auto VerifySameCanonicalImportIRInst(Context& context, SemIR::NameId name_id, } namespace { -class ImportRefResolver; - // The result of attempting to resolve an imported instruction to a constant. struct ResolveResult { // The new constant value, if known. @@ -174,9 +172,6 @@ struct ResolveResult { }; } // namespace -static auto TryResolveInst(ImportRefResolver& resolver, SemIR::InstId inst_id, - SemIR::ConstantId const_id) -> ResolveResult; - namespace { // A context within which we are performing an import. Tracks information about // the source and destination. This provides a restricted interface compared to @@ -455,45 +450,7 @@ class ImportRefResolver : public ImportContext { // Iteratively resolves an imported instruction's inner references until a // constant ID referencing the current IR is produced. See the class comment // for more details. - auto ResolveOneInst(SemIR::InstId inst_id) -> SemIR::ConstantId { - work_stack_.push_back({.inst_id = inst_id}); - while (!work_stack_.empty()) { - auto work = work_stack_.back(); - CARBON_CHECK(work.inst_id.has_value()); - - // Step 1: check for a constant value. - auto existing = FindResolvedConstId(work.inst_id); - if (existing.const_id.has_value() && !work.retry_with_constant_value) { - work_stack_.pop_back(); - continue; - } - - // Step 2: resolve the instruction. - initial_work_ = work_stack_.size(); - auto [new_const_id, _, retry] = - TryResolveInst(*this, work.inst_id, existing.const_id); - CARBON_CHECK(!HasNewWork() || retry); - - CARBON_CHECK( - !existing.const_id.has_value() || existing.const_id == new_const_id, - "Constant value changed in third phase."); - if (!existing.const_id.has_value()) { - SetResolvedConstId(work.inst_id, existing.indirect_insts, new_const_id); - } - - // Step 3: pop or retry. - if (retry) { - work_stack_[initial_work_ - 1].retry_with_constant_value = - new_const_id.has_value(); - } else { - work_stack_.pop_back(); - } - } - auto constant_id = - local_constant_values_for_import_insts().GetAttached(inst_id); - CARBON_CHECK(constant_id.has_value()); - return constant_id; - } + auto ResolveOneInst(SemIR::InstId inst_id) -> SemIR::ConstantId; // Performs resolution for one instruction and then performs all work we // deferred. @@ -511,26 +468,7 @@ class ImportRefResolver : public ImportContext { } // Wraps constant evaluation with logic to handle types. - // NOLINTNEXTLINE(misc-no-recursion) - auto ResolveType(SemIR::TypeId import_type_id) -> SemIR::TypeId { - if (!import_type_id.has_value()) { - return import_type_id; - } - - auto import_type_const_id = - import_ir().types().GetConstantId(import_type_id); - CARBON_CHECK(import_type_const_id.has_value()); - - if (auto import_type_inst_id = import_ir().types().GetAsTypeInstId( - import_ir().constant_values().GetInstId(import_type_const_id)); - SemIR::IsSingletonInstId(import_type_inst_id)) { - // Builtins don't require constant resolution; we can use them directly. - return GetSingletonType(local_context(), import_type_inst_id); - } else { - return local_context().types().GetTypeIdForTypeConstantId( - ResolveConstant(import_type_id.AsConstantId())); - } - } + auto ResolveType(SemIR::TypeId import_type_id) -> SemIR::TypeId; // Returns true if new unresolved constants were found as part of this // `Resolve` step. @@ -542,17 +480,7 @@ class ImportRefResolver : public ImportContext { // Returns the ConstantId for an InstId. Adds unresolved constants to // work_stack_. - auto GetLocalConstantValueOrPush(SemIR::InstId inst_id) -> SemIR::ConstantId { - if (!inst_id.has_value()) { - return SemIR::ConstantId::None; - } - auto const_id = - local_constant_values_for_import_insts().GetAttached(inst_id); - if (!const_id.has_value()) { - work_stack_.push_back({.inst_id = inst_id}); - } - return const_id; - } + auto GetLocalConstantValueOrPush(SemIR::InstId inst_id) -> SemIR::ConstantId; private: // A step in work_stack_. @@ -579,80 +507,12 @@ class ImportRefResolver : public ImportContext { // found indirectly, sets the constant for any indirect steps that don't // already have the constant. If a constant isn't found, returns the indirect // instructions so that they can have the resolved constant assigned later. - auto FindResolvedConstId(SemIR::InstId inst_id) -> ResolvedConstId { - ResolvedConstId result; - - if (auto existing_const_id = - local_constant_values_for_import_insts().GetAttached(inst_id); - existing_const_id.has_value()) { - result.const_id = existing_const_id; - return result; - } - - const auto* cursor_ir = &import_ir(); - auto cursor_inst_id = inst_id; - - while (true) { - auto import_ir_inst_id = - cursor_ir->insts().GetImportSource(cursor_inst_id); - if (!import_ir_inst_id.has_value()) { - return result; - } - auto ir_inst = cursor_ir->import_ir_insts().Get(import_ir_inst_id); - if (ir_inst.ir_id() == SemIR::ImportIRId::Cpp) { - local_context().TODO(SemIR::LocId::None, - "Unsupported: Importing C++ indirectly"); - SetResolvedConstId(inst_id, result.indirect_insts, - SemIR::ErrorInst::ConstantId); - result.const_id = SemIR::ErrorInst::ConstantId; - result.indirect_insts.clear(); - return result; - } - - const auto* prev_ir = cursor_ir; - auto prev_inst_id = cursor_inst_id; - - cursor_ir = cursor_ir->import_irs().Get(ir_inst.ir_id()).sem_ir; - auto cursor_ir_id = - AddImportIR(local_context(), {.decl_id = SemIR::InstId::None, - .is_export = false, - .sem_ir = cursor_ir}); - cursor_inst_id = ir_inst.inst_id(); - - CARBON_CHECK(cursor_ir != prev_ir || cursor_inst_id != prev_inst_id, - "{0}", cursor_ir->insts().Get(cursor_inst_id)); - - if (auto const_id = - local_context() - .import_ir_constant_values() - [local_context().sem_ir().import_irs().GetRawIndex( - cursor_ir_id)] - .GetAttached(cursor_inst_id); - const_id.has_value()) { - SetResolvedConstId(inst_id, result.indirect_insts, const_id); - result.const_id = const_id; - result.indirect_insts.clear(); - return result; - } else { - result.indirect_insts.push_back( - SemIR::ImportIRInst(cursor_ir_id, cursor_inst_id)); - } - } - } + auto FindResolvedConstId(SemIR::InstId inst_id) -> ResolvedConstId; // Sets a resolved constant into the current and indirect instructions. auto SetResolvedConstId(SemIR::InstId inst_id, llvm::ArrayRef indirect_insts, - SemIR::ConstantId const_id) -> void { - local_constant_values_for_import_insts().Set(inst_id, const_id); - for (auto indirect_inst : indirect_insts) { - local_context() - .import_ir_constant_values() - [local_context().sem_ir().import_irs().GetRawIndex( - indirect_inst.ir_id())] - .Set(indirect_inst.inst_id(), const_id); - } - } + SemIR::ConstantId const_id) -> void; auto PerformPendingWork() -> void; @@ -3653,6 +3513,154 @@ static auto TryResolveInst(ImportRefResolver& resolver, SemIR::InstId inst_id, return result; } +auto ImportRefResolver::ResolveOneInst(SemIR::InstId inst_id) + -> SemIR::ConstantId { + work_stack_.push_back({.inst_id = inst_id}); + while (!work_stack_.empty()) { + auto work = work_stack_.back(); + CARBON_CHECK(work.inst_id.has_value()); + + // Step 1: check for a constant value. + auto existing = FindResolvedConstId(work.inst_id); + if (existing.const_id.has_value() && !work.retry_with_constant_value) { + work_stack_.pop_back(); + continue; + } + + // Step 2: resolve the instruction. + initial_work_ = work_stack_.size(); + auto [new_const_id, _, retry] = + TryResolveInst(*this, work.inst_id, existing.const_id); + CARBON_CHECK(!HasNewWork() || retry); + + CARBON_CHECK( + !existing.const_id.has_value() || existing.const_id == new_const_id, + "Constant value changed in third phase."); + if (!existing.const_id.has_value()) { + SetResolvedConstId(work.inst_id, existing.indirect_insts, new_const_id); + } + + // Step 3: pop or retry. + if (retry) { + work_stack_[initial_work_ - 1].retry_with_constant_value = + new_const_id.has_value(); + } else { + work_stack_.pop_back(); + } + } + auto constant_id = + local_constant_values_for_import_insts().GetAttached(inst_id); + CARBON_CHECK(constant_id.has_value()); + return constant_id; +} + +// NOLINTNEXTLINE(misc-no-recursion) +auto ImportRefResolver::ResolveType(SemIR::TypeId import_type_id) + -> SemIR::TypeId { + if (!import_type_id.has_value()) { + return import_type_id; + } + + auto import_type_const_id = import_ir().types().GetConstantId(import_type_id); + CARBON_CHECK(import_type_const_id.has_value()); + + if (auto import_type_inst_id = import_ir().types().GetAsTypeInstId( + import_ir().constant_values().GetInstId(import_type_const_id)); + SemIR::IsSingletonInstId(import_type_inst_id)) { + // Builtins don't require constant resolution; we can use them directly. + return GetSingletonType(local_context(), import_type_inst_id); + } else { + return local_context().types().GetTypeIdForTypeConstantId( + ResolveConstant(import_type_id.AsConstantId())); + } +} + +auto ImportRefResolver::GetLocalConstantValueOrPush(SemIR::InstId inst_id) + -> SemIR::ConstantId { + if (!inst_id.has_value()) { + return SemIR::ConstantId::None; + } + auto const_id = local_constant_values_for_import_insts().GetAttached(inst_id); + if (!const_id.has_value()) { + work_stack_.push_back({.inst_id = inst_id}); + } + return const_id; +} + +auto ImportRefResolver::FindResolvedConstId(SemIR::InstId inst_id) + -> ResolvedConstId { + ResolvedConstId result; + + if (auto existing_const_id = + local_constant_values_for_import_insts().GetAttached(inst_id); + existing_const_id.has_value()) { + result.const_id = existing_const_id; + return result; + } + + const auto* cursor_ir = &import_ir(); + auto cursor_inst_id = inst_id; + + while (true) { + auto import_ir_inst_id = cursor_ir->insts().GetImportSource(cursor_inst_id); + if (!import_ir_inst_id.has_value()) { + return result; + } + auto ir_inst = cursor_ir->import_ir_insts().Get(import_ir_inst_id); + if (ir_inst.ir_id() == SemIR::ImportIRId::Cpp) { + local_context().TODO(SemIR::LocId::None, + "Unsupported: Importing C++ indirectly"); + SetResolvedConstId(inst_id, result.indirect_insts, + SemIR::ErrorInst::ConstantId); + result.const_id = SemIR::ErrorInst::ConstantId; + result.indirect_insts.clear(); + return result; + } + + const auto* prev_ir = cursor_ir; + auto prev_inst_id = cursor_inst_id; + + cursor_ir = cursor_ir->import_irs().Get(ir_inst.ir_id()).sem_ir; + auto cursor_ir_id = + AddImportIR(local_context(), {.decl_id = SemIR::InstId::None, + .is_export = false, + .sem_ir = cursor_ir}); + cursor_inst_id = ir_inst.inst_id(); + + CARBON_CHECK(cursor_ir != prev_ir || cursor_inst_id != prev_inst_id, "{0}", + cursor_ir->insts().Get(cursor_inst_id)); + + if (auto const_id = + local_context() + .import_ir_constant_values() + [local_context().sem_ir().import_irs().GetRawIndex( + cursor_ir_id)] + .GetAttached(cursor_inst_id); + const_id.has_value()) { + SetResolvedConstId(inst_id, result.indirect_insts, const_id); + result.const_id = const_id; + result.indirect_insts.clear(); + return result; + } else { + result.indirect_insts.push_back( + SemIR::ImportIRInst(cursor_ir_id, cursor_inst_id)); + } + } +} + +auto ImportRefResolver::SetResolvedConstId( + SemIR::InstId inst_id, llvm::ArrayRef indirect_insts, + SemIR::ConstantId const_id) -> void { + local_constant_values_for_import_insts().Set(inst_id, const_id); + for (auto indirect_inst : indirect_insts) { + local_context() + .import_ir_constant_values() + [local_context().sem_ir().import_irs().GetRawIndex( + indirect_inst.ir_id())] + .Set(indirect_inst.inst_id(), const_id); + } +} + // Resolves and returns the local contents for an imported instruction block // of constant instructions. static auto ResolveLocalInstBlockContents(ImportRefResolver& resolver,