diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 3e9bf8171fd6..4041ea29c1a5 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -26,6 +26,7 @@ #include "toolchain/sem_ir/generic.h" #include "toolchain/sem_ir/id_kind.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst_categories.h" #include "toolchain/sem_ir/inst_kind.h" #include "toolchain/sem_ir/typed_insts.h" diff --git a/toolchain/lower/file_context.cpp b/toolchain/lower/file_context.cpp index 23f904542ca2..6d6d2f157046 100644 --- a/toolchain/lower/file_context.cpp +++ b/toolchain/lower/file_context.cpp @@ -30,6 +30,7 @@ #include "toolchain/sem_ir/generic.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" +#include "toolchain/sem_ir/inst_categories.h" #include "toolchain/sem_ir/inst_kind.h" #include "toolchain/sem_ir/pattern.h" #include "toolchain/sem_ir/typed_insts.h" diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index bf79e0cc7fc8..f28e7be4adf4 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -27,6 +27,7 @@ cc_library( hdrs = [ "id_kind.h", "ids.h", + "inst_categories.h", "inst_kind.h", "singleton_insts.h", "typed_insts.h", diff --git a/toolchain/sem_ir/function.h b/toolchain/sem_ir/function.h index 8cdd723439b1..02c469bf1f89 100644 --- a/toolchain/sem_ir/function.h +++ b/toolchain/sem_ir/function.h @@ -9,6 +9,7 @@ #include "toolchain/sem_ir/builtin_function_kind.h" #include "toolchain/sem_ir/entity_with_params_base.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst_categories.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::SemIR { diff --git a/toolchain/sem_ir/inst.h b/toolchain/sem_ir/inst.h index 83984427ddc6..47efa2376414 100644 --- a/toolchain/sem_ir/inst.h +++ b/toolchain/sem_ir/inst.h @@ -24,12 +24,14 @@ namespace Carbon::SemIR { +template +struct CategoryOf; + // InstLikeTypeInfo is an implementation detail, and not public API. namespace Internal { // Information about an instruction-like type, which is a type that an Inst can -// be converted to and from. The `Enabled` parameter is used to check -// requirements on the type in the specializations of this template. +// be converted to and from. template struct InstLikeTypeInfo; @@ -74,15 +76,60 @@ struct InstLikeTypeInfo : InstLikeTypeInfoBase { static auto DebugName() -> InstKind { return TypedInst::Kind; } }; +// If `TypedInst` has an Nth field, validates that `CategoryInst` has a +// corresponding field with a compatible type. +template +static consteval auto ValidateCategoryFieldForTypedInst() -> void { + if constexpr (InstLikeTypeInfoBase::NumArgs > N) { + if constexpr (!std::is_same_v::template ArgType, + AnyRawId>) { + static_assert( + std::is_same_v< + typename InstLikeTypeInfoBase::template ArgType, + typename InstLikeTypeInfoBase::template ArgType>, + "Inst category field should be the same type as the " + "corresponding fields of its typed insts, or AnyRawId if " + "they have different types"); + } + } +} + +// Validates that `CategoryInst` is compatible with `TypedInst` +template +static consteval auto ValidateCategoryForTypedInst() -> void { + static_assert(Internal::HasKindMemberAsField, + "Inst category should have an `InstKind` field"); + static_assert(!HasTypeIdMember || HasTypeIdMember, + "Inst category should have a `TypeId` field if any of its " + "typed insts do"); + + static_assert(InstLikeTypeInfoBase::NumArgs >= + InstLikeTypeInfoBase::NumArgs, + "Inst category should have as many fields as any of its typed " + "insts"); + + ValidateCategoryFieldForTypedInst(); + ValidateCategoryFieldForTypedInst(); +} + +// Validates that `CategoryInst` is compatible with all of `TypedInsts`. +// Always returns true; validation failure will cause build errors when +// instantiating the function. +template +static consteval auto ValidateCategory( + CategoryOf /*category_info*/) -> bool { + (ValidateCategoryForTypedInst(), ...); + return true; +} + // An instruction category is instruction-like. template - requires std::same_as + requires requires { typename InstCat::CategoryInfo; } struct InstLikeTypeInfo : InstLikeTypeInfoBase { - static_assert(HasKindMemberAsField, - "Instruction category should have a kind field"); static auto GetKind(InstCat cat) -> InstKind { return cat.kind; } static constexpr auto IsKind(InstKind kind) -> bool { - for (InstKind k : InstCat::Kinds) { + for (InstKind k : InstCat::CategoryInfo::Kinds) { if (k == kind) { return true; } @@ -94,12 +141,16 @@ struct InstLikeTypeInfo : InstLikeTypeInfoBase { RawStringOstream out; out << "{"; llvm::ListSeparator sep; - for (auto kind : InstCat::Kinds) { + for (auto kind : InstCat::CategoryInfo::Kinds) { out << sep << kind; } out << "}"; return out.TakeStr(); } + + private: + // Trigger validation of `InstCat`. + static_assert(ValidateCategory(typename InstCat::CategoryInfo())); }; // HasInstCategory is true if T::Kind is an element of InstCat::Kinds. diff --git a/toolchain/sem_ir/inst_categories.h b/toolchain/sem_ir/inst_categories.h new file mode 100644 index 000000000000..f64b701b1e23 --- /dev/null +++ b/toolchain/sem_ir/inst_categories.h @@ -0,0 +1,172 @@ +// 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 + +#ifndef CARBON_TOOLCHAIN_SEM_IR_INST_CATEGORIES_H_ +#define CARBON_TOOLCHAIN_SEM_IR_INST_CATEGORIES_H_ + +#include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst_kind.h" +#include "toolchain/sem_ir/typed_insts.h" + +// An inst category is a set of inst kinds that can be treated polymorphically. +// Each inst category is represented by a C++ type, just like an inst kind, +// which can losslessly represent any inst in the category. `CategoryOf` +// is used to declare the typed insts that belong to the category. + +namespace Carbon::SemIR { + +// Declares a category consisting of `TypedInsts...`, which is a list of typed +// insts (not kinds). Should only be used to define a public type alias member +// of a category inst type: +// +// struct MyCategory { +// using CategoryInfo = CategoryOf; +// InstKind kind; +// ... +// } +template +struct CategoryOf { + // The InstKinds that belong to the category. + static constexpr InstKind Kinds[] = {TypedInsts::Kind...}; +}; + +// Common representation for aggregate access nodes, which access a fixed +// element of an aggregate. +struct AnyAggregateAccess { + using CategoryInfo = + CategoryOf; + + InstKind kind; + TypeId type_id; + InstId aggregate_id; + ElementIndex index; +}; + +// Common representation for all kinds of aggregate initialization. +struct AnyAggregateInit { + using CategoryInfo = CategoryOf; + + InstKind kind; + TypeId type_id; + InstBlockId elements_id; + DestInstId dest_id; +}; + +// Common representation for all kinds of aggregate value. +struct AnyAggregateValue { + using CategoryInfo = CategoryOf; + + InstKind kind; + TypeId type_id; + InstBlockId elements_id; +}; + +// Common representation for various `*binding_pattern` nodes. +struct AnyBindingPattern { + // TODO: Also handle TemplateBindingPattern once it exists. + using CategoryInfo = CategoryOf; + + InstKind kind; + + // Always a PatternType whose scrutinee type is the declared type of the + // binding. + TypeId type_id; + + // The name declared by the binding pattern. `None` indicates that the + // pattern has `_` in the name position, and so does not truly declare + // a name. + EntityNameId entity_name_id; +}; + +// Common representation for various `bind*` nodes. +struct AnyBindName { + // TODO: Also handle BindTemplateName once it exists. + using CategoryInfo = CategoryOf; + + InstKind kind; + TypeId type_id; + EntityNameId entity_name_id; + InstId value_id; +}; + +// Common representation for various `bind*` nodes, and `export name`. +struct AnyBindNameOrExportDecl { + // TODO: Also handle BindTemplateName once it exists. + using CategoryInfo = + CategoryOf; + + InstKind kind; + TypeId type_id; + EntityNameId entity_name_id; + InstId value_id; +}; + +// Common representation for all kinds of `Branch*` node. +struct AnyBranch { + using CategoryInfo = CategoryOf; + + InstKind kind; + // Branches don't produce a value, so have no type. + LabelId target_id; + // Kind-specific data. + AnyRawId arg1; +}; + +// Common representation for declarations describing the foundation type of a +// class -- either its adapted type or its base class. +struct AnyFoundationDecl { + using CategoryInfo = CategoryOf; + + InstKind kind; + TypeId type_id; + TypeInstId foundation_type_inst_id; + // Kind-specific data. + AnyRawId arg1; +}; + +// Common representation for all kinds of `ImportRef*` node. +struct AnyImportRef { + using CategoryInfo = CategoryOf; + + InstKind kind; + TypeId type_id; + ImportIRInstId import_ir_inst_id; + // A BindName is currently only set on directly imported names. It is not + // generically available. + EntityNameId entity_name_id; +}; + +// A `Call` parameter for a function or other parameterized block. +struct AnyParam { + using CategoryInfo = CategoryOf; + + InstKind kind; + TypeId type_id; + CallParamIndex index; + + // A name to associate with this Param in pretty-printed IR. This is not + // necessarily unique, and can even be `None`; it has no semantic + // significance. + NameId pretty_name_id; +}; + +// A pattern that represents a `Call` parameter. It delegates to subpattern_id +// in pattern matching. The sub-kinds differ only in the expression category +// of the corresponding parameter inst. +struct AnyParamPattern { + using CategoryInfo = + CategoryOf; + + InstKind kind; + + // Always a PatternType that represents the same type as the type of + // `subpattern_id`. + TypeId type_id; + InstId subpattern_id; + CallParamIndex index; +}; + +} // namespace Carbon::SemIR + +#endif // CARBON_TOOLCHAIN_SEM_IR_INST_CATEGORIES_H_ diff --git a/toolchain/sem_ir/inst_namer.h b/toolchain/sem_ir/inst_namer.h index 96ac9c48288e..7175591f2ccc 100644 --- a/toolchain/sem_ir/inst_namer.h +++ b/toolchain/sem_ir/inst_namer.h @@ -11,6 +11,7 @@ #include "toolchain/parse/tree.h" #include "toolchain/sem_ir/file.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst_categories.h" #include "toolchain/sem_ir/inst_fingerprinter.h" namespace Carbon::SemIR { diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index 069efabbcd18..5715bc10f34f 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -76,17 +76,6 @@ struct AccessOptionalMemberAction { NameId name_id; }; -// Common representation for declarations describing the foundation type of a -// class -- either its adapted type or its base class. -struct AnyFoundationDecl { - static constexpr InstKind Kinds[] = {InstKind::AdaptDecl, InstKind::BaseDecl}; - - InstKind kind; - TypeInstId foundation_type_inst_id; - // Kind-specific data. - AnyRawId arg1; -}; - // An adapted type declaration in a class, of the form `adapt T;`. struct AdaptDecl { static constexpr auto Kind = InstKind::AdaptDecl.Define( @@ -139,41 +128,6 @@ struct ArrayIndex { InstId index_id; }; -// Common representation for aggregate access nodes, which access a fixed -// element of an aggregate. -struct AnyAggregateAccess { - static constexpr InstKind Kinds[] = {InstKind::ClassElementAccess, - InstKind::StructAccess, - InstKind::TupleAccess}; - - InstKind kind; - TypeId type_id; - InstId aggregate_id; - ElementIndex index; -}; - -// Common representation for all kinds of aggregate initialization. -struct AnyAggregateInit { - static constexpr InstKind Kinds[] = {InstKind::ArrayInit, InstKind::ClassInit, - InstKind::StructInit, - InstKind::TupleInit}; - - InstKind kind; - TypeId type_id; - InstBlockId elements_id; - DestInstId dest_id; -}; - -// Common representation for all kinds of aggregate value. -struct AnyAggregateValue { - static constexpr InstKind Kinds[] = {InstKind::StructValue, - InstKind::TupleValue}; - - InstKind kind; - TypeId type_id; - InstBlockId elements_id; -}; - // Initializes an array from a tuple. `tuple_id` is the source tuple // expression. `inits_id` contains one initializer per array element. // `dest_id` is the destination array object for the initialization. @@ -296,31 +250,6 @@ struct BaseDecl { ElementIndex index; }; -// Common representation for various `bind*` nodes. -struct AnyBindName { - // TODO: Also handle BindTemplateName once it exists. - static constexpr InstKind Kinds[] = {InstKind::BindAlias, InstKind::BindName, - InstKind::BindSymbolicName}; - - InstKind kind; - TypeId type_id; - EntityNameId entity_name_id; - InstId value_id; -}; - -// Common representation for various `bind*` nodes, and `export name`. -struct AnyBindNameOrExportDecl { - // TODO: Also handle BindTemplateName once it exists. - static constexpr InstKind Kinds[] = {InstKind::BindAlias, InstKind::BindName, - InstKind::BindSymbolicName, - InstKind::ExportDecl}; - - InstKind kind; - TypeId type_id; - EntityNameId entity_name_id; - InstId value_id; -}; - // Binds a name as an alias. struct BindAlias { static constexpr auto Kind = @@ -366,25 +295,8 @@ struct BindValue { InstId value_id; }; -// Common representation for various `*binding_pattern` nodes. -struct AnyBindingPattern { - // TODO: Also handle TemplateBindingPattern once it exists. - static constexpr InstKind Kinds[] = {InstKind::BindingPattern, - InstKind::SymbolicBindingPattern}; - - InstKind kind; - - // Always a PatternType whose scrutinee type is the declared type of the - // binding. - TypeId type_id; - - // The name declared by the binding pattern. `None` indicates that the - // pattern has `_` in the name position, and so does not truly declare - // a name. - EntityNameId entity_name_id; -}; - -// Represents a non-symbolic binding pattern. +// Represents a non-symbolic binding pattern. See `AnyBindingPattern` for member +// documentation. struct BindingPattern { static constexpr auto Kind = InstKind::BindingPattern.Define( {.ir_name = "binding_pattern", @@ -395,19 +307,6 @@ struct BindingPattern { EntityNameId entity_name_id; }; -// Represents a symbolic binding pattern. -struct SymbolicBindingPattern { - static constexpr auto Kind = - InstKind::SymbolicBindingPattern.Define({ - .ir_name = "symbolic_binding_pattern", - .constant_kind = InstConstantKind::AlwaysUnique, - .is_lowered = false, - }); - - TypeId type_id; - EntityNameId entity_name_id; -}; - // Reads an argument from `BranchWithArg`. struct BlockArg { static constexpr auto Kind = InstKind::BlockArg.Define( @@ -471,18 +370,6 @@ struct BoundMethodType { TypeId type_id; }; -// Common representation for all kinds of `Branch*` node. -struct AnyBranch { - static constexpr InstKind Kinds[] = {InstKind::Branch, InstKind::BranchIf, - InstKind::BranchWithArg}; - - InstKind kind; - // Branches don't produce a value, so have no type. - LabelId target_id; - // Kind-specific data. - AnyRawId arg1; -}; - // Control flow to branch to the target block. struct Branch { // TODO: Make Parse::NodeId more specific. @@ -625,6 +512,19 @@ struct ConstType { TypeInstId inner_id; }; +// Records that a type conversion `original as new_type` was done, producing the +// result. +struct Converted { + static constexpr auto Kind = + InstKind::Converted.Define({.ir_name = "converted"}); + + TypeId type_id; + // The operand prior to being converted. This is tracked only for tooling + // purposes and has no associated semantics. + AbsoluteInstId original_id; + InstId result_id; +}; + // An action that performs simple conversion to a value expression of a given // type. struct ConvertToValueAction { @@ -639,19 +539,6 @@ struct ConvertToValueAction { TypeInstId target_type_inst_id; }; -// Records that a type conversion `original as new_type` was done, producing the -// result. -struct Converted { - static constexpr auto Kind = - InstKind::Converted.Define({.ir_name = "converted"}); - - TypeId type_id; - // The operand prior to being converted. This is tracked only for tooling - // purposes and has no associated semantics. - AbsoluteInstId original_id; - InstId result_id; -}; - // The `*` dereference operator, as in `*pointer`. struct Deref { static constexpr auto Kind = @@ -774,22 +661,6 @@ struct FloatType { InstId bit_width_id; }; -// The legacy float type. This is currently used for real literals, and is -// treated as f64. It's separate from `FloatType`, and should change to mirror -// integers, likely replacing this with a `FloatLiteralType`. -struct LegacyFloatType { - static constexpr auto Kind = - InstKind::LegacyFloatType.Define( - {.ir_name = "f64", - .is_type = InstIsType::Always, - .constant_kind = InstConstantKind::Always}); - // This is a singleton instruction. However, it may still evolve into a more - // standard type and be removed. - static constexpr auto TypeInstId = MakeSingletonTypeInstId(); - - TypeId type_id; -}; - // A function declaration. struct FunctionDecl { static constexpr auto Kind = @@ -1017,19 +888,8 @@ struct ImportDecl { NameId package_id; }; -// Common representation for all kinds of `ImportRef*` node. -struct AnyImportRef { - static constexpr InstKind Kinds[] = {InstKind::ImportRefUnloaded, - InstKind::ImportRefLoaded}; - - InstKind kind; - ImportIRInstId import_ir_inst_id; - // A BindName is currently only set on directly imported names. It is not - // generically available. - EntityNameId entity_name_id; -}; - -// An imported entity that is not yet been loaded. +// An imported entity that is not yet been loaded. See `AnyImportRef` for +// member documentation. struct ImportRefUnloaded { static constexpr auto Kind = InstKind::ImportRefUnloaded.Define( @@ -1039,7 +899,8 @@ struct ImportRefUnloaded { EntityNameId entity_name_id; }; -// A imported entity that is loaded, and may be used. +// A imported entity that is loaded, and may be used. See `AnyImportRef` for +// member documentation. struct ImportRefLoaded { static constexpr auto Kind = InstKind::ImportRefLoaded.Define( {.ir_name = "import_ref", .is_lowered = false}); @@ -1103,16 +964,6 @@ struct InterfaceDecl { DeclInstBlockId decl_block_id; }; -// A literal integer value. -struct IntValue { - // TODO: Make Parse::NodeId more specific. - static constexpr auto Kind = InstKind::IntValue.Define( - {.ir_name = "int_value", .constant_kind = InstConstantKind::Always}); - - TypeId type_id; - IntId int_id; -}; - // An arbitrary-precision integer type, which is used as the type of integer // literals and as the parameter type of `Core.Int` and `Core.Float`. This type // only provides compile-time operations, and is represented as an empty type at @@ -1148,6 +999,32 @@ struct IntType { InstId bit_width_id; }; +// A literal integer value. +struct IntValue { + // TODO: Make Parse::NodeId more specific. + static constexpr auto Kind = InstKind::IntValue.Define( + {.ir_name = "int_value", .constant_kind = InstConstantKind::Always}); + + TypeId type_id; + IntId int_id; +}; + +// The legacy float type. This is currently used for real literals, and is +// treated as f64. It's separate from `FloatType`, and should change to mirror +// integers, likely replacing this with a `FloatLiteralType`. +struct LegacyFloatType { + static constexpr auto Kind = + InstKind::LegacyFloatType.Define( + {.ir_name = "f64", + .is_type = InstIsType::Always, + .constant_kind = InstConstantKind::Always}); + // This is a singleton instruction. However, it may still evolve into a more + // standard type and be removed. + static constexpr auto TypeInstId = MakeSingletonTypeInstId(); + + TypeId type_id; +}; + // A symbolic instruction that takes the place of an `ImplWitness` when the // result is not fully known. When evaluated it does an impl lookup query, based // on the stored query arguments, that a type implements an interface. The query @@ -1230,21 +1107,6 @@ struct NamespaceType { TypeId type_id; }; -// A `Call` parameter for a function or other parameterized block. -struct AnyParam { - static constexpr InstKind Kinds[] = {InstKind::OutParam, InstKind::RefParam, - InstKind::ValueParam}; - - InstKind kind; - TypeId type_id; - CallParamIndex index; - - // A name to associate with this Param in pretty-printed IR. This is not - // necessarily unique, and can even be `None`; it has no semantic - // significance. - NameId pretty_name_id; -}; - // An output `Call` parameter. See AnyParam for member documentation. struct OutParam { // TODO: Make Parse::NodeId more specific. @@ -1256,46 +1118,8 @@ struct OutParam { NameId pretty_name_id; }; -// A by-reference `Call` parameter. See AnyParam for member documentation. -struct RefParam { - // TODO: Make Parse::NodeId more specific. - static constexpr auto Kind = InstKind::RefParam.Define( - {.ir_name = "ref_param", .constant_kind = InstConstantKind::Never}); - - TypeId type_id; - CallParamIndex index; - NameId pretty_name_id; -}; - -// A by-value `Call` parameter. See AnyParam for member documentation. -struct ValueParam { - // TODO: Make Parse::NodeId more specific. - static constexpr auto Kind = InstKind::ValueParam.Define( - {.ir_name = "value_param", .constant_kind = InstConstantKind::Never}); - - TypeId type_id; - CallParamIndex index; - NameId pretty_name_id; -}; - -// A pattern that represents a `Call` parameter. It delegates to subpattern_id -// in pattern matching. The sub-kinds differ only in the expression category -// of the corresponding parameter inst. -struct AnyParamPattern { - static constexpr InstKind Kinds[] = {InstKind::OutParamPattern, - InstKind::RefParamPattern, - InstKind::ValueParamPattern}; - - InstKind kind; - - // Always a PatternType that represents the same type as the type of - // `subpattern_id`. - TypeId type_id; - InstId subpattern_id; - CallParamIndex index; -}; - -// A pattern that represents an output `Call` parameter. +// A pattern that represents an output `Call` parameter. See `AnyParamPattern` +// for member documentation. struct OutParamPattern { static constexpr auto Kind = InstKind::OutParamPattern.Define( @@ -1308,33 +1132,6 @@ struct OutParamPattern { CallParamIndex index; }; -// A pattern that represents a by-reference `Call` parameter. -struct RefParamPattern { - // TODO: Make Parse::NodeId more specific. - static constexpr auto Kind = InstKind::RefParamPattern.Define( - {.ir_name = "ref_param_pattern", - .constant_kind = InstConstantKind::AlwaysUnique, - .is_lowered = false}); - - TypeId type_id; - InstId subpattern_id; - CallParamIndex index; -}; - -// A pattern that represents a by-value `Call` parameter. -struct ValueParamPattern { - // TODO: Make Parse::NodeId more specific. - static constexpr auto Kind = - InstKind::ValueParamPattern.Define( - {.ir_name = "value_param_pattern", - .constant_kind = InstConstantKind::AlwaysUnique, - .is_lowered = false}); - - TypeId type_id; - InstId subpattern_id; - CallParamIndex index; -}; - // The type of a pattern that matches scrutinees of type // `scrutinee_type_inst_id`. struct PatternType { @@ -1375,6 +1172,31 @@ struct RefineTypeAction { TypeInstId inst_type_inst_id; }; +// A by-reference `Call` parameter. See AnyParam for member documentation. +struct RefParam { + // TODO: Make Parse::NodeId more specific. + static constexpr auto Kind = InstKind::RefParam.Define( + {.ir_name = "ref_param", .constant_kind = InstConstantKind::Never}); + + TypeId type_id; + CallParamIndex index; + NameId pretty_name_id; +}; + +// A pattern that represents a by-reference `Call` parameter. See +// `AnyParamPattern` for member documentation. +struct RefParamPattern { + // TODO: Make Parse::NodeId more specific. + static constexpr auto Kind = InstKind::RefParamPattern.Define( + {.ir_name = "ref_param_pattern", + .constant_kind = InstConstantKind::AlwaysUnique, + .is_lowered = false}); + + TypeId type_id; + InstId subpattern_id; + CallParamIndex index; +}; + // Requires a type to be complete. This is only created for generic types and // produces a witness that the type is complete. // @@ -1395,6 +1217,45 @@ struct RequireCompleteType { TypeInstId complete_type_inst_id; }; +// An `expr == expr` clause in a `where` expression or `require` declaration. +struct RequirementEquivalent { + static constexpr auto Kind = + InstKind::RequirementEquivalent.Define( + {.ir_name = "requirement_equivalent", + .constant_kind = InstConstantKind::Never, + .is_lowered = false}); + + // No type since not an expression + InstId lhs_id; + InstId rhs_id; +}; + +// An `expr impls expr` clause in a `where` expression or `require` declaration. +struct RequirementImpls { + static constexpr auto Kind = + InstKind::RequirementImpls.Define( + {.ir_name = "requirement_impls", + .constant_kind = InstConstantKind::Never, + .is_lowered = false}); + + // No type since not an expression + InstId lhs_id; + InstId rhs_id; +}; + +// A `.M = expr` clause in a `where` expression or `require` declaration. +struct RequirementRewrite { + static constexpr auto Kind = + InstKind::RequirementRewrite.Define( + {.ir_name = "requirement_rewrite", + .constant_kind = InstConstantKind::Never, + .is_lowered = false}); + + // No type since not an expression + InstId lhs_id; + InstId rhs_id; +}; + struct Return { static constexpr auto Kind = InstKind::Return.Define( {.ir_name = "return", @@ -1457,45 +1318,6 @@ struct ReturnSlotPattern { TypeInstId type_inst_id; }; -// An `expr == expr` clause in a `where` expression or `require` declaration. -struct RequirementEquivalent { - static constexpr auto Kind = - InstKind::RequirementEquivalent.Define( - {.ir_name = "requirement_equivalent", - .constant_kind = InstConstantKind::Never, - .is_lowered = false}); - - // No type since not an expression - InstId lhs_id; - InstId rhs_id; -}; - -// An `expr impls expr` clause in a `where` expression or `require` declaration. -struct RequirementImpls { - static constexpr auto Kind = - InstKind::RequirementImpls.Define( - {.ir_name = "requirement_impls", - .constant_kind = InstConstantKind::Never, - .is_lowered = false}); - - // No type since not an expression - InstId lhs_id; - InstId rhs_id; -}; - -// A `.M = expr` clause in a `where` expression or `require` declaration. -struct RequirementRewrite { - static constexpr auto Kind = - InstKind::RequirementRewrite.Define( - {.ir_name = "requirement_rewrite", - .constant_kind = InstConstantKind::Never, - .is_lowered = false}); - - // No type since not an expression - InstId lhs_id; - InstId rhs_id; -}; - // Given an instruction with a constant value that depends on a generic // parameter, selects a version of that instruction with the constant value // corresponding to a particular specific. @@ -1682,6 +1504,20 @@ struct StructValue { InstBlockId elements_id; }; +// Represents a symbolic binding pattern. See `AnyBindingPattern` for member +// documentation. +struct SymbolicBindingPattern { + static constexpr auto Kind = + InstKind::SymbolicBindingPattern.Define({ + .ir_name = "symbolic_binding_pattern", + .constant_kind = InstConstantKind::AlwaysUnique, + .is_lowered = false, + }); + + TypeId type_id; + EntityNameId entity_name_id; +}; + // A temporary value. struct Temporary { static constexpr auto Kind = @@ -1858,6 +1694,32 @@ struct ValueOfInitializer { InstId init_id; }; +// A by-value `Call` parameter. See AnyParam for member documentation. +struct ValueParam { + // TODO: Make Parse::NodeId more specific. + static constexpr auto Kind = InstKind::ValueParam.Define( + {.ir_name = "value_param", .constant_kind = InstConstantKind::Never}); + + TypeId type_id; + CallParamIndex index; + NameId pretty_name_id; +}; + +// A pattern that represents a by-value `Call` parameter. See `AnyParamPattern` +// for member documentation. +struct ValueParamPattern { + // TODO: Make Parse::NodeId more specific. + static constexpr auto Kind = + InstKind::ValueParamPattern.Define( + {.ir_name = "value_param_pattern", + .constant_kind = InstConstantKind::AlwaysUnique, + .is_lowered = false}); + + TypeId type_id; + InstId subpattern_id; + CallParamIndex index; +}; + // A `var` pattern. struct VarPattern { static constexpr auto Kind = @@ -1887,6 +1749,24 @@ struct VarStorage { AbsoluteInstId pattern_id; }; +// Definition of ABI-neutral vtable information for a dynamic class. +struct Vtable { + static constexpr auto Kind = InstKind::Vtable.Define( + {.ir_name = "vtable", + .constant_kind = InstConstantKind::Always, + .is_lowered = false}); + TypeId type_id; + InstBlockId virtual_functions_id; +}; + +// Initializer for virtual function table pointers in object initialization. +struct VtablePtr { + static constexpr auto Kind = InstKind::VtablePtr.Define( + {.ir_name = "vtable_ptr", .constant_kind = InstConstantKind::Never}); + TypeId type_id; + InstId vtable_id; +}; + // The type of virtual function tables. struct VtableType { static constexpr auto Kind = InstKind::VtableType.Define( @@ -1900,24 +1780,6 @@ struct VtableType { TypeId type_id; }; -// Initializer for virtual function table pointers in object initialization. -struct VtablePtr { - static constexpr auto Kind = InstKind::VtablePtr.Define( - {.ir_name = "vtable_ptr", .constant_kind = InstConstantKind::Never}); - TypeId type_id; - InstId vtable_id; -}; - -// Definition of ABI-neutral vtable information for a dynamic class. -struct Vtable { - static constexpr auto Kind = InstKind::Vtable.Define( - {.ir_name = "vtable", - .constant_kind = InstConstantKind::Always, - .is_lowered = false}); - TypeId type_id; - InstBlockId virtual_functions_id; -}; - // An `expr where requirements` expression. struct WhereExpr { static constexpr auto Kind = InstKind::WhereExpr.Define(