|
|
@@ -5,6 +5,7 @@
|
|
|
#ifndef CARBON_TOOLCHAIN_SEM_IR_TYPED_INSTS_H_
|
|
|
#define CARBON_TOOLCHAIN_SEM_IR_TYPED_INSTS_H_
|
|
|
|
|
|
+#include "common/template_string.h"
|
|
|
#include "toolchain/base/int.h"
|
|
|
#include "toolchain/parse/node_ids.h"
|
|
|
#include "toolchain/parse/typed_nodes.h"
|
|
|
@@ -51,6 +52,24 @@
|
|
|
|
|
|
namespace Carbon::SemIR {
|
|
|
|
|
|
+// A template for singleton types.
|
|
|
+template <InstKind::RawEnumType KindT, TemplateString IrName>
|
|
|
+struct SingletonTypeInst final {
|
|
|
+ static constexpr auto Kind = InstKind::Make(KindT).Define<Parse::NoneNodeId>(
|
|
|
+ InstKind::DefinitionInfo{.ir_name = IrName,
|
|
|
+ .is_type = InstIsType::Always,
|
|
|
+ .constant_kind = InstConstantKind::Always});
|
|
|
+ static constexpr auto TypeInstId = MakeSingletonTypeInstId<Kind>();
|
|
|
+ static constexpr SemIR::InstId InstId = TypeInstId;
|
|
|
+ static constexpr auto ConstantId = ConstantId::ForConcreteConstant(InstId);
|
|
|
+ static constexpr auto TypeId =
|
|
|
+ TypeId::ForTypeConstant(ConstantId::ForConcreteConstant(TypeInstId));
|
|
|
+
|
|
|
+ // Singleton types have a type of `TypeType`, except for `ErrorInst` which
|
|
|
+ // uses itself.
|
|
|
+ SemIR::TypeId type_id;
|
|
|
+};
|
|
|
+
|
|
|
// An action that performs simple member access, `base.name`.
|
|
|
struct AccessMemberAction {
|
|
|
static constexpr auto Kind =
|
|
|
@@ -247,17 +266,7 @@ struct AssociatedEntityType {
|
|
|
};
|
|
|
|
|
|
// Used for the type of patterns that do not match a fixed type.
|
|
|
-struct AutoType {
|
|
|
- static constexpr auto Kind = InstKind::AutoType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "auto",
|
|
|
- .is_type = InstIsType::Always,
|
|
|
- .constant_kind = InstConstantKind::Always});
|
|
|
- static constexpr auto TypeInstId = MakeSingletonTypeInstId<Kind>();
|
|
|
- static constexpr auto TypeId =
|
|
|
- TypeId::ForTypeConstant(ConstantId::ForConcreteConstant(TypeInstId));
|
|
|
-
|
|
|
- SemIR::TypeId type_id;
|
|
|
-};
|
|
|
+using AutoType = SingletonTypeInst<InstKind::AutoType, "auto">;
|
|
|
|
|
|
// A base in a class, of the form `base: base_type;`. A base class is an
|
|
|
// element of the derived class, and the type of the `BaseDecl` instruction is
|
|
|
@@ -292,17 +301,10 @@ struct BoolLiteral {
|
|
|
};
|
|
|
|
|
|
// The type of bool literals and branch conditions, bool.
|
|
|
-struct BoolType {
|
|
|
- static constexpr auto Kind = InstKind::BoolType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "bool",
|
|
|
- .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<Kind>();
|
|
|
-
|
|
|
- TypeId type_id;
|
|
|
-};
|
|
|
+//
|
|
|
+// This is a singleton instruction. However, it may still evolve into a more
|
|
|
+// standard type and be removed.
|
|
|
+using BoolType = SingletonTypeInst<InstKind::BoolType, "bool">;
|
|
|
|
|
|
// For member access such as `object.MethodName`, combines a member function
|
|
|
// with the value to use for `self`. This is a callable structure; `Call` will
|
|
|
@@ -322,18 +324,11 @@ struct BoundMethod {
|
|
|
};
|
|
|
|
|
|
// The type of bound method values.
|
|
|
-struct BoundMethodType {
|
|
|
- static constexpr auto Kind =
|
|
|
- InstKind::BoundMethodType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "<bound method>",
|
|
|
- .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<Kind>();
|
|
|
-
|
|
|
- TypeId type_id;
|
|
|
-};
|
|
|
+//
|
|
|
+// This is a singleton instruction. However, it may still evolve into a more
|
|
|
+// standard type and be removed.
|
|
|
+using BoundMethodType =
|
|
|
+ SingletonTypeInst<InstKind::BoundMethodType, "<bound method>">;
|
|
|
|
|
|
// Control flow to branch to the target block.
|
|
|
struct Branch {
|
|
|
@@ -394,20 +389,11 @@ struct Call {
|
|
|
|
|
|
// A unicode code point character literal. This type only provides compile-time
|
|
|
// operations, and is represented as an empty type at runtime.
|
|
|
-struct CharLiteralType {
|
|
|
- static constexpr auto Kind =
|
|
|
- InstKind::CharLiteralType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "Core.CharLiteral",
|
|
|
- .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<Kind>();
|
|
|
- static constexpr auto TypeId =
|
|
|
- TypeId::ForTypeConstant(ConstantId::ForConcreteConstant(TypeInstId));
|
|
|
-
|
|
|
- SemIR::TypeId type_id;
|
|
|
-};
|
|
|
+//
|
|
|
+// This is a singleton instruction. However, it may still evolve into a more
|
|
|
+// standard type and be removed.
|
|
|
+using CharLiteralType =
|
|
|
+ SingletonTypeInst<InstKind::CharLiteralType, "Core.CharLiteral">;
|
|
|
|
|
|
// A unicode code point character value, whose type is `CharLiteralType`.
|
|
|
struct CharLiteralValue {
|
|
|
@@ -586,18 +572,7 @@ struct Deref {
|
|
|
// required. For example, when there is a type checking issue, this will be used
|
|
|
// in the type_id. It's typically used as a cue that semantic checking doesn't
|
|
|
// need to issue further diagnostics.
|
|
|
-struct ErrorInst {
|
|
|
- static constexpr auto Kind = InstKind::ErrorInst.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "<error>",
|
|
|
- .is_type = InstIsType::Always,
|
|
|
- .constant_kind = InstConstantKind::Always});
|
|
|
- static constexpr auto TypeInstId = MakeSingletonTypeInstId<Kind>();
|
|
|
- static constexpr SemIR::InstId InstId = TypeInstId;
|
|
|
- static constexpr auto ConstantId = ConstantId::ForConcreteConstant(InstId);
|
|
|
- static constexpr auto TypeId = TypeId::ForTypeConstant(ConstantId);
|
|
|
-
|
|
|
- SemIR::TypeId type_id;
|
|
|
-};
|
|
|
+using ErrorInst = SingletonTypeInst<InstKind::ErrorInst, "<error>">;
|
|
|
|
|
|
// An `export bind_name` declaration.
|
|
|
struct ExportDecl {
|
|
|
@@ -677,18 +652,11 @@ struct FieldDecl {
|
|
|
|
|
|
// The float literal type.
|
|
|
// TODO: Replace this with a rational number type, following the design.
|
|
|
-struct FloatLiteralType {
|
|
|
- static constexpr auto Kind =
|
|
|
- InstKind::FloatLiteralType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "Core.FloatLiteral",
|
|
|
- .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<Kind>();
|
|
|
-
|
|
|
- TypeId type_id;
|
|
|
-};
|
|
|
+//
|
|
|
+// This is a singleton instruction. However, it may still evolve into a more
|
|
|
+// standard type and be removed.
|
|
|
+using FloatLiteralType =
|
|
|
+ SingletonTypeInst<InstKind::FloatLiteralType, "Core.FloatLiteral">;
|
|
|
|
|
|
// A floating point literal value.
|
|
|
// TODO: Eventually this should be represented as a rational number, and should
|
|
|
@@ -1076,17 +1044,7 @@ struct InitializeFrom {
|
|
|
};
|
|
|
|
|
|
// Used as the type of template actions that produce instructions.
|
|
|
-struct InstType {
|
|
|
- static constexpr auto Kind = InstKind::InstType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "<instruction>",
|
|
|
- .is_type = InstIsType::Always,
|
|
|
- .constant_kind = InstConstantKind::Always});
|
|
|
- static constexpr auto TypeInstId = MakeSingletonTypeInstId<Kind>();
|
|
|
- static constexpr auto TypeId =
|
|
|
- TypeId::ForTypeConstant(ConstantId::ForConcreteConstant(TypeInstId));
|
|
|
-
|
|
|
- SemIR::TypeId type_id;
|
|
|
-};
|
|
|
+using InstType = SingletonTypeInst<InstKind::InstType, "<instruction>">;
|
|
|
|
|
|
// A value of type `InstType` that refers to an instruction. This is used to
|
|
|
// represent an instruction as a value for use as a result of a template action.
|
|
|
@@ -1119,18 +1077,11 @@ struct InterfaceDecl {
|
|
|
// 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
|
|
|
// runtime.
|
|
|
-struct IntLiteralType {
|
|
|
- static constexpr auto Kind =
|
|
|
- InstKind::IntLiteralType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "Core.IntLiteral",
|
|
|
- .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<Kind>();
|
|
|
-
|
|
|
- TypeId type_id;
|
|
|
-};
|
|
|
+//
|
|
|
+// This is a singleton instruction. However, it may still evolve into a more
|
|
|
+// standard type and be removed.
|
|
|
+using IntLiteralType =
|
|
|
+ SingletonTypeInst<InstKind::IntLiteralType, "Core.IntLiteral">;
|
|
|
|
|
|
// A primitive integer type whose representation and operations are defined by
|
|
|
// the toolchain. The `Core.Int` and `Core.UInt` classes are defined as adapters
|
|
|
@@ -1259,18 +1210,10 @@ struct Namespace {
|
|
|
};
|
|
|
|
|
|
// The type of namespace and imported package names.
|
|
|
-struct NamespaceType {
|
|
|
- static constexpr auto Kind =
|
|
|
- InstKind::NamespaceType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "<namespace>",
|
|
|
- .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<Kind>();
|
|
|
-
|
|
|
- TypeId type_id;
|
|
|
-};
|
|
|
+//
|
|
|
+// This is a singleton instruction. However, it may still evolve into a more
|
|
|
+// standard type and be removed.
|
|
|
+using NamespaceType = SingletonTypeInst<InstKind::NamespaceType, "<namespace>">;
|
|
|
|
|
|
// An output `Call` parameter. See AnyParam for member documentation.
|
|
|
struct OutParam {
|
|
|
@@ -1575,18 +1518,11 @@ struct SpecificFunction {
|
|
|
};
|
|
|
|
|
|
// The type of specific functions.
|
|
|
-struct SpecificFunctionType {
|
|
|
- static constexpr auto Kind =
|
|
|
- InstKind::SpecificFunctionType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "<specific function>",
|
|
|
- .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<Kind>();
|
|
|
-
|
|
|
- TypeId type_id;
|
|
|
-};
|
|
|
+//
|
|
|
+// This is a singleton instruction. However, it may still evolve into a more
|
|
|
+// standard type and be removed.
|
|
|
+using SpecificFunctionType =
|
|
|
+ SingletonTypeInst<InstKind::SpecificFunctionType, "<specific function>">;
|
|
|
|
|
|
// A specific instance of a function from an impl, named as the function from
|
|
|
// the interface.
|
|
|
@@ -1863,17 +1799,7 @@ struct TypeOfInst {
|
|
|
|
|
|
// Tracks expressions which are valid as types. This has a deliberately
|
|
|
// self-referential type.
|
|
|
-struct TypeType {
|
|
|
- static constexpr auto Kind = InstKind::TypeType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "type",
|
|
|
- .is_type = InstIsType::Always,
|
|
|
- .constant_kind = InstConstantKind::Always});
|
|
|
- static constexpr auto TypeInstId = MakeSingletonTypeInstId<Kind>();
|
|
|
- static constexpr auto TypeId =
|
|
|
- TypeId::ForTypeConstant(ConstantId::ForConcreteConstant(TypeInstId));
|
|
|
-
|
|
|
- SemIR::TypeId type_id;
|
|
|
-};
|
|
|
+using TypeType = SingletonTypeInst<InstKind::TypeType, "type">;
|
|
|
|
|
|
// The `not` operator, such as `not operand`.
|
|
|
struct UnaryOperatorNot {
|
|
|
@@ -2010,17 +1936,10 @@ struct VarStorage {
|
|
|
};
|
|
|
|
|
|
// The type of virtual function tables.
|
|
|
-struct VtableType {
|
|
|
- static constexpr auto Kind = InstKind::VtableType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "<vtable>",
|
|
|
- .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<Kind>();
|
|
|
-
|
|
|
- TypeId type_id;
|
|
|
-};
|
|
|
+//
|
|
|
+// This is a singleton instruction. However, it may still evolve into a more
|
|
|
+// standard type and be removed.
|
|
|
+using VtableType = SingletonTypeInst<InstKind::VtableType, "<vtable>">;
|
|
|
|
|
|
// Initializer for virtual function table pointers in object initialization.
|
|
|
struct VtablePtr {
|
|
|
@@ -2059,17 +1978,10 @@ struct WhereExpr {
|
|
|
// their types should not change in the process.
|
|
|
//
|
|
|
// Also the type of `RequireCompleteType` instructions.
|
|
|
-struct WitnessType {
|
|
|
- static constexpr auto Kind = InstKind::WitnessType.Define<Parse::NoneNodeId>(
|
|
|
- {.ir_name = "<witness>",
|
|
|
- .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<Kind>();
|
|
|
-
|
|
|
- TypeId type_id;
|
|
|
-};
|
|
|
+//
|
|
|
+// This is a singleton instruction. However, it may still evolve into a more
|
|
|
+// standard type and be removed.
|
|
|
+using WitnessType = SingletonTypeInst<InstKind::WitnessType, "<witness>">;
|
|
|
|
|
|
// These concepts are an implementation detail of the library, not public API.
|
|
|
namespace Internal {
|