mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 09:51:04 +01:00
Switch GetNodeBlock and GetTypeBlock to return an ArrayRef (#3220)
This removes the risk of accidentally performing a vector copy when calling these functions, and is a preparation step towards the new node block allocation design. This required changing how we build call expressions. Instead of finishing the argument block and then later adding a return slot, we now delay finishing the argument block and checking for conversions to parameter types until after we've added the return slot to it.
This commit is contained in:
+35
-16
@@ -69,6 +69,11 @@ auto Context::AddNodeToBlock(SemIR::NodeBlockId block, SemIR::Node node)
|
||||
return semantics_ir_->AddNode(block, node);
|
||||
}
|
||||
|
||||
auto Context::AddNodeIdToBlock(SemIR::NodeBlockId block, SemIR::NodeId node_id)
|
||||
-> void {
|
||||
semantics_ir_->AddNodeId(block, node_id);
|
||||
}
|
||||
|
||||
auto Context::AddNodeAndPush(Parse::Node parse_node, SemIR::Node node) -> void {
|
||||
auto node_id = AddNode(node);
|
||||
node_stack_.Push(parse_node, node_id);
|
||||
@@ -436,7 +441,8 @@ auto Context::HandleDiscardedExpression(SemIR::NodeId expr_id) -> void {
|
||||
auto Context::ImplicitAsForArgs(Parse::Node call_parse_node,
|
||||
SemIR::NodeBlockId arg_refs_id,
|
||||
Parse::Node param_parse_node,
|
||||
SemIR::NodeBlockId param_refs_id) -> bool {
|
||||
SemIR::NodeBlockId param_refs_id,
|
||||
bool has_return_slot) -> bool {
|
||||
// If both arguments and parameters are empty, return quickly. Otherwise,
|
||||
// we'll fetch both so that errors are consistent.
|
||||
if (arg_refs_id == SemIR::NodeBlockId::Empty &&
|
||||
@@ -444,8 +450,16 @@ auto Context::ImplicitAsForArgs(Parse::Node call_parse_node,
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& arg_refs = semantics_ir_->GetNodeBlock(arg_refs_id);
|
||||
const auto& param_refs = semantics_ir_->GetNodeBlock(param_refs_id);
|
||||
auto arg_refs = semantics_ir_->GetNodeBlock(arg_refs_id);
|
||||
auto param_refs = semantics_ir_->GetNodeBlock(param_refs_id);
|
||||
|
||||
if (has_return_slot) {
|
||||
// There's no entry in the parameter block for the return slot, so ignore
|
||||
// the corresponding entry in the argument block.
|
||||
// TODO: Consider adding the return slot to the parameter list.
|
||||
CARBON_CHECK(!arg_refs.empty()) << "missing return slot";
|
||||
arg_refs = arg_refs.drop_back();
|
||||
}
|
||||
|
||||
// If sizes mismatch, fail early.
|
||||
if (arg_refs.size() != param_refs.size()) {
|
||||
@@ -581,14 +595,23 @@ auto Context::ParamOrArgComma(bool for_args) -> void {
|
||||
ParamOrArgSave(for_args);
|
||||
}
|
||||
|
||||
auto Context::ParamOrArgEnd(bool for_args, Parse::NodeKind start_kind)
|
||||
-> SemIR::NodeBlockId {
|
||||
auto Context::ParamOrArgEndNoPop(bool for_args, Parse::NodeKind start_kind)
|
||||
-> void {
|
||||
if (parse_tree_->node_kind(node_stack_.PeekParseNode()) != start_kind) {
|
||||
ParamOrArgSave(for_args);
|
||||
}
|
||||
}
|
||||
|
||||
auto Context::ParamOrArgPop() -> SemIR::NodeBlockId {
|
||||
return params_or_args_stack_.Pop();
|
||||
}
|
||||
|
||||
auto Context::ParamOrArgEnd(bool for_args, Parse::NodeKind start_kind)
|
||||
-> SemIR::NodeBlockId {
|
||||
ParamOrArgEndNoPop(for_args, start_kind);
|
||||
return ParamOrArgPop();
|
||||
}
|
||||
|
||||
auto Context::ParamOrArgSave(bool for_args) -> void {
|
||||
auto [entry_parse_node, entry_node_id] =
|
||||
node_stack_.PopExpressionWithParseNode();
|
||||
@@ -601,9 +624,7 @@ auto Context::ParamOrArgSave(bool for_args) -> void {
|
||||
}
|
||||
|
||||
// Save the param or arg ID.
|
||||
auto& params_or_args =
|
||||
semantics_ir_->GetNodeBlock(params_or_args_stack_.PeekForAdd());
|
||||
params_or_args.push_back(entry_node_id);
|
||||
AddNodeIdToBlock(params_or_args_stack_.PeekForAdd(), entry_node_id);
|
||||
}
|
||||
|
||||
auto Context::CanonicalizeTypeImpl(
|
||||
@@ -641,9 +662,9 @@ auto Context::CanonicalizeTypeImpl(
|
||||
}
|
||||
|
||||
// Compute a fingerprint for a tuple type, for use as a key in a folding set.
|
||||
static auto ProfileTupleType(const llvm::SmallVector<SemIR::TypeId>& type_ids,
|
||||
static auto ProfileTupleType(llvm::ArrayRef<SemIR::TypeId> type_ids,
|
||||
llvm::FoldingSetNodeID& canonical_id) -> void {
|
||||
for (const auto& type_id : type_ids) {
|
||||
for (auto type_id : type_ids) {
|
||||
canonical_id.AddInteger(type_id.index);
|
||||
}
|
||||
}
|
||||
@@ -739,18 +760,16 @@ auto Context::CanonicalizeStructType(Parse::Node parse_node,
|
||||
}
|
||||
|
||||
auto Context::CanonicalizeTupleType(Parse::Node parse_node,
|
||||
llvm::SmallVector<SemIR::TypeId>&& type_ids)
|
||||
llvm::ArrayRef<SemIR::TypeId> type_ids)
|
||||
-> SemIR::TypeId {
|
||||
// Defer allocating a SemIR::TypeBlockId until we know this is a new type.
|
||||
auto profile_tuple = [&](llvm::FoldingSetNodeID& canonical_id) {
|
||||
ProfileTupleType(type_ids, canonical_id);
|
||||
};
|
||||
auto make_tuple_node = [&] {
|
||||
auto type_block_id = semantics_ir_->AddTypeBlock();
|
||||
auto& type_block = semantics_ir_->GetTypeBlock(type_block_id);
|
||||
type_block = std::move(type_ids);
|
||||
return AddNode(SemIR::Node::TupleType::Make(
|
||||
parse_node, SemIR::TypeId::TypeType, type_block_id));
|
||||
return AddNode(
|
||||
SemIR::Node::TupleType::Make(parse_node, SemIR::TypeId::TypeType,
|
||||
semantics_ir_->AddTypeBlock(type_ids)));
|
||||
};
|
||||
return CanonicalizeTypeImpl(SemIR::NodeKind::TupleType, profile_tuple,
|
||||
make_tuple_node);
|
||||
|
||||
Reference in New Issue
Block a user