mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 19:11:11 +01:00
Make Destroy.Op functions able to have a body (#6729)
This is iterating on how `Destroy.Op` generates, to start adding body capabilities. This changes the way the signature is created, and adds a `CoreWitness` function kind so that mangling can prevent name collisions. The result is that what _was_ `DestroyOp` is now `Core.Destroy.Op` or, as can be seen in toolchain/lower/testdata/interop/cpp/nullptr.carbon, `_COp.<hash>:core.Destroy.Core` where `:core` is indicating that it's a core witness (taking a note from `:thunk`). Assisted-by: Google Antigravity with Gemini 3 Flash
This commit is contained in:
@@ -89,28 +89,44 @@ auto IsValidBuiltinDeclaration(Context& context,
|
||||
return_type_id);
|
||||
}
|
||||
|
||||
auto MakeBuiltinFunction(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::BuiltinFunctionKind builtin_kind,
|
||||
SemIR::NameScopeId name_scope_id,
|
||||
SemIR::NameId name_id,
|
||||
BuiltinFunctionSignature signature) -> SemIR::InstId {
|
||||
namespace {
|
||||
// Function signature fields for `MakeFunctionSignature`.
|
||||
struct FunctionSignatureInsts {
|
||||
SemIR::InstBlockId decl_block_id = SemIR::InstBlockId::None;
|
||||
SemIR::InstBlockId pattern_block_id = SemIR::InstBlockId::None;
|
||||
SemIR::InstBlockId implicit_param_patterns_id = SemIR::InstBlockId::None;
|
||||
SemIR::InstBlockId param_patterns_id = SemIR::InstBlockId::None;
|
||||
SemIR::InstBlockId call_param_patterns_id = SemIR::InstBlockId::None;
|
||||
SemIR::InstBlockId call_params_id = SemIR::InstBlockId::None;
|
||||
SemIR::TypeInstId return_type_inst_id = SemIR::TypeInstId::None;
|
||||
SemIR::InstId return_form_inst_id = SemIR::InstId::None;
|
||||
SemIR::InstBlockId return_patterns_id = SemIR::InstBlockId::None;
|
||||
SemIR::InstId self_param_id = SemIR::InstId::None;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Handles construction of the signature's parameter and return types.
|
||||
static auto MakeFunctionSignature(Context& context, SemIR::LocId loc_id,
|
||||
const FunctionDeclArgs& args)
|
||||
-> FunctionSignatureInsts {
|
||||
FunctionSignatureInsts insts;
|
||||
|
||||
StartFunctionSignature(context);
|
||||
|
||||
// Build and add a `[ref self: Self]` parameter if needed.
|
||||
auto implicit_param_patterns_id = SemIR::InstBlockId::None;
|
||||
auto self_param_id = SemIR::InstId::None;
|
||||
if (signature.self_type_id.has_value()) {
|
||||
if (args.self_type_id.has_value()) {
|
||||
context.full_pattern_stack().PushFullPattern(
|
||||
FullPatternStack::Kind::ImplicitParamList);
|
||||
|
||||
BeginSubpattern(context);
|
||||
auto self_type_region_id = EndSubpatternAsExpr(
|
||||
context, context.types().GetTypeInstId(signature.self_type_id));
|
||||
context, context.types().GetTypeInstId(args.self_type_id));
|
||||
|
||||
self_param_id = AddParamPattern(context, loc_id, SemIR::NameId::SelfValue,
|
||||
self_type_region_id, signature.self_type_id,
|
||||
signature.self_is_ref);
|
||||
implicit_param_patterns_id = context.inst_blocks().Add({self_param_id});
|
||||
insts.self_param_id = AddParamPattern(
|
||||
context, loc_id, SemIR::NameId::SelfValue, self_type_region_id,
|
||||
args.self_type_id, args.self_is_ref);
|
||||
insts.implicit_param_patterns_id =
|
||||
context.inst_blocks().Add({insts.self_param_id});
|
||||
|
||||
context.full_pattern_stack().EndImplicitParamList();
|
||||
} else {
|
||||
@@ -120,10 +136,11 @@ auto MakeBuiltinFunction(Context& context, SemIR::LocId loc_id,
|
||||
|
||||
// Build and add any explicit parameters. We always use value parameters for
|
||||
// now.
|
||||
auto param_patterns_id = SemIR::InstBlockId::Empty;
|
||||
if (!signature.param_type_ids.empty()) {
|
||||
if (args.param_type_ids.empty()) {
|
||||
insts.param_patterns_id = SemIR::InstBlockId::Empty;
|
||||
} else {
|
||||
context.inst_block_stack().Push();
|
||||
for (auto param_type_id : signature.param_type_ids) {
|
||||
for (auto param_type_id : args.param_type_ids) {
|
||||
BeginSubpattern(context);
|
||||
auto param_type_region_id = EndSubpatternAsExpr(
|
||||
context, context.types().GetTypeInstId(param_type_id));
|
||||
@@ -132,45 +149,52 @@ auto MakeBuiltinFunction(Context& context, SemIR::LocId loc_id,
|
||||
context, loc_id, SemIR::NameId::Underscore, param_type_region_id,
|
||||
param_type_id, /*is_ref=*/false));
|
||||
}
|
||||
param_patterns_id = context.inst_block_stack().Pop();
|
||||
insts.param_patterns_id = context.inst_block_stack().Pop();
|
||||
}
|
||||
|
||||
// Build and add the return type. We always use an initializing form for now.
|
||||
auto return_patterns_id = SemIR::InstBlockId::None;
|
||||
Context::FormExpr return_form = {
|
||||
.form_inst_id = SemIR::InstId::None,
|
||||
.type_component_inst_id = SemIR::TypeInstId::None,
|
||||
.type_component_id = SemIR::TypeId::None};
|
||||
if (signature.return_type_id.has_value()) {
|
||||
return_form = ReturnExprAsForm(
|
||||
context, loc_id,
|
||||
context.types().GetTypeInstId(signature.return_type_id));
|
||||
return_patterns_id = AddReturnPatterns(context, loc_id, return_form);
|
||||
if (args.return_type_id.has_value()) {
|
||||
auto return_form = ReturnExprAsForm(
|
||||
context, loc_id, context.types().GetTypeInstId(args.return_type_id));
|
||||
insts.return_type_inst_id = return_form.type_component_inst_id;
|
||||
insts.return_form_inst_id = return_form.form_inst_id;
|
||||
insts.return_patterns_id = AddReturnPatterns(context, loc_id, return_form);
|
||||
}
|
||||
|
||||
auto [call_param_patterns_id, call_params_id] =
|
||||
CalleePatternMatch(context, implicit_param_patterns_id, param_patterns_id,
|
||||
return_patterns_id);
|
||||
CalleePatternMatch(context, insts.implicit_param_patterns_id,
|
||||
insts.param_patterns_id, insts.return_patterns_id);
|
||||
insts.call_param_patterns_id = call_param_patterns_id;
|
||||
insts.call_params_id = call_params_id;
|
||||
|
||||
context.full_pattern_stack().PopFullPattern();
|
||||
auto [pattern_block_id, decl_block_id] =
|
||||
FinishFunctionSignature(context, /*check_unused=*/false);
|
||||
insts.pattern_block_id = pattern_block_id;
|
||||
insts.decl_block_id = decl_block_id;
|
||||
|
||||
return insts;
|
||||
}
|
||||
|
||||
auto MakeGeneratedFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
const FunctionDeclArgs& args)
|
||||
-> std::pair<SemIR::InstId, SemIR::FunctionId> {
|
||||
auto insts = MakeFunctionSignature(context, loc_id, args);
|
||||
|
||||
// Add the function declaration.
|
||||
// TODO: This should probably handle generics.
|
||||
auto [decl_id, function_id] = MakeFunctionDecl(
|
||||
context, loc_id, decl_block_id, /*build_generic=*/false,
|
||||
context, loc_id, insts.decl_block_id, /*build_generic=*/false,
|
||||
/*is_definition=*/true,
|
||||
SemIR::Function{
|
||||
{
|
||||
.name_id = name_id,
|
||||
.parent_scope_id = name_scope_id,
|
||||
.name_id = args.name_id,
|
||||
.parent_scope_id = args.parent_scope_id,
|
||||
.generic_id = SemIR::GenericId::None,
|
||||
.first_param_node_id = Parse::NodeId::None,
|
||||
.last_param_node_id = Parse::NodeId::None,
|
||||
.pattern_block_id = pattern_block_id,
|
||||
.implicit_param_patterns_id = implicit_param_patterns_id,
|
||||
.param_patterns_id = param_patterns_id,
|
||||
.pattern_block_id = insts.pattern_block_id,
|
||||
.implicit_param_patterns_id = insts.implicit_param_patterns_id,
|
||||
.param_patterns_id = insts.param_patterns_id,
|
||||
.is_extern = false,
|
||||
.extern_library_id = SemIR::LibraryNameId::None,
|
||||
.non_owning_decl_id = SemIR::InstId::None,
|
||||
@@ -178,22 +202,16 @@ auto MakeBuiltinFunction(Context& context, SemIR::LocId loc_id,
|
||||
.first_owning_decl_id = SemIR::InstId::None,
|
||||
},
|
||||
{
|
||||
.call_param_patterns_id = call_param_patterns_id,
|
||||
.call_params_id = call_params_id,
|
||||
.return_type_inst_id = return_form.type_component_inst_id,
|
||||
.return_form_inst_id = return_form.form_inst_id,
|
||||
.return_patterns_id = return_patterns_id,
|
||||
.self_param_id = self_param_id,
|
||||
.call_param_patterns_id = insts.call_param_patterns_id,
|
||||
.call_params_id = insts.call_params_id,
|
||||
.return_type_inst_id = insts.return_type_inst_id,
|
||||
.return_form_inst_id = insts.return_form_inst_id,
|
||||
.return_patterns_id = insts.return_patterns_id,
|
||||
.self_param_id = insts.self_param_id,
|
||||
}});
|
||||
// TODO: Find a better way to handle this. Ideally we should stop using this
|
||||
// function entirely and declare builtins in the prelude.
|
||||
context.generated().push_back(decl_id);
|
||||
|
||||
auto& function = context.functions().Get(function_id);
|
||||
CARBON_CHECK(IsValidBuiltinDeclaration(context, function, builtin_kind));
|
||||
function.SetBuiltinFunction(builtin_kind);
|
||||
|
||||
return decl_id;
|
||||
return {decl_id, function_id};
|
||||
}
|
||||
|
||||
auto CheckFunctionReturnTypeMatches(Context& context,
|
||||
|
||||
Reference in New Issue
Block a user