Skip to content

Commit e20e8bf

Browse files
geoffromerjonmeow
andauthored
Consolidate caller match in one function call (#4446)
Co-authored-by: Jon Ross-Perkins <[email protected]>
1 parent 89eed42 commit e20e8bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+460
-496
lines changed

toolchain/check/call.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,10 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
210210
}
211211

212212
// Convert the arguments to match the parameters.
213-
auto converted_args_id = ConvertCallArgs(
214-
context, loc_id, callee_function.self_id, arg_ids, return_slot_arg_id,
215-
CalleeParamsInfo(callable), *callee_specific_id);
213+
auto converted_args_id =
214+
ConvertCallArgs(context, loc_id, callee_function.self_id, arg_ids,
215+
return_slot_arg_id, CalleeParamsInfo(callable),
216+
callable.return_slot_pattern_id, *callee_specific_id);
216217
auto call_inst_id =
217218
context.AddInst<SemIR::Call>(loc_id, {.type_id = return_info.type_id,
218219
.callee_id = callee_id,

toolchain/check/convert.cpp

Lines changed: 24 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,46 +1136,12 @@ auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
11361136
{.kind = ConversionTarget::ExplicitAs, .type_id = type_id});
11371137
}
11381138

1139-
CARBON_DIAGNOSTIC(InCallToFunction, Note, "calling function declared here");
1140-
1141-
// Convert the object argument in a method call to match the `self` parameter.
1142-
static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id,
1143-
SemIRLoc callee_loc,
1144-
SemIR::SpecificId callee_specific_id,
1145-
SemIR::InstId self_param_id, SemIR::InstId self_id)
1146-
-> SemIR::InstId {
1147-
if (!self_id.is_valid()) {
1148-
CARBON_DIAGNOSTIC(MissingObjectInMethodCall, Error,
1149-
"missing object argument in method call");
1150-
context.emitter()
1151-
.Build(call_loc_id, MissingObjectInMethodCall)
1152-
.Note(callee_loc, InCallToFunction)
1153-
.Emit();
1154-
return SemIR::InstId::BuiltinError;
1155-
}
1156-
1157-
bool addr_pattern = context.insts().Is<SemIR::AddrPattern>(self_param_id);
1158-
DiagnosticAnnotationScope annotate_diagnostics(
1159-
&context.emitter(), [&](auto& builder) {
1160-
CARBON_DIAGNOSTIC(InCallToFunctionSelf, Note,
1161-
"initializing `{0:addr self|self}` parameter of "
1162-
"method declared here",
1163-
BoolAsSelect);
1164-
builder.Note(self_param_id, InCallToFunctionSelf, addr_pattern);
1165-
});
1166-
1167-
return CallerPatternMatch(context, callee_specific_id, self_param_id,
1168-
self_id);
1169-
}
1170-
11711139
// TODO: consider moving this to pattern_match.h
1172-
auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
1173-
SemIR::InstId self_id,
1174-
llvm::ArrayRef<SemIR::InstId> arg_refs,
1175-
SemIR::InstId return_slot_arg_id,
1176-
const CalleeParamsInfo& callee,
1177-
SemIR::SpecificId callee_specific_id)
1178-
-> SemIR::InstBlockId {
1140+
auto ConvertCallArgs(
1141+
Context& context, SemIR::LocId call_loc_id, SemIR::InstId self_id,
1142+
llvm::ArrayRef<SemIR::InstId> arg_refs, SemIR::InstId return_slot_arg_id,
1143+
const CalleeParamsInfo& callee, SemIR::InstId return_slot_pattern_id,
1144+
SemIR::SpecificId callee_specific_id) -> SemIR::InstBlockId {
11791145
auto implicit_param_patterns =
11801146
context.inst_blocks().GetOrEmpty(callee.implicit_param_patterns_id);
11811147
auto param_patterns =
@@ -1184,68 +1150,31 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
11841150
// The caller should have ensured this callee has the right arity.
11851151
CARBON_CHECK(arg_refs.size() == param_patterns.size());
11861152

1187-
// Start building a block to hold the converted arguments.
1188-
llvm::SmallVector<SemIR::InstId> args;
1189-
args.reserve(implicit_param_patterns.size() + param_patterns.size() +
1190-
return_slot_arg_id.is_valid());
1191-
1192-
// Check implicit parameters.
1153+
// Find self parameter pattern.
1154+
// TODO: Do this during initial traversal of implicit params.
1155+
auto self_param_id = SemIR::InstId::Invalid;
11931156
for (auto implicit_param_id : implicit_param_patterns) {
1194-
if (implicit_param_id == SemIR::InstId::BuiltinError) {
1195-
return SemIR::InstBlockId::Invalid;
1157+
if (SemIR::Function::GetNameFromPatternId(
1158+
context.sem_ir(), implicit_param_id) == SemIR::NameId::SelfValue) {
1159+
CARBON_CHECK(!self_param_id.is_valid());
1160+
self_param_id = implicit_param_id;
11961161
}
1197-
auto param_pattern_info = SemIR::Function::GetParamPatternInfoFromPatternId(
1198-
context.sem_ir(), implicit_param_id);
1199-
if (param_pattern_info.GetNameId(context.sem_ir()) ==
1200-
SemIR::NameId::SelfValue) {
1201-
auto converted_self_id =
1202-
ConvertSelf(context, call_loc_id, callee.callee_loc,
1203-
callee_specific_id, implicit_param_id, self_id);
1204-
if (converted_self_id == SemIR::InstId::BuiltinError) {
1205-
return SemIR::InstBlockId::Invalid;
1206-
}
1207-
args.push_back(converted_self_id);
1208-
} else {
1209-
CARBON_CHECK(!param_pattern_info.inst.runtime_index.is_valid(),
1210-
"Unexpected implicit parameter passed at runtime");
1211-
}
1212-
}
1213-
1214-
// Check type conversions per-element.
1215-
for (auto [i, arg_id, param_pattern_id] :
1216-
llvm::enumerate(arg_refs, param_patterns)) {
1217-
auto runtime_index = SemIR::Function::GetParamPatternInfoFromPatternId(
1218-
context.sem_ir(), param_pattern_id)
1219-
.inst.runtime_index;
1220-
if (!runtime_index.is_valid()) {
1221-
// Not a runtime parameter: we don't pass an argument.
1222-
continue;
1223-
}
1224-
1225-
DiagnosticAnnotationScope annotate_diagnostics(
1226-
&context.emitter(), [&](auto& builder) {
1227-
CARBON_DIAGNOSTIC(InCallToFunctionParam, Note,
1228-
"initializing function parameter");
1229-
builder.Note(param_pattern_id, InCallToFunctionParam);
1230-
});
1231-
1232-
auto converted_arg_id = CallerPatternMatch(context, callee_specific_id,
1233-
param_pattern_id, arg_id);
1234-
if (converted_arg_id == SemIR::InstId::BuiltinError) {
1235-
return SemIR::InstBlockId::Invalid;
1236-
}
1237-
1238-
CARBON_CHECK(static_cast<int32_t>(args.size()) == runtime_index.index,
1239-
"Parameters not numbered in order.");
1240-
args.push_back(converted_arg_id);
12411162
}
12421163

1243-
// Track the return storage, if present.
1244-
if (return_slot_arg_id.is_valid()) {
1245-
args.push_back(return_slot_arg_id);
1164+
if (self_param_id.is_valid() && !self_id.is_valid()) {
1165+
CARBON_DIAGNOSTIC(MissingObjectInMethodCall, Error,
1166+
"missing object argument in method call");
1167+
CARBON_DIAGNOSTIC(InCallToFunction, Note, "calling function declared here");
1168+
context.emitter()
1169+
.Build(call_loc_id, MissingObjectInMethodCall)
1170+
.Note(callee.callee_loc, InCallToFunction)
1171+
.Emit();
1172+
self_id = SemIR::InstId::BuiltinError;
12461173
}
12471174

1248-
return context.inst_blocks().AddOrEmpty(args);
1175+
return CallerPatternMatch(context, callee_specific_id, self_param_id,
1176+
callee.param_patterns_id, return_slot_pattern_id,
1177+
self_id, arg_refs, return_slot_arg_id);
12491178
}
12501179

12511180
auto ExprAsType(Context& context, SemIR::LocId loc_id, SemIR::InstId value_id)

toolchain/check/convert.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,11 @@ auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
8989
SemIR::InstId value_id, SemIR::TypeId type_id)
9090
-> SemIR::InstId;
9191

92-
// Information about the parameters of a callee. This information is extracted
93-
// from the EntityWithParamsBase before calling ConvertCallArgs, because
94-
// conversion can trigger importing of more entities, which can invalidate the
95-
// reference to the callee.
92+
// Information about the syntactic parameters of a callee (excluding the return
93+
// slot, for example). This information is extracted from the
94+
// EntityWithParamsBase before calling ConvertCallArgs, because conversion can
95+
// trigger importing of more entities, which can invalidate the reference to the
96+
// callee.
9697
struct CalleeParamsInfo {
9798
explicit CalleeParamsInfo(const SemIR::EntityWithParamsBase& callee)
9899
: callee_loc(callee.latest_decl_id()),
@@ -114,13 +115,11 @@ struct CalleeParamsInfo {
114115
// Implicitly converts a set of arguments to match the parameter types in a
115116
// function call. Returns a block containing the converted implicit and explicit
116117
// argument values for runtime parameters.
117-
auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
118-
SemIR::InstId self_id,
119-
llvm::ArrayRef<SemIR::InstId> arg_refs,
120-
SemIR::InstId return_slot_arg_id,
121-
const CalleeParamsInfo& callee,
122-
SemIR::SpecificId callee_specific_id)
123-
-> SemIR::InstBlockId;
118+
auto ConvertCallArgs(
119+
Context& context, SemIR::LocId call_loc_id, SemIR::InstId self_id,
120+
llvm::ArrayRef<SemIR::InstId> arg_refs, SemIR::InstId return_slot_arg_id,
121+
const CalleeParamsInfo& callee, SemIR::InstId return_slot_pattern_id,
122+
SemIR::SpecificId callee_specific_id) -> SemIR::InstBlockId;
124123

125124
// A type that has been converted for use as a type expression.
126125
struct TypeExpr {

toolchain/check/global_init.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ auto GlobalInit::Finalize() -> void {
4949
.extern_library_id = SemIR::LibraryNameId::Invalid,
5050
.non_owning_decl_id = SemIR::InstId::Invalid,
5151
.first_owning_decl_id = SemIR::InstId::Invalid},
52-
{.return_slot_id = SemIR::InstId::Invalid,
52+
{.return_slot_pattern_id = SemIR::InstId::Invalid,
53+
.return_slot_id = SemIR::InstId::Invalid,
5354
.body_block_ids = {SemIR::InstBlockId::GlobalInit}}}));
5455
}
5556

toolchain/check/handle_function.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ static auto BuildFunctionDecl(Context& context,
236236
auto function_info =
237237
SemIR::Function{{name_context.MakeEntityWithParamsBase(
238238
name, decl_id, is_extern, introducer.extern_library)},
239-
{.return_slot_id = name.return_slot_id,
239+
{.return_slot_pattern_id = name.return_slot_pattern_id,
240+
.return_slot_id = name.return_slot_id,
240241
.virtual_modifier = virtual_modifier}};
241242
if (is_definition) {
242243
function_info.definition_id = decl_id;

toolchain/check/import_ref.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,34 @@ class ImportRefResolver {
888888
return context_.inst_blocks().Add(new_patterns);
889889
}
890890

891+
// Returns a version of import_return_slot_pattern_id localized to the current
892+
// IR.
893+
auto GetLocalReturnSlotPatternId(SemIR::InstId import_return_slot_pattern_id)
894+
-> SemIR::InstId {
895+
if (!import_return_slot_pattern_id.is_valid()) {
896+
return SemIR::InstId::Invalid;
897+
}
898+
899+
auto param_pattern = import_ir_.insts().GetAs<SemIR::OutParamPattern>(
900+
import_return_slot_pattern_id);
901+
auto return_slot_pattern =
902+
import_ir_.insts().GetAs<SemIR::ReturnSlotPattern>(
903+
param_pattern.subpattern_id);
904+
auto type_id = context_.GetTypeIdForTypeConstant(
905+
GetLocalConstantIdChecked(return_slot_pattern.type_id));
906+
907+
auto new_return_slot_pattern_id = context_.AddInstInNoBlock(
908+
context_.MakeImportedLocAndInst<SemIR::ReturnSlotPattern>(
909+
AddImportIRInst(param_pattern.subpattern_id),
910+
{.type_id = type_id, .type_inst_id = SemIR::InstId::Invalid}));
911+
return context_.AddInstInNoBlock(
912+
context_.MakeImportedLocAndInst<SemIR::OutParamPattern>(
913+
AddImportIRInst(import_return_slot_pattern_id),
914+
{.type_id = type_id,
915+
.subpattern_id = new_return_slot_pattern_id,
916+
.runtime_index = param_pattern.runtime_index}));
917+
}
918+
891919
// Translates a NameId from the import IR to a local NameId.
892920
auto GetLocalNameId(SemIR::NameId import_name_id) -> SemIR::NameId {
893921
if (auto ident_id = import_name_id.AsIdentifierId(); ident_id.is_valid()) {
@@ -1600,7 +1628,8 @@ class ImportRefResolver {
16001628
// Start with an incomplete function.
16011629
function_decl.function_id = context_.functions().Add(
16021630
{GetIncompleteLocalEntityBase(function_decl_id, import_function),
1603-
{.return_slot_id = SemIR::InstId::Invalid,
1631+
{.return_slot_pattern_id = SemIR::InstId::Invalid,
1632+
.return_slot_id = SemIR::InstId::Invalid,
16041633
.builtin_function_kind = import_function.builtin_function_kind}});
16051634

16061635
function_decl.type_id =
@@ -1671,6 +1700,8 @@ class ImportRefResolver {
16711700
GetLocalParamRefsId(import_function.param_refs_id);
16721701
new_function.param_patterns_id =
16731702
GetLocalParamPatternsId(import_function.param_patterns_id);
1703+
new_function.return_slot_pattern_id =
1704+
GetLocalReturnSlotPatternId(import_function.return_slot_pattern_id);
16741705
SetGenericData(import_function.generic_id, new_function.generic_id,
16751706
generic_data);
16761707

0 commit comments

Comments
 (0)