diff --git a/toolchain/base/kind_switch.h b/toolchain/base/kind_switch.h index 396c0601ee12..49fa020863ff 100644 --- a/toolchain/base/kind_switch.h +++ b/toolchain/base/kind_switch.h @@ -20,6 +20,10 @@ // case CARBON_KIND(SomeInstType inst): { // return inst.typed_field; // } +// case CARBON_KIND_ANY(AnyKind, any_inst): { +// return any_inst.typed_field; +// } +// // case OtherType1::Kind: // case OtherType2::Kind: // return value; @@ -27,17 +31,62 @@ // return default_value; // } // -// For compatibility, this requires: +// When used on kind-like types, this requires: // // - The type passed to `CARBON_KIND_SWITCH` has `.kind()` to switch on, and // `.As` for `CARBON_KIND` to cast to. // - Each type passed to `CARBON_KIND` (`CaseT` above) provides // `CaseT::Kind`, which is passed to the `case` keyword. // `CaseT::Kind::RawEnumType` is the type returned by `.kind()`. +// - Each type passed to `CARBON_KIND_ANY` must have a macro of the form: +// ``` +// #define AnyKind_CARBON_KIND_ANY_EXPAND \ +// CARBON_KIND_ANY_EXPAND_BEGIN CARBON_KIND_ANY_EXPAND_CASE(Kind1) \ +// CARBON_KIND_ANY_EXPAND_SEP CARBON_KIND_ANY_EXPAND_CASE(Kind2) \ +// ... +// CARBON_KIND_ANY_EXPAND_SEP CARBON_KIND_ANY_EXPAND_CASE(KindN) +// ``` +// Note the prefix `,` is required. // -// Note, this is currently used primarily for Inst in toolchain. When more -// use-cases are added, it would be worth considering whether the API -// requirements should change. +// When used with `std::variant` (e.g., `CARBON_KIND_SWITCH(variant_value)`), +// members of the variant are passed to `CARBON_KIND`, instead of types that +// have a `::Kind` member. + +// Produces a switch statement on value.kind(). +#define CARBON_KIND_SWITCH(value) \ + switch ( \ + auto&& carbon_internal_kind_switch_value = value; \ + ::Carbon::Internal::Kind::SwitchOn(carbon_internal_kind_switch_value)) + +// Produces a case-compatible block of code that also instantiates a local typed +// variable. typed_variable_decl looks like `int i`; the `CARBON_KIND` value +// will be cast to the provided type. +// +// Because of the dangling else, braces should always be used with a `case +// CARBON_KIND`. Otherwise, only the first statement is going to see the +// variable. Even if that sometimes works, it can lead to confusing issues when +// statements are added, and `if`/`else` coding style already requires braces. +#define CARBON_KIND(typed_variable_decl) \ + CARBON_KIND_INTERNAL_CASE_VALUE(typed_variable_decl) \ + : CARBON_KIND_INTERNAL_DECLARE(typed_variable_decl) + +// Macros for clients to add support for `Type_CARBON_KIND_ANY_EXPAND` (see +// example above). +#define CARBON_KIND_ANY_EXPAND_CASE(X) CARBON_KIND_INTERNAL_CASE_VALUE(X) +#define CARBON_KIND_ANY_EXPAND_BEGIN , +#define CARBON_KIND_ANY_EXPAND_SEP : case + +// Produces a case-compatible block of code that also instantiates a local typed +// variable. Versus `CARBON_KIND(int i)`, note this requires a comma after the +// type, as in `CARBON_KIND_ANY(AnyKind, i)`. +#define CARBON_KIND_ANY(Type, variable_name) \ + CARBON_KIND_ANY_INTERNAL_WITH_SUFFIX(Type variable_name, \ + Type##_CARBON_KIND_ANY_EXPAND) + +// ----------------------------------------------------------------------------- +// Internal implementation details follow. +// ----------------------------------------------------------------------------- + namespace Carbon::Internal::Kind { template @@ -243,34 +292,52 @@ auto Cast(SwitchT&& kind_switch_value) -> decltype(auto) { #define CARBON_INTERNAL_KIND_LABEL(Line) \ CARBON_INTERNAL_KIND_MERGE(carbon_internal_kind_case_, Line) -} // namespace Carbon::Internal::Kind +// To extract the type from an argument, we wrap it in a lambda and will use +// `function_traits` to extract the type. This supports `typed_param` either +// being `Type name`, or just `Type`. +#define CARBON_KIND_INTERNAL_WRAP_TYPE(typed_param) \ + decltype([]([[maybe_unused]] typed_param) {}) -// Produces a switch statement on value.kind(). -#define CARBON_KIND_SWITCH(value) \ - switch ( \ - auto&& carbon_internal_kind_switch_value = value; \ - ::Carbon::Internal::Kind::SwitchOn(carbon_internal_kind_switch_value)) +// Produces the value for a `case` statement on the type of `typed_param`. +#define CARBON_KIND_INTERNAL_CASE_VALUE(typed_param) \ + ::Carbon::Internal::Kind::ForCase< \ + decltype(carbon_internal_kind_switch_value), \ + CARBON_KIND_INTERNAL_WRAP_TYPE(typed_param)>() -// Produces a case-compatible block of code that also instantiates a local typed -// variable. typed_variable_decl looks like `int i`, with a space. +// Produces a declaration using `typed_variable_decl`. // // This uses `if` to scope the variable, and provides a dangling `else` in order // to prevent accidental `else` use. The label allows `:` to follow the macro // name, making it look more like a typical `case`. +#define CARBON_KIND_INTERNAL_DECLARE(typed_variable_decl) \ + if (typed_variable_decl = \ + ::Carbon::Internal::Kind::Cast( \ + std::forward( \ + carbon_internal_kind_switch_value)); \ + false) { \ + } else [[maybe_unused]] \ + CARBON_INTERNAL_KIND_LABEL(__LINE__) + +// Helper for `CARBON_KIND_ANY` that expands the now-suffixed macro. +#define CARBON_KIND_ANY_INTERNAL_WITH_SUFFIX(typed_variable_decl, \ + Type_CARBON_KIND_ANY_EXPAND) \ + CARBON_KIND_ANY_INTERNAL_IMPL(typed_variable_decl, \ + Type_CARBON_KIND_ANY_EXPAND) + +// Helper for `CARBON_KIND_ANY` that forms the final case setup. The variadic +// arguments are the expansion of `Type_CARBON_KIND_ANY_EXPAND`, which may +// contain commas. // -// Because of the dangling else, braces should always be used with a `case -// CARBON_KIND`. Otherwise, only the first statement is going to see the -// variable. Even if that sometimes works, it can lead to confusing issues when -// statements are added, and `if`/`else` coding style already requires braces. -#define CARBON_KIND(typed_variable_decl) \ - ::Carbon::Internal::Kind::ForCase< \ - decltype(carbon_internal_kind_switch_value), \ - decltype([]([[maybe_unused]] typed_variable_decl) {})>() \ - : if (typed_variable_decl = ::Carbon::Internal::Kind::Cast< \ - decltype([]([[maybe_unused]] typed_variable_decl) {})>( \ - std::forward( \ - carbon_internal_kind_switch_value)); \ - false) {} \ - else [[maybe_unused]] CARBON_INTERNAL_KIND_LABEL(__LINE__) +// As a consequence of the macro suffixing along with the required prefix comma +// in `Type_CARBON_KIND_ANY_EXPAND`, input of `Namespace::Type` will have become +// `Namespace::, Type_CARBON_KIND_ANY_EXPAND`, and `DiscardNamespace` exists to +// discard `Namespace::`. +#define CARBON_KIND_ANY_INTERNAL_IMPL(typed_variable_decl, DiscardNamespace, \ + ...) \ + __VA_ARGS__: \ + CARBON_KIND_INTERNAL_DECLARE(typed_variable_decl) + +} // namespace Carbon::Internal::Kind #endif // CARBON_TOOLCHAIN_BASE_KIND_SWITCH_H_ diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index 80bab8f8fac4..4dbed383cb76 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -520,18 +520,11 @@ static auto MarkPatternUnused(Context& context, SemIR::InstId inst_id) -> bool { auto current_inst_id = worklist.pop_back_val(); auto inst = context.insts().Get(current_inst_id); CARBON_KIND_SWITCH(inst) { - case SemIR::OutParamPattern::Kind: - case SemIR::RefParamPattern::Kind: - case SemIR::ValueParamPattern::Kind: - case SemIR::VarParamPattern::Kind: { - auto param = inst.As(); + case CARBON_KIND_ANY(SemIR::AnyParamPattern, param): { worklist.push_back(param.subpattern_id); break; } - case SemIR::RefBindingPattern::Kind: - case SemIR::SymbolicBindingPattern::Kind: - case SemIR::ValueBindingPattern::Kind: { - auto bind = inst.As(); + case CARBON_KIND_ANY(SemIR::AnyBindingPattern, bind): { auto& name = context.entity_names().Get(bind.entity_name_id); name.is_unused = true; // We treat `_` as not marking the pattern as unused for the purpose of diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index f10ca31ffcc5..8ec94f30d586 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -602,18 +602,11 @@ static auto CheckUnusedBindingsInPattern(Context& context, auto current_id = work_list.pop_back_val(); auto inst = context.insts().Get(current_id); CARBON_KIND_SWITCH(inst) { - case SemIR::OutParamPattern::Kind: - case SemIR::RefParamPattern::Kind: - case SemIR::ValueParamPattern::Kind: - case SemIR::VarParamPattern::Kind: { - auto param = inst.As(); + case CARBON_KIND_ANY(SemIR::AnyParamPattern, param): { work_list.push_back(param.subpattern_id); break; } - case SemIR::RefBindingPattern::Kind: - case SemIR::SymbolicBindingPattern::Kind: - case SemIR::ValueBindingPattern::Kind: { - auto bind = inst.As(); + case CARBON_KIND_ANY(SemIR::AnyBindingPattern, bind): { auto& entity_name = context.entity_names().Get(bind.entity_name_id); // We need special treatment for the name "_" which is implicitly // unused but actually permitted in declarations. diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index f888f187fe22..3a1b3a960a88 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -248,40 +248,30 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param, return false; } - switch (new_param_pattern.kind()) { - case SemIR::FormParamPattern::Kind: - case SemIR::OutParamPattern::Kind: - case SemIR::RefParamPattern::Kind: - case SemIR::ValueParamPattern::Kind: - case SemIR::VarParamPattern::Kind: { + CARBON_KIND_SWITCH(new_param_pattern) { + case CARBON_KIND_ANY(SemIR::AnyParamPattern, new_any_param_pattern): { + auto prev_any_param_pattern = + prev_param_pattern.As(); pattern_stack.push_back( - {.prev_id = - prev_param_pattern.As().subpattern_id, - .new_id = - new_param_pattern.As().subpattern_id}); + {.prev_id = prev_any_param_pattern.subpattern_id, + .new_id = new_any_param_pattern.subpattern_id}); break; } - case SemIR::VarPattern::Kind: - pattern_stack.push_back( - {.prev_id = - prev_param_pattern.As().subpattern_id, - .new_id = - new_param_pattern.As().subpattern_id}); + case CARBON_KIND(SemIR::VarPattern new_var_pattern): { + auto prev_var_pattern = prev_param_pattern.As(); + pattern_stack.push_back({.prev_id = prev_var_pattern.subpattern_id, + .new_id = new_var_pattern.subpattern_id}); break; - case SemIR::FormBindingPattern::Kind: - case SemIR::RefBindingPattern::Kind: - case SemIR::SymbolicBindingPattern::Kind: - case SemIR::ValueBindingPattern::Kind: { - auto new_name_id = - context.entity_names() - .Get(new_param_pattern.As() - .entity_name_id) - .name_id; - auto prev_name_id = - context.entity_names() - .Get(prev_param_pattern.As() - .entity_name_id) - .name_id; + } + case CARBON_KIND_ANY(SemIR::AnyBindingPattern, new_any_binding_pattern): { + auto prev_any_binding_pattern = + prev_param_pattern.As(); + auto new_name_id = context.entity_names() + .Get(new_any_binding_pattern.entity_name_id) + .name_id; + auto prev_name_id = context.entity_names() + .Get(prev_any_binding_pattern.entity_name_id) + .name_id; if (!check_self && new_name_id == SemIR::NameId::SelfValue && prev_name_id == SemIR::NameId::SelfValue) { diff --git a/toolchain/check/pattern_match.cpp b/toolchain/check/pattern_match.cpp index 3f9405fa9333..2c29e2149939 100644 --- a/toolchain/check/pattern_match.cpp +++ b/toolchain/check/pattern_match.cpp @@ -634,20 +634,14 @@ auto MatchContext::EmitPatternMatch(Context& context, }); auto pattern = context.insts().Get(entry.pattern_id); CARBON_KIND_SWITCH(pattern) { - case SemIR::RefBindingPattern::Kind: - case SemIR::SymbolicBindingPattern::Kind: - case SemIR::ValueBindingPattern::Kind: - case SemIR::FormBindingPattern::Kind: - DoEmitPatternMatch(context, pattern.As(), - entry); + case CARBON_KIND_ANY(SemIR::AnyBindingPattern, any_binding_pattern): { + DoEmitPatternMatch(context, any_binding_pattern, entry); break; - case SemIR::FormParamPattern::Kind: - case SemIR::RefParamPattern::Kind: - case SemIR::ValueParamPattern::Kind: - case SemIR::VarParamPattern::Kind: - case SemIR::OutParamPattern::Kind: - DoEmitPatternMatch(context, pattern.As(), entry); + } + case CARBON_KIND_ANY(SemIR::AnyParamPattern, any_param_pattern): { + DoEmitPatternMatch(context, any_param_pattern, entry); break; + } case CARBON_KIND(SemIR::ReturnSlotPattern return_slot_pattern): { DoEmitPatternMatch(context, return_slot_pattern, entry); break; diff --git a/toolchain/check/testdata/function/call/form.carbon b/toolchain/check/testdata/function/call/form.carbon index 81cc577dc5da..8984d46c4054 100644 --- a/toolchain/check/testdata/function/call/form.carbon +++ b/toolchain/check/testdata/function/call/form.carbon @@ -226,15 +226,15 @@ fn F() ->? ref i32; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { -// CHECK:STDOUT: %.loc4_6.1: %pattern_type.7ce = form_binding_pattern x [concrete] -// CHECK:STDOUT: %.loc4_7: %pattern_type.7ce = form_param_pattern %.loc4_6.1 [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.7ce = form_binding_pattern x [concrete] +// CHECK:STDOUT: %.loc4_7: %pattern_type.7ce = form_param_pattern %x.patt [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %x.param: ref %i32 = ref_param call_param0 // CHECK:STDOUT: %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.1da] { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc4_15.2: Core.Form = ref_form %i32 [concrete = constants.%.1da] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc4_6.2: ref %i32 = form_binding x, %x.param +// CHECK:STDOUT: %x: ref %i32 = form_binding x, %x.param // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -286,15 +286,15 @@ fn F() ->? ref i32; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { -// CHECK:STDOUT: %.loc4_6.1: %pattern_type.7ce = form_binding_pattern x [concrete] -// CHECK:STDOUT: %.loc4_7: %pattern_type.7ce = form_param_pattern %.loc4_6.1 [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.7ce = form_binding_pattern x [concrete] +// CHECK:STDOUT: %.loc4_7: %pattern_type.7ce = form_param_pattern %x.patt [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %x.param: ref %i32 = ref_param call_param0 // CHECK:STDOUT: %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.324] { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc4_15.2: Core.Form = init_form %i32, call_param [concrete = constants.%.324] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc4_6.2: ref %i32 = form_binding x, %x.param +// CHECK:STDOUT: %x: ref %i32 = form_binding x, %x.param // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -354,15 +354,15 @@ fn F() ->? ref i32; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { -// CHECK:STDOUT: %.loc4_6.1: %pattern_type.7ce = form_binding_pattern x [concrete] -// CHECK:STDOUT: %.loc4_7: %pattern_type.7ce = form_param_pattern %.loc4_6.1 [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.7ce = form_binding_pattern x [concrete] +// CHECK:STDOUT: %.loc4_7: %pattern_type.7ce = form_param_pattern %x.patt [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %x.param: %i32 = value_param call_param0 // CHECK:STDOUT: %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.754] { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc4_15.2: Core.Form = value_form %i32 [concrete = constants.%.754] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc4_6.2: %i32 = form_binding x, %x.param +// CHECK:STDOUT: %x: %i32 = form_binding x, %x.param // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -396,8 +396,8 @@ fn F() ->? ref i32; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { -// CHECK:STDOUT: %.loc4_6.1: %pattern_type = form_binding_pattern x [concrete] -// CHECK:STDOUT: %.loc4_7: %pattern_type = form_param_pattern %.loc4_6.1 [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type = form_binding_pattern x [concrete] +// CHECK:STDOUT: %.loc4_7: %pattern_type = form_param_pattern %x.patt [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %x.param: ref %empty_tuple.type = ref_param call_param0 // CHECK:STDOUT: %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.9f9] { @@ -405,7 +405,7 @@ fn F() ->? ref i32; // CHECK:STDOUT: %.loc4_20.2: type = converted %.loc4_20.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] // CHECK:STDOUT: %.loc4_15.2: Core.Form = ref_form %.loc4_20.2 [concrete = constants.%.9f9] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc4_6.2: ref %empty_tuple.type = form_binding x, %x.param +// CHECK:STDOUT: %x: ref %empty_tuple.type = form_binding x, %x.param // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index 12ea98b6b6fc..1f0dd722faa6 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -24,6 +24,7 @@ #include "toolchain/sem_ir/formatter_chunks.h" #include "toolchain/sem_ir/function.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst_categories.h" #include "toolchain/sem_ir/name_scope.h" #include "toolchain/sem_ir/typed_insts.h" #include "toolchain/sem_ir/vtable.h" @@ -1042,23 +1043,17 @@ auto Formatter::FormatInstArgAndKind(Inst::ArgAndKind arg_and_kind) -> void { auto Formatter::FormatInstRhs(Inst inst) -> void { CARBON_KIND_SWITCH(inst) { - case InstKind::ArrayInit: - case InstKind::StructInit: - case InstKind::TupleInit: { - auto init = inst.As(); + case CARBON_KIND_ANY(AnyAggregateInit, init): { FormatArgs(init.elements_id); return; } - case InstKind::ImportRefLoaded: - case InstKind::ImportRefUnloaded: - FormatImportRefRhs(inst.As()); + case CARBON_KIND_ANY(AnyImportRef, import_ref): { + FormatImportRefRhs(import_ref); return; + } - case InstKind::OutParam: - case InstKind::RefParam: - case InstKind::ValueParam: { - auto param = inst.As(); + case CARBON_KIND_ANY(AnyParam, param): { FormatArgs(param.index); // Omit pretty_name because it's an implementation detail of // pretty-printing. @@ -1140,7 +1135,7 @@ auto Formatter::FormatInstRhs(Inst inst) -> void { return; } - case InstKind::ImportCppDecl: { + case ImportCppDecl::Kind: { FormatImportCppDeclRhs(); return; } @@ -1229,7 +1224,7 @@ auto Formatter::FormatInstRhs(Inst inst) -> void { return; } - case InstKind::ReturnSlotPattern: + case ReturnSlotPattern::Kind: // No-op because type_id is the only semantically significant field, // and it's handled separately. return; diff --git a/toolchain/sem_ir/inst_categories.h b/toolchain/sem_ir/inst_categories.h index a191cb4b48a7..d431eb9642e4 100644 --- a/toolchain/sem_ir/inst_categories.h +++ b/toolchain/sem_ir/inst_categories.h @@ -21,7 +21,7 @@ namespace Carbon::SemIR { // of a category inst type: // // struct MyCategory { -// using CategoryInfo = CategoryOf; +// using CategoryInfo = CARBON_INST_CATEGORY_INFO(MyCategory); // InstKind kind; // ... // } @@ -31,11 +31,31 @@ struct CategoryOf { static constexpr InstKind Kinds[] = {TypedInsts::Kind...}; }; +// For each category, we provide `CategoryName_CARBON_INST_CATEGORY` for the +// `CARBON_KIND_ANY` macro. This macro uses the same expansion to provide a +// `CategoryOf` for the category. +#define CARBON_INST_CATEGORY_INFO(Name) \ + CategoryOf +#define CARBON_INST_CATEGORY_INFO_INTERNAL_NAME(Name) Name +#define CARBON_INST_CATEGORY_INFO_INTERNAL_COMMA , + +// clang-format off +#define AnyAggregateAccess_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::ClassElementAccess) Sep \ + X(::Carbon::SemIR::StructAccess) Sep \ + X(::Carbon::SemIR::TupleAccess) +// clang-format on + +#define AnyAggregateAccess_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyAggregateAccess_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // Common representation for aggregate access nodes, which access a fixed // element of an aggregate. struct AnyAggregateAccess { - using CategoryInfo = - CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyAggregateAccess); InstKind kind; TypeId type_id; @@ -43,9 +63,21 @@ struct AnyAggregateAccess { ElementIndex index; }; +// clang-format off +#define AnyAggregateInit_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::ArrayInit) Sep \ + X(::Carbon::SemIR::ClassInit) Sep \ + X(::Carbon::SemIR::StructInit) Sep \ + X(::Carbon::SemIR::TupleInit) +// clang-format on + +#define AnyAggregateInit_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyAggregateInit_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // Common representation for all kinds of aggregate initialization. struct AnyAggregateInit { - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyAggregateInit); InstKind kind; TypeId type_id; @@ -53,20 +85,41 @@ struct AnyAggregateInit { DestInstId dest_id; }; +// clang-format off +#define AnyAggregateValue_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::StructValue) Sep \ + X(::Carbon::SemIR::TupleValue) +// clang-format on + +#define AnyAggregateValue_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyAggregateValue_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // Common representation for all kinds of aggregate value. struct AnyAggregateValue { - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyAggregateValue); InstKind kind; TypeId type_id; InstBlockId elements_id; }; +// clang-format off +#define AnyBindingPattern_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::FormBindingPattern) Sep \ + X(::Carbon::SemIR::RefBindingPattern) Sep \ + X(::Carbon::SemIR::SymbolicBindingPattern) Sep \ + X(::Carbon::SemIR::ValueBindingPattern) +// clang-format on + +#define AnyBindingPattern_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyBindingPattern_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // Common representation for various `*binding_pattern` nodes. struct AnyBindingPattern { // TODO: Also handle TemplateBindingPattern once it exists. - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyBindingPattern); InstKind kind; @@ -80,11 +133,23 @@ struct AnyBindingPattern { EntityNameId entity_name_id; }; +// clang-format off +#define AnyBinding_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::AliasBinding) Sep \ + X(::Carbon::SemIR::FormBinding) Sep \ + X(::Carbon::SemIR::RefBinding) Sep \ + X(::Carbon::SemIR::SymbolicBinding) Sep \ + X(::Carbon::SemIR::ValueBinding) +// clang-format on + +#define AnyBinding_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyBinding_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // Common representation for various `bind*` nodes. struct AnyBinding { // TODO: Also handle BindTemplateName once it exists. - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyBinding); InstKind kind; TypeId type_id; @@ -95,11 +160,24 @@ struct AnyBinding { InstId value_id; }; +// clang-format off +#define AnyBindingOrExportDecl_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::AliasBinding) Sep \ + X(::Carbon::SemIR::FormBinding) Sep \ + X(::Carbon::SemIR::RefBinding) Sep \ + X(::Carbon::SemIR::SymbolicBinding) Sep \ + X(::Carbon::SemIR::ValueBinding) Sep \ + X(::Carbon::SemIR::ExportDecl) +// clang-format on + +#define AnyBindingOrExportDecl_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyBindingOrExportDecl_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // Common representation for various `bind*` nodes, and `export name`. struct AnyBindingOrExportDecl { // TODO: Also handle BindTemplateName once it exists. - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyBindingOrExportDecl); InstKind kind; TypeId type_id; @@ -107,9 +185,20 @@ struct AnyBindingOrExportDecl { InstId value_id; }; +// clang-format off +#define AnyBranch_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::Branch) Sep \ + X(::Carbon::SemIR::BranchIf) Sep \ + X(::Carbon::SemIR::BranchWithArg) +// clang-format on + +#define AnyBranch_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyBranch_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // Common representation for all kinds of `Branch*` node. struct AnyBranch { - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyBranch); InstKind kind; // Branches don't produce a value, so have no type. @@ -118,10 +207,20 @@ struct AnyBranch { AnyRawId arg1; }; +// clang-format off +#define AnyFoundationDecl_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::AdaptDecl) Sep \ + X(::Carbon::SemIR::BaseDecl) +// clang-format on + +#define AnyFoundationDecl_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyFoundationDecl_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // Common representation for declarations describing the foundation type of a // class -- either its adapted type or its base class. struct AnyFoundationDecl { - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyFoundationDecl); InstKind kind; TypeId type_id; @@ -130,9 +229,19 @@ struct AnyFoundationDecl { AnyRawId arg1; }; +// clang-format off +#define AnyImportRef_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::ImportRefLoaded) Sep \ + X(::Carbon::SemIR::ImportRefUnloaded) +// clang-format on + +#define AnyImportRef_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyImportRef_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // Common representation for all kinds of `ImportRef*` node. struct AnyImportRef { - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyImportRef); InstKind kind; TypeId type_id; @@ -142,9 +251,20 @@ struct AnyImportRef { EntityNameId entity_name_id; }; +// clang-format off +#define AnyParam_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::OutParam) Sep \ + X(::Carbon::SemIR::RefParam) Sep \ + X(::Carbon::SemIR::ValueParam) +// clang-format on + +#define AnyParam_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyParam_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // A `Call` parameter for a function or other parameterized block. struct AnyParam { - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyParam); InstKind kind; TypeId type_id; @@ -156,12 +276,23 @@ struct AnyParam { NameId pretty_name_id; }; +// clang-format off +#define AnyParamPattern_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::FormParamPattern) Sep \ + X(::Carbon::SemIR::OutParamPattern) Sep \ + X(::Carbon::SemIR::RefParamPattern) Sep \ + X(::Carbon::SemIR::ValueParamPattern) Sep \ + X(::Carbon::SemIR::VarParamPattern) +// clang-format on + +#define AnyParamPattern_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyParamPattern_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // A pattern that represents a `Call` parameter. It delegates to subpattern_id // in pattern matching. struct AnyParamPattern { - using CategoryInfo = - CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyParamPattern); InstKind kind; @@ -171,9 +302,20 @@ struct AnyParamPattern { InstId subpattern_id; }; +// clang-format off +#define AnyPrimitiveForm_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::InitForm) Sep \ + X(::Carbon::SemIR::RefForm) Sep \ + X(::Carbon::SemIR::ValueForm) +// clang-format on + +#define AnyPrimitiveForm_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyPrimitiveForm_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // An inst that represents a primitive form. struct AnyPrimitiveForm { - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyPrimitiveForm); InstKind kind; @@ -186,11 +328,22 @@ struct AnyPrimitiveForm { AnyRawId arg1; }; +// clang-format off +#define AnyQualifiedType_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::ConstType) Sep \ + X(::Carbon::SemIR::MaybeUnformedType) Sep \ + X(::Carbon::SemIR::PartialType) +// clang-format on + +#define AnyQualifiedType_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyQualifiedType_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // A type qualifier that wraps another type and has the same object // representation. Qualifiers are arranged so that adding a qualifier is // generally safe, and removing a qualifier is not necessarily safe or correct. struct AnyQualifiedType { - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyQualifiedType); InstKind kind; @@ -198,9 +351,19 @@ struct AnyQualifiedType { TypeInstId inner_id; }; +// clang-format off +#define AnyStructType_CARBON_INST_CATEGORY(X, Sep) \ + X(::Carbon::SemIR::CustomLayoutType) Sep \ + X(::Carbon::SemIR::StructType) +// clang-format on + +#define AnyStructType_CARBON_KIND_ANY_EXPAND \ + CARBON_KIND_ANY_EXPAND_BEGIN AnyStructType_CARBON_INST_CATEGORY( \ + CARBON_KIND_ANY_EXPAND_CASE, CARBON_KIND_ANY_EXPAND_SEP) + // A struct-like type with a list of named fields. struct AnyStructType { - using CategoryInfo = CategoryOf; + using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyStructType); InstKind kind; diff --git a/toolchain/sem_ir/inst_namer.cpp b/toolchain/sem_ir/inst_namer.cpp index 0ac6ba70d0d1..ec69febea583 100644 --- a/toolchain/sem_ir/inst_namer.cpp +++ b/toolchain/sem_ir/inst_namer.cpp @@ -914,19 +914,11 @@ auto InstNamer::NamingContext::NameInst() -> void { AddEntityNameAndMaybePush(inst.interface_id, ".assoc_type"); return; } - case AliasBinding::Kind: - case RefBinding::Kind: - case SymbolicBinding::Kind: - case ValueBinding::Kind: - case ExportDecl::Kind: { - auto inst = inst_.As(); + case CARBON_KIND_ANY(AnyBindingOrExportDecl, inst): { AddInstNameId(sem_ir().entity_names().Get(inst.entity_name_id).name_id); return; } - case RefBindingPattern::Kind: - case SymbolicBindingPattern::Kind: - case ValueBindingPattern::Kind: { - auto inst = inst_.As(); + case CARBON_KIND_ANY(AnyBindingPattern, inst): { auto name_id = NameId::Underscore; if (inst.entity_name_id.has_value()) { name_id = sem_ir().entity_names().Get(inst.entity_name_id).name_id; @@ -951,10 +943,7 @@ auto InstNamer::NamingContext::NameInst() -> void { } return; } - case Branch::Kind: - case BranchIf::Kind: - case BranchWithArg::Kind: { - auto branch = inst_.As(); + case CARBON_KIND_ANY(AnyBranch, branch): { inst_namer_->AddBlockLabel(scope_id_, LocId(inst_id_), branch); return; } @@ -1209,12 +1198,10 @@ auto InstNamer::NamingContext::NameInst() -> void { } return; } - case ImportRefUnloaded::Kind: - case ImportRefLoaded::Kind: { + case CARBON_KIND_ANY(AnyImportRef, inst): { // Build the base import name: . RawStringOstream out; - auto inst = inst_.As(); auto import_ir_inst = sem_ir().import_ir_insts().Get(inst.import_ir_inst_id); const auto& import_ir = @@ -1304,10 +1291,8 @@ auto InstNamer::NamingContext::NameInst() -> void { AddInstNameId(sem_ir().name_scopes().Get(inst.name_scope_id).name_id()); return; } - case OutParam::Kind: - case RefParam::Kind: - case ValueParam::Kind: { - AddInstNameId(inst_.As().pretty_name_id, ".param"); + case CARBON_KIND_ANY(AnyParam, inst): { + AddInstNameId(inst.pretty_name_id, ".param"); return; } case OutParamPattern::Kind: