Support CARBON_KIND with Any types (#6828)

This uses the `CARBON_KIND_ANY(AnyImportRef, auto import_ref):` syntax
that seemed to be favored [on
Discord](https://discord.com/channels/655572317891461132/655578254970716160/1478486848207720478).

This converted uses in the `sem_ir` directory to show it works
initially, then added `check` for full coverage plus validating the
`SemIR::` namespace discard.

Note in inst_namer.cpp, AnyBindingPattern includes FormBindingPattern
which wasn't previously handled.

I'm disabling clang-format because I think it formats with readability
issues, e.g.:

```
#define CARBON_KIND_ANY_EXPAND_AnyBinding(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)
```

Since `SEP` is typically a comma, it's also a nuisance to treat as an
argument to `X` (which could get better results).

Assisted-by: Google Antigravity with Gemini 3 Flash
This commit is contained in:
Jon Ross-Perkins
2026-03-05 01:20:37 +00:00
committed by GitHub
parent 4d0003765d
commit 002b7c74ea
9 changed files with 333 additions and 153 deletions
+93 -26
View File
@@ -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<CaseT>` 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 <typename T>
@@ -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<CARBON_KIND_INTERNAL_WRAP_TYPE( \
typed_variable_decl)>( \
std::forward<decltype(carbon_internal_kind_switch_value)>( \
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<decltype(carbon_internal_kind_switch_value)>( \
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_
+2 -9
View File
@@ -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<SemIR::AnyParamPattern>();
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<SemIR::AnyBindingPattern>();
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
+2 -9
View File
@@ -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<SemIR::AnyParamPattern>();
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<SemIR::AnyBindingPattern>();
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.
+20 -30
View File
@@ -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<SemIR::AnyParamPattern>();
pattern_stack.push_back(
{.prev_id =
prev_param_pattern.As<SemIR::AnyParamPattern>().subpattern_id,
.new_id =
new_param_pattern.As<SemIR::AnyParamPattern>().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<SemIR::VarPattern>().subpattern_id,
.new_id =
new_param_pattern.As<SemIR::VarPattern>().subpattern_id});
case CARBON_KIND(SemIR::VarPattern new_var_pattern): {
auto prev_var_pattern = prev_param_pattern.As<SemIR::VarPattern>();
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<SemIR::AnyBindingPattern>()
.entity_name_id)
.name_id;
auto prev_name_id =
context.entity_names()
.Get(prev_param_pattern.As<SemIR::AnyBindingPattern>()
.entity_name_id)
.name_id;
}
case CARBON_KIND_ANY(SemIR::AnyBindingPattern, new_any_binding_pattern): {
auto prev_any_binding_pattern =
prev_param_pattern.As<SemIR::AnyBindingPattern>();
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) {
+6 -12
View File
@@ -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<SemIR::AnyBindingPattern>(),
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<SemIR::AnyParamPattern>(), 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;
+12 -12
View File
@@ -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<none> [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:
+8 -13
View File
@@ -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<AnyAggregateInit>();
case CARBON_KIND_ANY(AnyAggregateInit, init): {
FormatArgs(init.elements_id);
return;
}
case InstKind::ImportRefLoaded:
case InstKind::ImportRefUnloaded:
FormatImportRefRhs(inst.As<AnyImportRef>());
case CARBON_KIND_ANY(AnyImportRef, import_ref): {
FormatImportRefRhs(import_ref);
return;
}
case InstKind::OutParam:
case InstKind::RefParam:
case InstKind::ValueParam: {
auto param = inst.As<AnyParam>();
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;
+184 -21
View File
@@ -21,7 +21,7 @@ namespace Carbon::SemIR {
// of a category inst type:
//
// struct MyCategory {
// using CategoryInfo = CategoryOf<X, Y, Z>;
// 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<Name##_CARBON_INST_CATEGORY( \
CARBON_INST_CATEGORY_INFO_INTERNAL_NAME, \
CARBON_INST_CATEGORY_INFO_INTERNAL_COMMA)>
#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<ClassElementAccess, StructAccess, TupleAccess>;
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<ArrayInit, ClassInit, StructInit, TupleInit>;
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<StructValue, TupleValue>;
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<FormBindingPattern, RefBindingPattern,
SymbolicBindingPattern, ValueBindingPattern>;
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<AliasBinding, FormBinding, RefBinding,
SymbolicBinding, ValueBinding>;
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<AliasBinding, FormBinding, RefBinding,
SymbolicBinding, ValueBinding, ExportDecl>;
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<Branch, BranchIf, BranchWithArg>;
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<AdaptDecl, BaseDecl>;
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<ImportRefUnloaded, ImportRefLoaded>;
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<OutParam, RefParam, ValueParam>;
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<FormParamPattern, OutParamPattern, RefParamPattern,
ValueParamPattern, VarParamPattern>;
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<InitForm, RefForm, ValueForm>;
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<ConstType, PartialType, MaybeUnformedType>;
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<StructType, CustomLayoutType>;
using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyStructType);
InstKind kind;
+6 -21
View File
@@ -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<AnyBindingOrExportDecl>();
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<AnyBindingPattern>();
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<AnyBranch>();
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: <package>.<entity-name>
RawStringOstream out;
auto inst = inst_.As<AnyImportRef>();
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<AnyParam>().pretty_name_id, ".param");
case CARBON_KIND_ANY(AnyParam, inst): {
AddInstNameId(inst.pretty_name_id, ".param");
return;
}
case OutParamPattern::Kind: