|
|
@@ -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);
|