ids.h 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_SEM_IR_IDS_H_
  5. #define CARBON_TOOLCHAIN_SEM_IR_IDS_H_
  6. #include <limits>
  7. #include "common/check.h"
  8. #include "common/ostream.h"
  9. #include "toolchain/base/index_base.h"
  10. #include "toolchain/base/value_ids.h"
  11. #include "toolchain/diagnostics/diagnostic_emitter.h"
  12. #include "toolchain/parse/node_ids.h"
  13. namespace Carbon::SemIR {
  14. // TODO: This is in use, but not here.
  15. class File;
  16. // The ID of an `Inst`.
  17. struct InstId : public IdBase<InstId> {
  18. static constexpr llvm::StringLiteral Label = "inst";
  19. // The maximum ID, inclusive.
  20. static constexpr int Max = std::numeric_limits<int32_t>::max();
  21. // Represents the result of a name lookup that is temporarily disallowed
  22. // because the name is currently being initialized.
  23. static const InstId InitTombstone;
  24. using IdBase::IdBase;
  25. auto Print(llvm::raw_ostream& out) const -> void;
  26. };
  27. constexpr InstId InstId::InitTombstone = InstId(NoneIndex - 1);
  28. // An InstId whose value is a type. The fact it's a type is CHECKed on
  29. // construction, and this allows that check to be represented in the type
  30. // system.
  31. struct TypeInstId : public InstId {
  32. static constexpr llvm::StringLiteral Label = "type_inst";
  33. static const TypeInstId None;
  34. using InstId::InstId;
  35. static constexpr auto UnsafeMake(InstId id) -> TypeInstId {
  36. return TypeInstId(UnsafeCtor(), id);
  37. }
  38. private:
  39. struct UnsafeCtor {};
  40. explicit constexpr TypeInstId(UnsafeCtor /*unsafe*/, InstId id)
  41. : InstId(id) {}
  42. };
  43. constexpr TypeInstId TypeInstId::None = TypeInstId::UnsafeMake(InstId::None);
  44. // An ID of an instruction that is referenced absolutely by another instruction.
  45. // This should only be used as the type of a field within a typed instruction
  46. // class.
  47. //
  48. // When a typed instruction has a field of this type, that field represents an
  49. // absolute reference to another instruction that typically resides in a
  50. // different entity. This behaves in most respects like an InstId field, but
  51. // substitution into the typed instruction leaves the field unchanged rather
  52. // than substituting into it.
  53. class AbsoluteInstId : public InstId {
  54. public:
  55. static constexpr llvm::StringLiteral Label = "absolute_inst";
  56. // Support implicit conversion from InstId so that InstId and AbsoluteInstId
  57. // have the same interface.
  58. // NOLINTNEXTLINE(google-explicit-constructor)
  59. constexpr AbsoluteInstId(InstId inst_id) : InstId(inst_id) {}
  60. using InstId::InstId;
  61. };
  62. // An ID of an instruction that is used as the destination of an initializing
  63. // expression. This should only be used as the type of a field within a typed
  64. // instruction class.
  65. //
  66. // This behaves in most respects like an InstId field, but constant evaluation
  67. // of an instruction with a destination field will not evaluate this field, and
  68. // substitution will not substitute into it.
  69. //
  70. // TODO: Decide on how substitution should handle this. Multiple instructions
  71. // can refer to the same destination, so these don't have the tree structure
  72. // that substitution expects, but we might need to substitute into the result of
  73. // an instruction.
  74. class DestInstId : public InstId {
  75. public:
  76. static constexpr llvm::StringLiteral Label = "dest_inst";
  77. // Support implicit conversion from InstId so that InstId and DestInstId
  78. // have the same interface.
  79. // NOLINTNEXTLINE(google-explicit-constructor)
  80. constexpr DestInstId(InstId inst_id) : InstId(inst_id) {}
  81. using InstId::InstId;
  82. };
  83. // An ID of an instruction that is referenced as a meta-operand of an action.
  84. // This should only be used as the type of a field within a typed instruction
  85. // class.
  86. //
  87. // This is used to model cases where an action's operand is not the value
  88. // produced by another instruction, but is the other instruction itself. This is
  89. // common for actions representing template instantiation.
  90. //
  91. // This behaves in most respects like an InstId field, but evaluation of the
  92. // instruction that has this field will not fail if the instruction does not
  93. // have a constant value. If the instruction has a constant value, it will still
  94. // be replaced by its constant value during evaluation like normal, but if it
  95. // has a non-constant value, the field is left unchanged by evaluation.
  96. class MetaInstId : public InstId {
  97. public:
  98. static constexpr llvm::StringLiteral Label = "meta_inst";
  99. // Support implicit conversion from InstId so that InstId and MetaInstId
  100. // have the same interface.
  101. // NOLINTNEXTLINE(google-explicit-constructor)
  102. constexpr MetaInstId(InstId inst_id) : InstId(inst_id) {}
  103. using InstId::InstId;
  104. };
  105. // The ID of a constant value of an expression. An expression is either:
  106. //
  107. // - a concrete constant, whose value does not depend on any generic parameters,
  108. // such as `42` or `i32*` or `("hello", "world")`, or
  109. // - a symbolic constant, whose value includes a generic parameter, such as
  110. // `Vector(T*)`, or
  111. // - a runtime expression, such as `Print("hello")`.
  112. //
  113. // Concrete constants are a thin wrapper around the instruction ID of the
  114. // constant instruction that defines the constant. Symbolic constants are an
  115. // index into a separate table of `SymbolicConstant`s maintained by the constant
  116. // value store.
  117. struct ConstantId : public IdBase<ConstantId> {
  118. static constexpr llvm::StringLiteral Label = "constant";
  119. // An ID for an expression that is not constant.
  120. static const ConstantId NotConstant;
  121. // Returns the constant ID corresponding to a concrete constant, which should
  122. // either be in the `constants` block in the file or should be known to be
  123. // unique.
  124. static constexpr auto ForConcreteConstant(InstId const_id) -> ConstantId {
  125. return ConstantId(const_id.index);
  126. }
  127. using IdBase::IdBase;
  128. // Returns whether this represents a constant. Requires has_value.
  129. constexpr auto is_constant() const -> bool {
  130. CARBON_DCHECK(has_value());
  131. return *this != ConstantId::NotConstant;
  132. }
  133. // Returns whether this represents a symbolic constant. Requires has_value.
  134. constexpr auto is_symbolic() const -> bool {
  135. CARBON_DCHECK(has_value());
  136. return index <= FirstSymbolicId;
  137. }
  138. // Returns whether this represents a concrete constant. Requires has_value.
  139. constexpr auto is_concrete() const -> bool {
  140. CARBON_DCHECK(has_value());
  141. return index >= 0;
  142. }
  143. // Prints this ID to the given output stream. `disambiguate` indicates whether
  144. // concrete constants should be wrapped with "concrete_constant(...)" so that
  145. // they aren't printed the same as an InstId. This can be set to false if
  146. // there is no risk of ambiguity.
  147. auto Print(llvm::raw_ostream& out, bool disambiguate = true) const -> void;
  148. private:
  149. friend class ConstantValueStore;
  150. // For Dump.
  151. friend auto MakeSymbolicConstantId(int id) -> ConstantId;
  152. // A symbolic constant.
  153. struct SymbolicId : public IdBase<SymbolicId> {
  154. static constexpr llvm::StringLiteral Label = "symbolic_constant";
  155. using IdBase::IdBase;
  156. };
  157. // Returns the constant ID corresponding to a symbolic constant index.
  158. static constexpr auto ForSymbolicConstantId(SymbolicId symbolic_id)
  159. -> ConstantId {
  160. return ConstantId(FirstSymbolicId - symbolic_id.index);
  161. }
  162. // TODO: C++23 makes std::abs constexpr, but until then we mirror std::abs
  163. // logic here. LLVM should still optimize this.
  164. static constexpr auto Abs(int32_t i) -> int32_t { return i > 0 ? i : -i; }
  165. // Returns the instruction that describes this concrete constant value.
  166. // Requires `is_concrete()`. Use `ConstantValueStore::GetInstId` to get the
  167. // instruction ID of a `ConstantId`.
  168. constexpr auto concrete_inst_id() const -> InstId {
  169. CARBON_DCHECK(is_concrete());
  170. return InstId(index);
  171. }
  172. // Returns the symbolic constant index that describes this symbolic constant
  173. // value. Requires `is_symbolic()`.
  174. constexpr auto symbolic_id() const -> SymbolicId {
  175. CARBON_DCHECK(is_symbolic());
  176. return SymbolicId(FirstSymbolicId - index);
  177. }
  178. static constexpr int32_t NotConstantIndex = NoneIndex - 1;
  179. static constexpr int32_t FirstSymbolicId = NoneIndex - 2;
  180. };
  181. constexpr ConstantId ConstantId::NotConstant = ConstantId(NotConstantIndex);
  182. // The ID of a `EntityName`.
  183. struct EntityNameId : public IdBase<EntityNameId> {
  184. static constexpr llvm::StringLiteral Label = "entity_name";
  185. using IdBase::IdBase;
  186. };
  187. // The index of a compile-time binding. This is the de Bruijn level for the
  188. // binding -- that is, this is the number of other compile time bindings whose
  189. // scope encloses this binding.
  190. struct CompileTimeBindIndex : public IndexBase<CompileTimeBindIndex> {
  191. static constexpr llvm::StringLiteral Label = "comp_time_bind";
  192. using IndexBase::IndexBase;
  193. };
  194. // The index of a `Call` parameter in a function. These are allocated
  195. // sequentially, left-to-right, to the function parameters that will have
  196. // arguments passed to them at runtime. In a `Call` instruction, a runtime
  197. // argument will have the position in the argument list corresponding to its
  198. // `Call` parameter index.
  199. struct CallParamIndex : public IndexBase<CallParamIndex> {
  200. static constexpr llvm::StringLiteral Label = "call_param";
  201. using IndexBase::IndexBase;
  202. };
  203. // The ID of a `Function`.
  204. struct FunctionId : public IdBase<FunctionId> {
  205. static constexpr llvm::StringLiteral Label = "function";
  206. using IdBase::IdBase;
  207. };
  208. // The ID of an IR within the set of all IRs being evaluated in the current
  209. // check execution.
  210. struct CheckIRId : public IdBase<CheckIRId> {
  211. static constexpr llvm::StringLiteral Label = "check_ir";
  212. // Used when referring to the imported C++.
  213. static const CheckIRId Cpp;
  214. using IdBase::IdBase;
  215. };
  216. constexpr CheckIRId CheckIRId::Cpp = CheckIRId(NoneIndex - 1);
  217. // The ID of a `Class`.
  218. struct ClassId : public IdBase<ClassId> {
  219. static constexpr llvm::StringLiteral Label = "class";
  220. using IdBase::IdBase;
  221. };
  222. // The ID of a `Vtable`.
  223. struct VtableId : public IdBase<VtableId> {
  224. static constexpr llvm::StringLiteral Label = "vtable";
  225. using IdBase::IdBase;
  226. };
  227. // The ID of an `Interface`.
  228. struct InterfaceId : public IdBase<InterfaceId> {
  229. static constexpr llvm::StringLiteral Label = "interface";
  230. using IdBase::IdBase;
  231. };
  232. // The ID of an `AssociatedConstant`.
  233. struct AssociatedConstantId : public IdBase<AssociatedConstantId> {
  234. static constexpr llvm::StringLiteral Label = "assoc_const";
  235. using IdBase::IdBase;
  236. };
  237. // The ID of a `FacetTypeInfo`.
  238. struct FacetTypeId : public IdBase<FacetTypeId> {
  239. static constexpr llvm::StringLiteral Label = "facet_type";
  240. using IdBase::IdBase;
  241. };
  242. // The ID of an resolved facet type value.
  243. struct IdentifiedFacetTypeId : public IdBase<IdentifiedFacetTypeId> {
  244. static constexpr llvm::StringLiteral Label = "identified_facet_type";
  245. using IdBase::IdBase;
  246. };
  247. // The ID of an `Impl`.
  248. struct ImplId : public IdBase<ImplId> {
  249. using DiagnosticType = Diagnostics::TypeInfo<std::string>;
  250. static constexpr llvm::StringLiteral Label = "impl";
  251. using IdBase::IdBase;
  252. };
  253. // The ID of a `Generic`.
  254. struct GenericId : public IdBase<GenericId> {
  255. static constexpr llvm::StringLiteral Label = "generic";
  256. using IdBase::IdBase;
  257. };
  258. // The ID of a `Specific`, which is the result of specifying the generic
  259. // arguments for a generic.
  260. struct SpecificId : public IdBase<SpecificId> {
  261. using DiagnosticType = Diagnostics::TypeInfo<std::string>;
  262. static constexpr llvm::StringLiteral Label = "specific";
  263. using IdBase::IdBase;
  264. };
  265. // The ID of a `SpecificInterface`, which is an interface and a specific pair.
  266. struct SpecificInterfaceId : public IdBase<SpecificInterfaceId> {
  267. using DiagnosticType = Diagnostics::TypeInfo<std::string>;
  268. static constexpr llvm::StringLiteral Label = "specific_interface";
  269. using IdBase::IdBase;
  270. };
  271. // The index of an instruction that depends on generic parameters within a
  272. // region of a generic. A corresponding specific version of the instruction can
  273. // be found in each specific corresponding to that generic. This is a pair of a
  274. // region and an index, stored in 32 bits.
  275. struct GenericInstIndex : public IndexBase<GenericInstIndex> {
  276. // Where the value is first used within the generic.
  277. enum Region : uint8_t {
  278. // In the declaration.
  279. Declaration,
  280. // In the definition.
  281. Definition,
  282. };
  283. // An index with no value.
  284. static const GenericInstIndex None;
  285. explicit constexpr GenericInstIndex(Region region, int32_t index)
  286. : IndexBase(region == Declaration ? index
  287. : FirstDefinitionIndex - index) {
  288. CARBON_CHECK(index >= 0);
  289. }
  290. // Returns the index of the instruction within the region.
  291. auto index() const -> int32_t {
  292. CARBON_CHECK(has_value());
  293. return IndexBase::index >= 0 ? IndexBase::index
  294. : FirstDefinitionIndex - IndexBase::index;
  295. }
  296. // Returns the region within which this instruction was first used.
  297. auto region() const -> Region {
  298. CARBON_CHECK(has_value());
  299. return IndexBase::index >= 0 ? Declaration : Definition;
  300. }
  301. auto Print(llvm::raw_ostream& out) const -> void;
  302. private:
  303. static constexpr auto MakeNone() -> GenericInstIndex {
  304. GenericInstIndex result(Declaration, 0);
  305. result.IndexBase::index = NoneIndex;
  306. return result;
  307. }
  308. static constexpr int32_t FirstDefinitionIndex = NoneIndex - 1;
  309. };
  310. constexpr GenericInstIndex GenericInstIndex::None =
  311. GenericInstIndex::MakeNone();
  312. // The ID of an `ImportCpp`.
  313. struct ImportCppId : public IdBase<ImportCppId> {
  314. static constexpr llvm::StringLiteral Label = "import_cpp";
  315. using IdBase::IdBase;
  316. };
  317. // The ID of an `ImportIR` within the set of imported IRs, both direct and
  318. // indirect.
  319. struct ImportIRId : public IdBase<ImportIRId> {
  320. static constexpr llvm::StringLiteral Label = "ir";
  321. // The implicit `api` import, for an `impl` file. A null entry is added if
  322. // there is none, as in an `api`, in which case this ID should not show up in
  323. // instructions.
  324. static const ImportIRId ApiForImpl;
  325. // The `Cpp` import. A null entry is added if there is none, in which case
  326. // this ID should not show up in instructions.
  327. static const ImportIRId Cpp;
  328. using IdBase::IdBase;
  329. };
  330. constexpr ImportIRId ImportIRId::ApiForImpl = ImportIRId(0);
  331. constexpr ImportIRId ImportIRId::Cpp = ImportIRId(ApiForImpl.index + 1);
  332. // A boolean value.
  333. struct BoolValue : public IdBase<BoolValue> {
  334. // Not used by `Print`, but for `IdKind`.
  335. static constexpr llvm::StringLiteral Label = "bool";
  336. static const BoolValue False;
  337. static const BoolValue True;
  338. // Returns the `BoolValue` corresponding to `b`.
  339. static constexpr auto From(bool b) -> BoolValue { return b ? True : False; }
  340. // Returns the `bool` corresponding to this `BoolValue`.
  341. constexpr auto ToBool() -> bool {
  342. CARBON_CHECK(*this == False || *this == True, "Invalid bool value {0}",
  343. index);
  344. return *this != False;
  345. }
  346. using IdBase::IdBase;
  347. auto Print(llvm::raw_ostream& out) const -> void;
  348. };
  349. constexpr BoolValue BoolValue::False = BoolValue(0);
  350. constexpr BoolValue BoolValue::True = BoolValue(1);
  351. // An integer kind value -- either "signed" or "unsigned".
  352. //
  353. // This might eventually capture any other properties of an integer type that
  354. // affect its semantics, such as overflow behavior.
  355. struct IntKind : public IdBase<IntKind> {
  356. // Not used by `Print`, but for `IdKind`.
  357. static constexpr llvm::StringLiteral Label = "int_kind";
  358. static const IntKind Unsigned;
  359. static const IntKind Signed;
  360. using IdBase::IdBase;
  361. // Returns whether this type is signed.
  362. constexpr auto is_signed() -> bool { return *this == Signed; }
  363. auto Print(llvm::raw_ostream& out) const -> void;
  364. };
  365. constexpr IntKind IntKind::Unsigned = IntKind(0);
  366. constexpr IntKind IntKind::Signed = IntKind(1);
  367. // A float kind value.
  368. struct FloatKind : public IdBase<FloatKind> {
  369. // Not used by `Print`, but for `IdKind`.
  370. static constexpr llvm::StringLiteral Label = "float_kind";
  371. using IdBase::IdBase;
  372. auto Print(llvm::raw_ostream& out) const -> void { out << "float"; }
  373. };
  374. // An X-macro for special names. Uses should look like:
  375. //
  376. // #define CARBON_SPECIAL_NAME_ID_FOR_XYZ(Name) ...
  377. // CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_XYZ)
  378. // #undef CARBON_SPECIAL_NAME_ID_FOR_XYZ
  379. #define CARBON_SPECIAL_NAME_ID(X) \
  380. /* The name of `base`. */ \
  381. X(Base) \
  382. /* The name of the discriminant field (if any) in a choice. */ \
  383. X(ChoiceDiscriminant) \
  384. /* The name of the package `Core`. */ \
  385. X(Core) \
  386. /* The name of `destroy`. */ \
  387. X(Destroy) \
  388. /* The name of `package`. */ \
  389. X(PackageNamespace) \
  390. /* The name of `.Self`. */ \
  391. X(PeriodSelf) \
  392. /* The name of the return slot in a function. */ \
  393. X(ReturnSlot) \
  394. /* The name of `Self`. */ \
  395. X(SelfType) \
  396. /* The name of `self`. */ \
  397. X(SelfValue) \
  398. /* The name of `_`. */ \
  399. X(Underscore) \
  400. /* The name of `vptr`. */ \
  401. X(Vptr)
  402. // The ID of a name. A name is either a string or a special name such as
  403. // `self`, `Self`, or `base`.
  404. struct NameId : public IdBase<NameId> {
  405. static constexpr llvm::StringLiteral Label = "name";
  406. // names().GetFormatted() is used for diagnostics.
  407. using DiagnosticType = Diagnostics::TypeInfo<std::string>;
  408. // An enum of special names.
  409. enum class SpecialNameId : uint8_t {
  410. #define CARBON_SPECIAL_NAME_ID_FOR_ENUM(Name) Name,
  411. CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_ENUM)
  412. #undef CARBON_SPECIAL_NAME_ID_FOR_ENUM
  413. };
  414. // For each SpecialNameId, provide a matching `NameId` instance for
  415. // convenience.
  416. #define CARBON_SPECIAL_NAME_ID_FOR_DECL(Name) static const NameId Name;
  417. CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_DECL)
  418. #undef CARBON_SPECIAL_NAME_ID_FOR_DECL
  419. // The number of non-index (<0) that exist, and will need storage in name
  420. // lookup.
  421. static const int NonIndexValueCount;
  422. // Returns the NameId corresponding to a particular IdentifierId.
  423. static auto ForIdentifier(IdentifierId id) -> NameId;
  424. // Returns the NameId corresponding to a particular PackageNameId. This is the
  425. // name that is declared when the package is imported.
  426. static auto ForPackageName(PackageNameId id) -> NameId;
  427. using IdBase::IdBase;
  428. // Returns the IdentifierId corresponding to this NameId, or `None` if this is
  429. // a special name.
  430. auto AsIdentifierId() const -> IdentifierId {
  431. return index >= 0 ? IdentifierId(index) : IdentifierId::None;
  432. }
  433. // Expose special names for `switch`.
  434. constexpr auto AsSpecialNameId() const -> std::optional<SpecialNameId> {
  435. if (index >= NoneIndex) {
  436. return std::nullopt;
  437. }
  438. return static_cast<SpecialNameId>(NoneIndex - 1 - index);
  439. }
  440. auto Print(llvm::raw_ostream& out) const -> void;
  441. };
  442. // Define the special `static const NameId` values.
  443. #define CARBON_SPECIAL_NAME_ID_FOR_DEF(Name) \
  444. constexpr NameId NameId::Name = \
  445. NameId(NoneIndex - 1 - static_cast<int>(NameId::SpecialNameId::Name));
  446. CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_DEF)
  447. #undef CARBON_SPECIAL_NAME_ID_FOR_DEF
  448. // Count non-index values, including `None` and special names.
  449. #define CARBON_SPECIAL_NAME_ID_FOR_COUNT(...) +1
  450. constexpr int NameId::NonIndexValueCount =
  451. 1 CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_COUNT);
  452. #undef CARBON_SPECIAL_NAME_ID_FOR_COUNT
  453. // The ID of a `NameScope`.
  454. struct NameScopeId : public IdBase<NameScopeId> {
  455. static constexpr llvm::StringLiteral Label = "name_scope";
  456. // The package (or file) name scope, guaranteed to be the first added.
  457. static const NameScopeId Package;
  458. using IdBase::IdBase;
  459. };
  460. constexpr NameScopeId NameScopeId::Package = NameScopeId(0);
  461. // The ID of an `InstId` block.
  462. struct InstBlockId : public IdBase<InstBlockId> {
  463. static constexpr llvm::StringLiteral Label = "inst_block";
  464. // The canonical empty block, reused to avoid allocating empty vectors. Always
  465. // the 0-index block.
  466. static const InstBlockId Empty;
  467. // Exported instructions. Empty until the File is fully checked; intermediate
  468. // state is in the Check::Context.
  469. static const InstBlockId Exports;
  470. // Instructions produced through import logic. Empty until the File is fully
  471. // checked; intermediate state is in the Check::Context.
  472. static const InstBlockId Imports;
  473. // Global declaration initialization instructions. Empty if none are present.
  474. // Otherwise, __global_init function will be generated and this block will
  475. // be inserted into it.
  476. static const InstBlockId GlobalInit;
  477. // An ID for unreachable code.
  478. static const InstBlockId Unreachable;
  479. using IdBase::IdBase;
  480. auto Print(llvm::raw_ostream& out) const -> void;
  481. };
  482. constexpr InstBlockId InstBlockId::Empty = InstBlockId(0);
  483. constexpr InstBlockId InstBlockId::Exports = InstBlockId(1);
  484. constexpr InstBlockId InstBlockId::Imports = InstBlockId(2);
  485. constexpr InstBlockId InstBlockId::GlobalInit = InstBlockId(3);
  486. constexpr InstBlockId InstBlockId::Unreachable = InstBlockId(NoneIndex - 1);
  487. // Contains either an `InstBlockId` value, an error value, or
  488. // `InstBlockId::None`.
  489. //
  490. // Error values are treated as values, though they are not representable as an
  491. // `InstBlockId` (unlike for the singleton error `InstId`).
  492. class InstBlockIdOrError {
  493. public:
  494. // NOLINTNEXTLINE(google-explicit-constructor)
  495. InstBlockIdOrError(InstBlockId inst_block_id)
  496. : InstBlockIdOrError(inst_block_id, false) {}
  497. static auto MakeError() -> InstBlockIdOrError {
  498. return {InstBlockId::None, true};
  499. }
  500. // Returns whether this class contains either an InstBlockId (other than
  501. // `None`) or an error.
  502. //
  503. // An error is treated as a value (as same for the singleton error `InstId`),
  504. // but it can not actually be materialized as an error value outside of this
  505. // class.
  506. auto has_value() const -> bool {
  507. return has_error_value() || inst_block_id_.has_value();
  508. }
  509. // Returns whether this class contains an error value.
  510. auto has_error_value() const -> bool { return error_; }
  511. // Returns the id of a non-empty inst block, or `None` if `has_value()` is
  512. // false.
  513. //
  514. // Only valid to call if `has_error_value()` is false.
  515. auto inst_block_id() const -> InstBlockId {
  516. CARBON_CHECK(!has_error_value());
  517. return inst_block_id_;
  518. }
  519. private:
  520. InstBlockIdOrError(InstBlockId inst_block_id, bool error)
  521. : inst_block_id_(inst_block_id), error_(error) {}
  522. InstBlockId inst_block_id_;
  523. bool error_;
  524. };
  525. // An ID of an instruction block that is referenced absolutely by an
  526. // instruction. This should only be used as the type of a field within a typed
  527. // instruction class. See AbsoluteInstId.
  528. class AbsoluteInstBlockId : public InstBlockId {
  529. public:
  530. // Support implicit conversion from InstBlockId so that InstBlockId and
  531. // AbsoluteInstBlockId have the same interface.
  532. // NOLINTNEXTLINE(google-explicit-constructor)
  533. constexpr AbsoluteInstBlockId(InstBlockId inst_block_id)
  534. : InstBlockId(inst_block_id) {}
  535. using InstBlockId::InstBlockId;
  536. };
  537. // An ID of an instruction block that is used as the declaration block within a
  538. // declaration instruction. This is a block that is nested within the
  539. // instruction, but doesn't contribute to its value. Such blocks are not
  540. // included in the fingerprint of the declaration. This should only be used as
  541. // the type of a field within a typed instruction class.
  542. class DeclInstBlockId : public InstBlockId {
  543. public:
  544. // Support implicit conversion from InstBlockId so that InstBlockId and
  545. // DeclInstBlockId have the same interface.
  546. // NOLINTNEXTLINE(google-explicit-constructor)
  547. constexpr DeclInstBlockId(InstBlockId inst_block_id)
  548. : InstBlockId(inst_block_id) {}
  549. using InstBlockId::InstBlockId;
  550. };
  551. // An ID of an instruction block that is used as a label in a branch instruction
  552. // or similar. This is a block that is not nested within the instruction, but
  553. // instead exists elsewhere in the enclosing executable region. This should
  554. // only be used as the type of a field within a typed instruction class.
  555. class LabelId : public InstBlockId {
  556. public:
  557. // Support implicit conversion from InstBlockId so that InstBlockId and
  558. // LabelId have the same interface.
  559. // NOLINTNEXTLINE(google-explicit-constructor)
  560. constexpr LabelId(InstBlockId inst_block_id) : InstBlockId(inst_block_id) {}
  561. using InstBlockId::InstBlockId;
  562. };
  563. // The ID of an `ExprRegion`.
  564. // TODO: Move this out of sem_ir and into check, if we don't wind up using it
  565. // in the SemIR for expression patterns.
  566. struct ExprRegionId : public IdBase<ExprRegionId> {
  567. static constexpr llvm::StringLiteral Label = "region";
  568. using IdBase::IdBase;
  569. };
  570. // The ID of a `StructTypeField` block.
  571. struct StructTypeFieldsId : public IdBase<StructTypeFieldsId> {
  572. static constexpr llvm::StringLiteral Label = "struct_type_fields";
  573. // The canonical empty block, reused to avoid allocating empty vectors. Always
  574. // the 0-index block.
  575. static const StructTypeFieldsId Empty;
  576. using IdBase::IdBase;
  577. };
  578. constexpr StructTypeFieldsId StructTypeFieldsId::Empty = StructTypeFieldsId(0);
  579. // The ID of a `CustomLayout` block.
  580. struct CustomLayoutId : public IdBase<CustomLayoutId> {
  581. static constexpr llvm::StringLiteral Label = "custom_layout";
  582. // The canonical empty block. This is never used, but needed by
  583. // BlockValueStore.
  584. static const CustomLayoutId Empty;
  585. // The index in a custom layout of the overall size field.
  586. static constexpr int SizeIndex = 0;
  587. // The index in a custom layout of the overall alignment field.
  588. static constexpr int AlignIndex = 1;
  589. // The index in a custom layout of the offset of the first struct field.
  590. static constexpr int FirstFieldIndex = 2;
  591. using IdBase::IdBase;
  592. };
  593. constexpr CustomLayoutId CustomLayoutId::Empty = CustomLayoutId(0);
  594. // The ID of a type.
  595. struct TypeId : public IdBase<TypeId> {
  596. static constexpr llvm::StringLiteral Label = "type";
  597. // `StringifyConstantInst` is used for diagnostics. However, where possible,
  598. // an `InstId` describing how the type was written should be preferred, using
  599. // `InstIdAsType` or `TypeOfInstId` as the diagnostic argument type.
  600. using DiagnosticType = Diagnostics::TypeInfo<std::string>;
  601. using IdBase::IdBase;
  602. // Returns the ID of the type corresponding to the constant `const_id`, which
  603. // must be of type `type`. As an exception, the type `Error` is of type
  604. // `Error`.
  605. static constexpr auto ForTypeConstant(ConstantId const_id) -> TypeId {
  606. return TypeId(const_id.index);
  607. }
  608. // Returns the constant ID that defines the type.
  609. auto AsConstantId() const -> ConstantId { return ConstantId(index); }
  610. // Returns whether this represents a symbolic type. Requires has_value.
  611. auto is_symbolic() const -> bool { return AsConstantId().is_symbolic(); }
  612. // Returns whether this represents a concrete type. Requires has_value.
  613. auto is_concrete() const -> bool { return AsConstantId().is_concrete(); }
  614. auto Print(llvm::raw_ostream& out) const -> void;
  615. };
  616. // The ID of a `clang::SourceLocation`.
  617. struct ClangSourceLocId : public IdBase<ClangSourceLocId> {
  618. static constexpr llvm::StringLiteral Label = "clang_source_loc";
  619. using IdBase::IdBase;
  620. };
  621. // An index for element access, for structs, tuples, and classes.
  622. struct ElementIndex : public IndexBase<ElementIndex> {
  623. static constexpr llvm::StringLiteral Label = "element";
  624. using IndexBase::IndexBase;
  625. };
  626. // The ID of a library name. This is either a string literal or `default`.
  627. struct LibraryNameId : public IdBase<LibraryNameId> {
  628. static constexpr llvm::StringLiteral Label = "library_name";
  629. using DiagnosticType = Diagnostics::TypeInfo<std::string>;
  630. // The name of `default`.
  631. static const LibraryNameId Default;
  632. // Track cases where the library name was set, but has been diagnosed and
  633. // shouldn't be used anymore.
  634. static const LibraryNameId Error;
  635. // Returns the LibraryNameId for a library name as a string literal.
  636. static auto ForStringLiteralValueId(StringLiteralValueId id) -> LibraryNameId;
  637. using IdBase::IdBase;
  638. // Converts a LibraryNameId back to a string literal.
  639. auto AsStringLiteralValueId() const -> StringLiteralValueId {
  640. CARBON_CHECK(index >= NoneIndex, "{0} must be handled directly", *this);
  641. return StringLiteralValueId(index);
  642. }
  643. auto Print(llvm::raw_ostream& out) const -> void;
  644. };
  645. constexpr LibraryNameId LibraryNameId::Default = LibraryNameId(NoneIndex - 1);
  646. constexpr LibraryNameId LibraryNameId::Error = LibraryNameId(NoneIndex - 2);
  647. // The ID of an `ImportIRInst`.
  648. struct ImportIRInstId : public IdBase<ImportIRInstId> {
  649. static constexpr llvm::StringLiteral Label = "import_ir_inst";
  650. // The maximum ID, non-inclusive. This is constrained to fit inside LocId.
  651. static constexpr int Max =
  652. -(std::numeric_limits<int32_t>::min() + 2 * Parse::NodeId::Max + 1);
  653. constexpr explicit ImportIRInstId(int32_t index) : IdBase(index) {
  654. CARBON_DCHECK(index < Max, "Index out of range: {0}", index);
  655. }
  656. };
  657. // A SemIR location used as the location of instructions. This contains either a
  658. // InstId, NodeId, ImportIRInstId, or None. The intent is that any of these can
  659. // indicate the source of an instruction, and also be used to associate a line
  660. // in diagnostics.
  661. //
  662. // The structure is:
  663. // - None: The standard NoneIndex for all Id types, -1.
  664. // - InstId: Positive values including zero; a full 31 bits.
  665. // - [0, 1 << 31)
  666. // - NodeId: Negative values starting after None; the 24 bit NodeId range.
  667. // - [-2, -2 - (1 << 24))
  668. // - Desugared NodeId: Another 24 bit NodeId range.
  669. // - [-2 - (1 << 24), -2 - (1 << 25))
  670. // - ImportIRInstId: Remaining negative values; after NodeId, fills out negative
  671. // values.
  672. // - [-2 - (1 << 25), -(1 << 31)]
  673. //
  674. // For desugaring, use `InstStore::GetLocIdForDesugaring()`.
  675. struct LocId : public IdBase<LocId> {
  676. // The contained index kind.
  677. enum class Kind {
  678. None,
  679. ImportIRInstId,
  680. InstId,
  681. NodeId,
  682. };
  683. static constexpr llvm::StringLiteral Label = "loc";
  684. using IdBase::IdBase;
  685. // NOLINTNEXTLINE(google-explicit-constructor)
  686. constexpr LocId(ImportIRInstId import_ir_inst_id)
  687. : IdBase(import_ir_inst_id.has_value()
  688. ? FirstImportIRInstId - import_ir_inst_id.index
  689. : NoneIndex) {}
  690. explicit constexpr LocId(InstId inst_id) : IdBase(inst_id.index) {}
  691. // NOLINTNEXTLINE(google-explicit-constructor)
  692. constexpr LocId(Parse::NoneNodeId /*none*/) : IdBase(NoneIndex) {}
  693. // NOLINTNEXTLINE(google-explicit-constructor)
  694. constexpr LocId(Parse::NodeId node_id)
  695. : IdBase(FirstNodeId - node_id.index) {}
  696. // Forms an equivalent LocId for a desugared location. Prefer calling
  697. // `InstStore::GetLocIdForDesugaring`.
  698. auto AsDesugared() const -> LocId {
  699. // This should only be called for NodeId or ImportIRInstId (i.e. canonical
  700. // locations), but we only set the flag for NodeId.
  701. CARBON_CHECK(kind() != Kind::InstId, "Use InstStore::GetDesugaredLocId");
  702. if (index <= FirstNodeId && index > FirstDesugaredNodeId) {
  703. return LocId(index - Parse::NodeId::Max);
  704. }
  705. return *this;
  706. }
  707. // Returns the kind of the `LocId`.
  708. auto kind() const -> Kind {
  709. if (!has_value()) {
  710. return Kind::None;
  711. }
  712. if (index >= 0) {
  713. return Kind::InstId;
  714. }
  715. if (index <= FirstImportIRInstId) {
  716. return Kind::ImportIRInstId;
  717. }
  718. return Kind::NodeId;
  719. }
  720. // Returns true if the location corresponds to desugared instructions.
  721. // Requires a non-`InstId` location.
  722. auto is_desugared() const -> bool {
  723. return index <= FirstDesugaredNodeId && index > FirstImportIRInstId;
  724. }
  725. // Returns the equivalent `ImportIRInstId` when `kind()` matches or is `None`.
  726. // Note that the returned `ImportIRInstId` only identifies a location; it is
  727. // not correct to interpret it as the instruction from which another
  728. // instruction was imported. Use `InstStore::GetImportSource` for that.
  729. auto import_ir_inst_id() const -> ImportIRInstId {
  730. if (!has_value()) {
  731. return ImportIRInstId::None;
  732. }
  733. CARBON_CHECK(kind() == Kind::ImportIRInstId, "{0}", index);
  734. return ImportIRInstId(FirstImportIRInstId - index);
  735. }
  736. // Returns the equivalent `InstId` when `kind()` matches or is `None`.
  737. auto inst_id() const -> InstId {
  738. CARBON_CHECK(kind() == Kind::None || kind() == Kind::InstId, "{0}", index);
  739. return InstId(index);
  740. }
  741. // Returns the equivalent `NodeId` when `kind()` matches or is `None`.
  742. auto node_id() const -> Parse::NodeId {
  743. if (!has_value()) {
  744. return Parse::NodeId::None;
  745. }
  746. CARBON_CHECK(kind() == Kind::NodeId, "{0}", index);
  747. if (index <= FirstDesugaredNodeId) {
  748. return Parse::NodeId(FirstDesugaredNodeId - index);
  749. } else {
  750. return Parse::NodeId(FirstNodeId - index);
  751. }
  752. }
  753. auto Print(llvm::raw_ostream& out) const -> void;
  754. private:
  755. // The value of the 0 index for each of `NodeId` and `ImportIRInstId`.
  756. static constexpr int32_t FirstNodeId = NoneIndex - 1;
  757. static constexpr int32_t FirstDesugaredNodeId =
  758. FirstNodeId - Parse::NodeId::Max;
  759. static constexpr int32_t FirstImportIRInstId =
  760. FirstDesugaredNodeId - Parse::NodeId::Max;
  761. };
  762. // Polymorphic id for fields in `Any[...]` typed instruction category. Used for
  763. // fields where the specific instruction structs have different field types in
  764. // that position or do not have a field in that position at all. Allows
  765. // conversion with `Inst::As<>` from the specific typed instruction to the
  766. // `Any[...]` instruction category.
  767. //
  768. // This type participates in `Inst::FromRaw` in order to convert from specific
  769. // instructions to an `Any[...]` instruction category:
  770. // - In the case the specific instruction has a field of some `IdKind` in the
  771. // same position, the `Any[...]` type will hold its raw value in the
  772. // `AnyRawId` field.
  773. // - In the case the specific instruction has no field in the same position, the
  774. // `Any[...]` type will hold a default constructed `AnyRawId` with a `None`
  775. // value.
  776. struct AnyRawId : public AnyIdBase {
  777. // For IdKind.
  778. static constexpr llvm::StringLiteral Label = "any_raw";
  779. constexpr explicit AnyRawId() : AnyIdBase(AnyIdBase::NoneIndex) {}
  780. constexpr explicit AnyRawId(int32_t id) : AnyIdBase(id) {}
  781. };
  782. } // namespace Carbon::SemIR
  783. #endif // CARBON_TOOLCHAIN_SEM_IR_IDS_H_