Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate caller match in one function call #4446

Merged
merged 9 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 19 additions & 88 deletions toolchain/check/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1136,38 +1136,6 @@ auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
{.kind = ConversionTarget::ExplicitAs, .type_id = type_id});
}

CARBON_DIAGNOSTIC(InCallToFunction, Note, "calling function declared here");

// Convert the object argument in a method call to match the `self` parameter.
static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id,
SemIRLoc callee_loc,
SemIR::SpecificId callee_specific_id,
SemIR::InstId self_param_id, SemIR::InstId self_id)
-> SemIR::InstId {
if (!self_id.is_valid()) {
CARBON_DIAGNOSTIC(MissingObjectInMethodCall, Error,
"missing object argument in method call");
context.emitter()
.Build(call_loc_id, MissingObjectInMethodCall)
.Note(callee_loc, InCallToFunction)
.Emit();
return SemIR::InstId::BuiltinError;
}

bool addr_pattern = context.insts().Is<SemIR::AddrPattern>(self_param_id);
DiagnosticAnnotationScope annotate_diagnostics(
&context.emitter(), [&](auto& builder) {
CARBON_DIAGNOSTIC(InCallToFunctionSelf, Note,
"initializing `{0:addr self|self}` parameter of "
"method declared here",
BoolAsSelect);
builder.Note(self_param_id, InCallToFunctionSelf, addr_pattern);
});

return CallerPatternMatch(context, callee_specific_id, self_param_id,
self_id);
}

// TODO: consider moving this to pattern_match.h
auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
SemIR::InstId self_id,
Expand All @@ -1184,68 +1152,31 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
// The caller should have ensured this callee has the right arity.
CARBON_CHECK(arg_refs.size() == param_patterns.size());

// Start building a block to hold the converted arguments.
llvm::SmallVector<SemIR::InstId> args;
args.reserve(implicit_param_patterns.size() + param_patterns.size() +
return_slot_arg_id.is_valid());

// Check implicit parameters.
// Find self parameter pattern.
// TODO: Do this during initial traversal of implicit params.
auto self_param_id = SemIR::InstId::Invalid;
for (auto implicit_param_id : implicit_param_patterns) {
if (implicit_param_id == SemIR::InstId::BuiltinError) {
return SemIR::InstBlockId::Invalid;
}
auto param_pattern_info = SemIR::Function::GetParamPatternInfoFromPatternId(
context.sem_ir(), implicit_param_id);
if (param_pattern_info.GetNameId(context.sem_ir()) ==
SemIR::NameId::SelfValue) {
auto converted_self_id =
ConvertSelf(context, call_loc_id, callee.callee_loc,
callee_specific_id, implicit_param_id, self_id);
if (converted_self_id == SemIR::InstId::BuiltinError) {
return SemIR::InstBlockId::Invalid;
}
args.push_back(converted_self_id);
} else {
CARBON_CHECK(!param_pattern_info.inst.runtime_index.is_valid(),
"Unexpected implicit parameter passed at runtime");
if (SemIR::Function::GetNameFromPatternId(
context.sem_ir(), implicit_param_id) == SemIR::NameId::SelfValue) {
CARBON_CHECK(!self_param_id.is_valid());
self_param_id = implicit_param_id;
}
}

// Check type conversions per-element.
for (auto [i, arg_id, param_pattern_id] :
llvm::enumerate(arg_refs, param_patterns)) {
auto runtime_index = SemIR::Function::GetParamPatternInfoFromPatternId(
context.sem_ir(), param_pattern_id)
.inst.runtime_index;
if (!runtime_index.is_valid()) {
// Not a runtime parameter: we don't pass an argument.
continue;
}

DiagnosticAnnotationScope annotate_diagnostics(
&context.emitter(), [&](auto& builder) {
CARBON_DIAGNOSTIC(InCallToFunctionParam, Note,
"initializing function parameter");
builder.Note(param_pattern_id, InCallToFunctionParam);
});

auto converted_arg_id = CallerPatternMatch(context, callee_specific_id,
param_pattern_id, arg_id);
if (converted_arg_id == SemIR::InstId::BuiltinError) {
return SemIR::InstBlockId::Invalid;
}

CARBON_CHECK(static_cast<int32_t>(args.size()) == runtime_index.index,
"Parameters not numbered in order.");
args.push_back(converted_arg_id);
}

// Track the return storage, if present.
if (return_slot_arg_id.is_valid()) {
args.push_back(return_slot_arg_id);
if (self_param_id.is_valid() && !self_id.is_valid()) {
CARBON_DIAGNOSTIC(MissingObjectInMethodCall, Error,
"missing object argument in method call");
CARBON_DIAGNOSTIC(InCallToFunction, Note, "calling function declared here");
context.emitter()
.Build(call_loc_id, MissingObjectInMethodCall)
.Note(callee.callee_loc, InCallToFunction)
.Emit();
self_id = SemIR::InstId::BuiltinError;
}

return context.inst_blocks().AddOrEmpty(args);
return CallerPatternMatch(
context, callee_specific_id, self_param_id, callee.param_patterns_id,
callee.return_slot_pattern_id, self_id, arg_refs, return_slot_arg_id);
}

auto ExprAsType(Context& context, SemIR::LocId loc_id, SemIR::InstId value_id)
Expand Down
5 changes: 4 additions & 1 deletion toolchain/check/convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ struct CalleeParamsInfo {
implicit_param_refs_id(callee.implicit_param_refs_id),
implicit_param_patterns_id(callee.implicit_param_patterns_id),
param_refs_id(callee.param_refs_id),
param_patterns_id(callee.param_patterns_id) {}
param_patterns_id(callee.param_patterns_id),
return_slot_pattern_id(callee.return_slot_pattern_id) {}

// The location of the callee to use in diagnostics.
SemIRLoc callee_loc;
Expand All @@ -109,6 +110,8 @@ struct CalleeParamsInfo {
// The explicit parameters of the callee.
SemIR::InstBlockId param_refs_id;
SemIR::InstBlockId param_patterns_id;
// The return slot pattern of the callee.
SemIR::InstId return_slot_pattern_id;
};

// Implicitly converts a set of arguments to match the parameter types in a
Expand Down
1 change: 1 addition & 0 deletions toolchain/check/decl_name_stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class DeclNameStack {
.implicit_param_patterns_id = name.implicit_param_patterns_id,
.param_refs_id = name.params_id,
.param_patterns_id = name.param_patterns_id,
.return_slot_pattern_id = name.return_slot_pattern_id,
.is_extern = is_extern,
.extern_library_id = extern_library,
.non_owning_decl_id =
Expand Down
1 change: 1 addition & 0 deletions toolchain/check/global_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ auto GlobalInit::Finalize() -> void {
.implicit_param_patterns_id = SemIR::InstBlockId::Invalid,
.param_refs_id = SemIR::InstBlockId::Empty,
.param_patterns_id = SemIR::InstBlockId::Empty,
.return_slot_pattern_id = SemIR::InstId::Invalid,
.is_extern = false,
.extern_library_id = SemIR::LibraryNameId::Invalid,
.non_owning_decl_id = SemIR::InstId::Invalid,
Expand Down
31 changes: 31 additions & 0 deletions toolchain/check/import_ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,34 @@ class ImportRefResolver {
return context_.inst_blocks().Add(new_patterns);
}

// Returns a version of import_return_slot_pattern_id localized to the current
// IR.
auto GetLocalReturnSlotPatternId(SemIR::InstId import_return_slot_pattern_id)
-> SemIR::InstId {
if (!import_return_slot_pattern_id.is_valid()) {
return SemIR::InstId::Invalid;
}

auto param_pattern = import_ir_.insts().GetAs<SemIR::OutParamPattern>(
import_return_slot_pattern_id);
auto return_slot_pattern =
import_ir_.insts().GetAs<SemIR::ReturnSlotPattern>(
param_pattern.subpattern_id);
auto type_id = context_.GetTypeIdForTypeConstant(
GetLocalConstantIdChecked(return_slot_pattern.type_id));

auto new_return_slot_pattern_id = context_.AddInstInNoBlock(
context_.MakeImportedLocAndInst<SemIR::ReturnSlotPattern>(
AddImportIRInst(param_pattern.subpattern_id),
{.type_id = type_id, .type_inst_id = SemIR::InstId::Invalid}));
return context_.AddInstInNoBlock(
context_.MakeImportedLocAndInst<SemIR::OutParamPattern>(
AddImportIRInst(import_return_slot_pattern_id),
{.type_id = type_id,
.subpattern_id = new_return_slot_pattern_id,
.runtime_index = param_pattern.runtime_index}));
}

// Translates a NameId from the import IR to a local NameId.
auto GetLocalNameId(SemIR::NameId import_name_id) -> SemIR::NameId {
if (auto ident_id = import_name_id.AsIdentifierId(); ident_id.is_valid()) {
Expand Down Expand Up @@ -1014,6 +1042,7 @@ class ImportRefResolver {
.param_patterns_id = import_base.param_patterns_id.is_valid()
? SemIR::InstBlockId::Empty
: SemIR::InstBlockId::Invalid,
.return_slot_pattern_id = SemIR::InstId::Invalid,
.is_extern = import_base.is_extern,
.extern_library_id = extern_library_id,
.non_owning_decl_id = import_base.non_owning_decl_id.is_valid()
Expand Down Expand Up @@ -1671,6 +1700,8 @@ class ImportRefResolver {
GetLocalParamRefsId(import_function.param_refs_id);
new_function.param_patterns_id =
GetLocalParamPatternsId(import_function.param_patterns_id);
new_function.return_slot_pattern_id =
GetLocalReturnSlotPatternId(import_function.return_slot_pattern_id);
SetGenericData(import_function.generic_id, new_function.generic_id,
generic_data);

Expand Down
Loading
Loading