mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
Add a new `specific_function` instruction that represents a generic function plus its deduced argument list as a callee in a function call. The new instruction can only appear as the immediate operand of a call instruction, so we give it a builtin placeholder type. At the end of each file, require definitions for all specific functions used in that file. Resolve the generic with the argument list to produce those specific function definitions as needed, and diagnose if the generic doesn't have a definition available. A few tests are updated in cases where they declared and used generic functions but didn't previously provide a function definition.
87 lines
2.8 KiB
C++
87 lines
2.8 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include "toolchain/sem_ir/function.h"
|
|
|
|
#include "toolchain/sem_ir/file.h"
|
|
#include "toolchain/sem_ir/generic.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
|
namespace Carbon::SemIR {
|
|
|
|
auto GetCalleeFunction(const File& sem_ir, InstId callee_id) -> CalleeFunction {
|
|
CalleeFunction result = {.function_id = FunctionId::Invalid,
|
|
.enclosing_specific_id = SpecificId::Invalid,
|
|
.resolved_specific_id = SpecificId::Invalid,
|
|
.self_id = InstId::Invalid,
|
|
.is_error = false};
|
|
|
|
if (auto specific_function =
|
|
sem_ir.insts().TryGetAs<SpecificFunction>(callee_id)) {
|
|
result.resolved_specific_id = specific_function->specific_id;
|
|
callee_id = specific_function->callee_id;
|
|
}
|
|
|
|
if (auto bound_method = sem_ir.insts().TryGetAs<BoundMethod>(callee_id)) {
|
|
result.self_id = bound_method->object_id;
|
|
callee_id = bound_method->function_id;
|
|
}
|
|
|
|
// Identify the function we're calling.
|
|
auto val_id = sem_ir.constant_values().GetConstantInstId(callee_id);
|
|
if (!val_id.is_valid()) {
|
|
return result;
|
|
}
|
|
auto val_inst = sem_ir.insts().Get(val_id);
|
|
auto struct_val = val_inst.TryAs<StructValue>();
|
|
if (!struct_val) {
|
|
result.is_error = val_inst.type_id() == SemIR::TypeId::Error;
|
|
return result;
|
|
}
|
|
auto fn_type = sem_ir.types().TryGetAs<FunctionType>(struct_val->type_id);
|
|
if (!fn_type) {
|
|
return result;
|
|
}
|
|
|
|
result.function_id = fn_type->function_id;
|
|
result.enclosing_specific_id = fn_type->specific_id;
|
|
return result;
|
|
}
|
|
|
|
auto Function::GetParamFromParamRefId(const File& sem_ir, InstId param_ref_id)
|
|
-> ParamInfo {
|
|
auto ref = sem_ir.insts().Get(param_ref_id);
|
|
|
|
if (auto addr_pattern = ref.TryAs<AddrPattern>()) {
|
|
param_ref_id = addr_pattern->inner_id;
|
|
ref = sem_ir.insts().Get(param_ref_id);
|
|
}
|
|
|
|
auto bind_name = ref.TryAs<AnyBindName>();
|
|
if (bind_name) {
|
|
param_ref_id = bind_name->value_id;
|
|
ref = sem_ir.insts().Get(param_ref_id);
|
|
}
|
|
return {param_ref_id, ref.As<Param>(), bind_name};
|
|
}
|
|
|
|
auto Function::ParamInfo::GetNameId(const File& sem_ir) -> NameId {
|
|
if (bind_name) {
|
|
return sem_ir.entity_names().Get(bind_name->entity_name_id).name_id;
|
|
} else {
|
|
return NameId::Invalid;
|
|
}
|
|
}
|
|
|
|
auto Function::GetDeclaredReturnType(const File& file,
|
|
SpecificId specific_id) const -> TypeId {
|
|
if (!return_storage_id.is_valid()) {
|
|
return TypeId::Invalid;
|
|
}
|
|
return GetTypeInSpecific(file, specific_id,
|
|
file.insts().Get(return_storage_id).type_id());
|
|
}
|
|
|
|
} // namespace Carbon::SemIR
|