1313#include " toolchain/base/kind_switch.h"
1414#include " toolchain/check/context.h"
1515#include " toolchain/check/operator.h"
16+ #include " toolchain/check/pattern_match.h"
1617#include " toolchain/sem_ir/copy_on_write_block.h"
1718#include " toolchain/sem_ir/file.h"
1819#include " toolchain/sem_ir/generic.h"
@@ -1138,9 +1139,8 @@ CARBON_DIAGNOSTIC(InCallToFunction, Note, "calling function declared here");
11381139static auto ConvertSelf (Context& context, SemIR::LocId call_loc_id,
11391140 SemIRLoc callee_loc,
11401141 SemIR::SpecificId callee_specific_id,
1141- std::optional<SemIR::AddrPattern> addr_pattern,
1142- SemIR::InstId self_param_id, SemIR::Param self_param,
1143- SemIR::InstId self_id) -> SemIR::InstId {
1142+ SemIR::InstId self_param_id, SemIR::InstId self_id)
1143+ -> SemIR::InstId {
11441144 if (!self_id.is_valid ()) {
11451145 CARBON_DIAGNOSTIC (MissingObjectInMethodCall, Error,
11461146 " missing object argument in method call" );
@@ -1151,6 +1151,7 @@ static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id,
11511151 return SemIR::InstId::BuiltinError;
11521152 }
11531153
1154+ bool addr_pattern = context.insts ().Is <SemIR::AddrPattern>(self_param_id);
11541155 DiagnosticAnnotationScope annotate_diagnostics (
11551156 &context.emitter (), [&](auto & builder) {
11561157 CARBON_DIAGNOSTIC (
@@ -1162,69 +1163,46 @@ static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id,
11621163 : llvm::StringLiteral (" self" ));
11631164 });
11641165
1165- // For `addr self`, take the address of the object argument.
1166- auto self_or_addr_id = self_id;
1167- if (addr_pattern) {
1168- self_or_addr_id = ConvertToValueOrRefExpr (context, self_or_addr_id);
1169- auto self = context.insts ().Get (self_or_addr_id);
1170- switch (SemIR::GetExprCategory (context.sem_ir (), self_id)) {
1171- case SemIR::ExprCategory::Error:
1172- case SemIR::ExprCategory::DurableRef:
1173- case SemIR::ExprCategory::EphemeralRef:
1174- break ;
1175- default :
1176- CARBON_DIAGNOSTIC (AddrSelfIsNonRef, Error,
1177- " `addr self` method cannot be invoked on a value" );
1178- context.emitter ().Emit (TokenOnly (call_loc_id), AddrSelfIsNonRef);
1179- return SemIR::InstId::BuiltinError;
1180- }
1181- auto loc_id = context.insts ().GetLocId (self_or_addr_id);
1182- self_or_addr_id = context.AddInst <SemIR::AddrOf>(
1183- loc_id, {.type_id = context.GetPointerType (self.type_id ()),
1184- .lvalue_id = self_or_addr_id});
1185- }
1186-
1187- return ConvertToValueOfType (
1188- context, call_loc_id, self_or_addr_id,
1189- SemIR::GetTypeInSpecific (context.sem_ir (), callee_specific_id,
1190- self_param.type_id ));
1166+ return CallerPatternMatch (context, callee_specific_id, self_param_id,
1167+ self_id);
11911168}
11921169
1170+ // TODO: consider moving this to pattern_match.h
11931171auto ConvertCallArgs (Context& context, SemIR::LocId call_loc_id,
11941172 SemIR::InstId self_id,
11951173 llvm::ArrayRef<SemIR::InstId> arg_refs,
11961174 SemIR::InstId return_storage_id,
11971175 const CalleeParamsInfo& callee,
11981176 SemIR::SpecificId callee_specific_id)
11991177 -> SemIR::InstBlockId {
1200- auto implicit_param_refs =
1201- context.inst_blocks ().GetOrEmpty (callee.implicit_param_refs_id );
1202- auto param_refs = context.inst_blocks ().GetOrEmpty (callee.param_refs_id );
1178+ auto implicit_param_patterns =
1179+ context.inst_blocks ().GetOrEmpty (callee.implicit_param_patterns_id );
1180+ auto param_patterns =
1181+ context.inst_blocks ().GetOrEmpty (callee.param_patterns_id );
12031182
12041183 // The caller should have ensured this callee has the right arity.
1205- CARBON_CHECK (arg_refs.size () == param_refs .size ());
1184+ CARBON_CHECK (arg_refs.size () == param_patterns .size ());
12061185
12071186 // Start building a block to hold the converted arguments.
12081187 llvm::SmallVector<SemIR::InstId> args;
1209- args.reserve (implicit_param_refs .size () + param_refs .size () +
1188+ args.reserve (implicit_param_patterns .size () + param_patterns .size () +
12101189 return_storage_id.is_valid ());
12111190
12121191 // Check implicit parameters.
1213- for (auto implicit_param_id : implicit_param_refs) {
1214- auto addr_pattern =
1215- context.insts ().TryGetAs <SemIR::AddrPattern>(implicit_param_id);
1216- auto param_info = SemIR::Function::GetParamFromParamRefId (
1192+ for (auto implicit_param_id : implicit_param_patterns) {
1193+ auto param_pattern_info = SemIR::Function::GetParamPatternInfoFromPatternId (
12171194 context.sem_ir (), implicit_param_id);
1218- if (param_info.GetNameId (context.sem_ir ()) == SemIR::NameId::SelfValue) {
1219- auto converted_self_id = ConvertSelf (
1220- context, call_loc_id, callee.callee_loc , callee_specific_id,
1221- addr_pattern, param_info.inst_id , param_info.inst , self_id);
1195+ if (param_pattern_info.GetNameId (context.sem_ir ()) ==
1196+ SemIR::NameId::SelfValue) {
1197+ auto converted_self_id =
1198+ ConvertSelf (context, call_loc_id, callee.callee_loc ,
1199+ callee_specific_id, implicit_param_id, self_id);
12221200 if (converted_self_id == SemIR::InstId::BuiltinError) {
12231201 return SemIR::InstBlockId::Invalid;
12241202 }
12251203 args.push_back (converted_self_id);
12261204 } else {
1227- CARBON_CHECK (!param_info .inst .runtime_index .is_valid (),
1205+ CARBON_CHECK (!param_pattern_info .inst .runtime_index .is_valid (),
12281206 " Unexpected implicit parameter passed at runtime" );
12291207 }
12301208 }
@@ -1240,31 +1218,25 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
12401218 });
12411219
12421220 // Check type conversions per-element.
1243- for (auto [i, arg_id, param_ref_id] : llvm::enumerate (arg_refs, param_refs)) {
1221+ for (auto [i, arg_id, param_pattern_id] :
1222+ llvm::enumerate (arg_refs, param_patterns)) {
12441223 diag_param_index = i;
12451224
1246- // TODO: In general we need to perform pattern matching here to find the
1247- // argument corresponding to each parameter.
1248- auto param_info =
1249- SemIR::Function::GetParamFromParamRefId (context.sem_ir (), param_ref_id);
1250- if (!param_info.inst .runtime_index .is_valid ()) {
1225+ auto runtime_index = SemIR::Function::GetParamPatternInfoFromPatternId (
1226+ context.sem_ir (), param_pattern_id)
1227+ .inst .runtime_index ;
1228+ if (!runtime_index.is_valid ()) {
12511229 // Not a runtime parameter: we don't pass an argument.
12521230 continue ;
12531231 }
12541232
1255- auto param_type_id = SemIR::GetTypeInSpecific (
1256- context.sem_ir (), callee_specific_id,
1257- context.insts ().Get (param_info.inst_id ).type_id ());
1258- // TODO: Convert to the proper expression category. For now, we assume
1259- // parameters are all `let` bindings.
1260- auto converted_arg_id =
1261- ConvertToValueOfType (context, call_loc_id, arg_id, param_type_id);
1233+ auto converted_arg_id = CallerPatternMatch (context, callee_specific_id,
1234+ param_pattern_id, arg_id);
12621235 if (converted_arg_id == SemIR::InstId::BuiltinError) {
12631236 return SemIR::InstBlockId::Invalid;
12641237 }
12651238
1266- CARBON_CHECK (static_cast <int32_t >(args.size ()) ==
1267- param_info.inst .runtime_index .index ,
1239+ CARBON_CHECK (static_cast <int32_t >(args.size ()) == runtime_index.index ,
12681240 " Parameters not numbered in order." );
12691241 args.push_back (converted_arg_id);
12701242 }
0 commit comments