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.
This commit is contained in:
Jon Ross-Perkins
2025-11-12 18:18:31 +00:00
committed by GitHub
parent faada92cee
commit bf4d59bc20
+153 -145
View File
@@ -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<SemIR::ImportIRInst> 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<SemIR::ImportIRInst> 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,