mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
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:
+153
-145
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user