mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 07:14:42 +01:00
Ensure we evaluate instructions created in uncommon ways. (#3598)
Instructions created by splices during conversion are now evaluated, as are instructions created in cases where we first create a placeholder instruction and later replace it by a different instruction. This also removes the ability to set a parse node and instruction independently after creating an `InstId`, which could lead to them accidentally not matching.
This commit is contained in:
@@ -62,9 +62,9 @@ auto Context::VerifyOnFinish() -> void {
|
||||
CARBON_CHECK(params_or_args_stack_.empty()) << params_or_args_stack_.size();
|
||||
}
|
||||
|
||||
auto Context::AddInst(SemIR::ParseNodeAndInst parse_node_and_inst)
|
||||
auto Context::AddInstInNoBlock(SemIR::ParseNodeAndInst parse_node_and_inst)
|
||||
-> SemIR::InstId {
|
||||
auto inst_id = inst_block_stack_.AddInst(parse_node_and_inst);
|
||||
auto inst_id = sem_ir().insts().AddInNoBlock(parse_node_and_inst);
|
||||
CARBON_VLOG() << "AddInst: " << parse_node_and_inst.inst << "\n";
|
||||
|
||||
auto const_id = TryEvalInst(*this, inst_id, parse_node_and_inst.inst);
|
||||
@@ -77,10 +77,31 @@ auto Context::AddInst(SemIR::ParseNodeAndInst parse_node_and_inst)
|
||||
return inst_id;
|
||||
}
|
||||
|
||||
auto Context::AddInst(SemIR::ParseNodeAndInst parse_node_and_inst)
|
||||
-> SemIR::InstId {
|
||||
auto inst_id = AddInstInNoBlock(parse_node_and_inst);
|
||||
inst_block_stack_.AddInstId(inst_id);
|
||||
return inst_id;
|
||||
}
|
||||
|
||||
auto Context::AddPlaceholderInstInNoBlock(
|
||||
SemIR::ParseNodeAndInst parse_node_and_inst) -> SemIR::InstId {
|
||||
auto inst_id = sem_ir().insts().AddInNoBlock(parse_node_and_inst);
|
||||
CARBON_VLOG() << "AddPlaceholderInst: " << parse_node_and_inst.inst << "\n";
|
||||
return inst_id;
|
||||
}
|
||||
|
||||
auto Context::AddPlaceholderInst(SemIR::ParseNodeAndInst parse_node_and_inst)
|
||||
-> SemIR::InstId {
|
||||
auto inst_id = AddPlaceholderInstInNoBlock(parse_node_and_inst);
|
||||
inst_block_stack_.AddInstId(inst_id);
|
||||
return inst_id;
|
||||
}
|
||||
|
||||
auto Context::AddConstant(SemIR::Inst inst, bool is_symbolic)
|
||||
-> SemIR::ConstantId {
|
||||
// TODO: Deduplicate constants.
|
||||
auto inst_id = insts().AddInNoBlock(
|
||||
auto inst_id = sem_ir().insts().AddInNoBlock(
|
||||
SemIR::ParseNodeAndInst::Untyped(Parse::NodeId::Invalid, inst));
|
||||
constants().Add(inst_id);
|
||||
|
||||
@@ -98,6 +119,25 @@ auto Context::AddInstAndPush(SemIR::ParseNodeAndInst parse_node_and_inst)
|
||||
node_stack_.Push(parse_node_and_inst.parse_node, inst_id);
|
||||
}
|
||||
|
||||
auto Context::ReplaceInstBeforeConstantUse(
|
||||
SemIR::InstId inst_id, SemIR::ParseNodeAndInst parse_node_and_inst)
|
||||
-> void {
|
||||
sem_ir().insts().Set(inst_id, parse_node_and_inst);
|
||||
|
||||
CARBON_VLOG() << "ReplaceInst: " << inst_id << " -> "
|
||||
<< parse_node_and_inst.inst << "\n";
|
||||
|
||||
// Redo evaluation. This is only safe to do if this instruction has not
|
||||
// already been used as a constant, which is the caller's responsibility to
|
||||
// ensure.
|
||||
auto const_id = TryEvalInst(*this, inst_id, parse_node_and_inst.inst);
|
||||
if (const_id.is_constant()) {
|
||||
CARBON_VLOG() << "Constant: " << parse_node_and_inst.inst << " -> "
|
||||
<< const_id.inst_id() << "\n";
|
||||
}
|
||||
constant_values().Set(inst_id, const_id);
|
||||
}
|
||||
|
||||
auto Context::DiagnoseDuplicateName(Parse::NodeId parse_node,
|
||||
SemIR::InstId prev_def_id) -> void {
|
||||
CARBON_DIAGNOSTIC(NameDeclDuplicate, Error,
|
||||
@@ -203,9 +243,13 @@ auto Context::ResolveIfLazyImportRef(SemIR::InstId inst_id) -> void {
|
||||
.param_refs_id = SemIR::InstBlockId::Empty,
|
||||
.return_type_id = SemIR::TypeId::Invalid,
|
||||
.return_slot_id = SemIR::InstId::Invalid});
|
||||
insts().Set(inst_id, SemIR::FunctionDecl{
|
||||
GetBuiltinType(SemIR::BuiltinKind::FunctionType),
|
||||
function_id});
|
||||
ReplaceInstBeforeConstantUse(
|
||||
inst_id,
|
||||
// TODO: For diagnostic purposes, we should provide some form of
|
||||
// location for the function.
|
||||
{Parse::NodeId::Invalid,
|
||||
SemIR::FunctionDecl{GetBuiltinType(SemIR::BuiltinKind::FunctionType),
|
||||
function_id}});
|
||||
constant_values().Set(inst_id,
|
||||
SemIR::ConstantId::ForTemplateConstant(inst_id));
|
||||
break;
|
||||
@@ -218,8 +262,10 @@ auto Context::ResolveIfLazyImportRef(SemIR::InstId inst_id) -> void {
|
||||
// error.
|
||||
TODO(Parse::NodeId::Invalid,
|
||||
(llvm::Twine("TODO: support ") + import_inst.kind().name()).str());
|
||||
insts().Set(inst_id, SemIR::VarStorage{SemIR::TypeId::Error,
|
||||
SemIR::NameId::PackageNamespace});
|
||||
ReplaceInstBeforeConstantUse(
|
||||
inst_id, {Parse::NodeId::Invalid,
|
||||
SemIR::VarStorage{SemIR::TypeId::Error,
|
||||
SemIR::NameId::PackageNamespace}});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user