type.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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_TYPE_H_
  5. #define CARBON_TOOLCHAIN_SEM_IR_TYPE_H_
  6. #include "toolchain/base/shared_value_stores.h"
  7. #include "toolchain/sem_ir/constant.h"
  8. #include "toolchain/sem_ir/ids.h"
  9. #include "toolchain/sem_ir/inst.h"
  10. #include "toolchain/sem_ir/type_info.h"
  11. namespace Carbon::SemIR {
  12. // Provides a ValueStore wrapper with an API specific to types.
  13. class TypeStore : public Yaml::Printable<TypeStore> {
  14. public:
  15. // Used to return information about an integer type in `GetIntTypeInfo`.
  16. struct IntTypeInfo {
  17. bool is_signed;
  18. IntId bit_width;
  19. };
  20. explicit TypeStore(File* file) : file_(file) {}
  21. // Returns the ID of the constant used to define the specified type.
  22. auto GetConstantId(TypeId type_id) const -> ConstantId {
  23. if (!type_id.has_value()) {
  24. // TODO: Investigate replacing this with a CHECK or returning `None`.
  25. return ConstantId::NotConstant;
  26. }
  27. return type_id.AsConstantId();
  28. }
  29. // Returns the type ID for a constant that is a type value, i.e. it is a value
  30. // of type `TypeType`.
  31. //
  32. // Facet values are of the same typishness as types, but are not themselves
  33. // types, so they can not be passed here. They should be converted to a type
  34. // through an `as type` conversion, that is, to a value of type `TypeType`.
  35. auto GetTypeIdForTypeConstantId(SemIR::ConstantId constant_id) const
  36. -> SemIR::TypeId;
  37. // Returns the type ID for an instruction whose constant value is a type
  38. // value, i.e. it is a value of type `TypeType`.
  39. //
  40. // Instructions whose values are facet values (see `FacetValue`) produce a
  41. // value of the same typishness as types, but which are themselves not types,
  42. // so they can not be passed here. They should be converted to a type through
  43. // an `as type` conversion, such as to a `FacetAccessType` instruction whose
  44. // value is of type `TypeType`.
  45. auto GetTypeIdForTypeInstId(SemIR::InstId inst_id) const -> SemIR::TypeId;
  46. // Returns the ID of the instruction used to define the specified type.
  47. auto GetInstId(TypeId type_id) const -> InstId;
  48. // Returns the instruction used to define the specified type.
  49. auto GetAsInst(TypeId type_id) const -> Inst;
  50. // Returns whether the specified kind of instruction was used to define the
  51. // type.
  52. template <typename InstT>
  53. auto Is(TypeId type_id) const -> bool {
  54. return GetAsInst(type_id).Is<InstT>();
  55. }
  56. // Returns the instruction used to define the specified type, which is known
  57. // to be a particular kind of instruction.
  58. template <typename InstT>
  59. auto GetAs(TypeId type_id) const -> InstT {
  60. return GetAsInst(type_id).As<InstT>();
  61. }
  62. // Returns the instruction used to define the specified type, if it is of a
  63. // particular kind.
  64. template <typename InstT>
  65. auto TryGetAs(TypeId type_id) const -> std::optional<InstT> {
  66. return GetAsInst(type_id).TryAs<InstT>();
  67. }
  68. // Returns whether two type IDs represent the same type. This includes the
  69. // case where they might be in different generics and thus might have
  70. // different ConstantIds, but are still symbolically equal.
  71. auto AreEqualAcrossDeclarations(TypeId a, TypeId b) const -> bool {
  72. return GetInstId(a) == GetInstId(b);
  73. }
  74. // Gets the value representation to use for a type. This returns an
  75. // invalid type if the given type is not complete.
  76. auto GetValueRepr(TypeId type_id) const -> ValueRepr {
  77. if (auto type_info = complete_type_info_.Lookup(type_id)) {
  78. return type_info.value().value_repr;
  79. }
  80. return {.kind = ValueRepr::Unknown};
  81. }
  82. // Sets the value representation associated with a type.
  83. auto SetValueRepr(TypeId type_id, ValueRepr value_repr) -> void {
  84. CARBON_CHECK(value_repr.kind != ValueRepr::Unknown);
  85. auto insert_info =
  86. complete_type_info_.Insert(type_id, {.value_repr = value_repr});
  87. CARBON_CHECK(insert_info.is_inserted(), "Type {0} completed more than once",
  88. type_id);
  89. complete_types_.push_back(type_id);
  90. CARBON_CHECK(IsComplete(type_id));
  91. }
  92. // Get the object representation associated with a type. For a non-class type,
  93. // this is the type itself. `None` is returned if the object representation
  94. // cannot be determined because the type is not complete.
  95. auto GetObjectRepr(TypeId type_id) const -> TypeId;
  96. // Determines whether the given type is known to be complete. This does not
  97. // determine whether the type could be completed, only whether it has been.
  98. auto IsComplete(TypeId type_id) const -> bool {
  99. return complete_type_info_.Contains(type_id);
  100. }
  101. // Removes any top-level `const` qualifiers from a type.
  102. auto GetUnqualifiedType(TypeId type_id) const -> TypeId;
  103. // Determines whether the given type is a signed integer type. This includes
  104. // the case where the type is `Core.IntLiteral` or a class type whose object
  105. // representation is a signed integer type.
  106. auto IsSignedInt(TypeId int_type_id) const -> bool;
  107. // Returns integer type information from a type ID that is known to represent
  108. // an integer type. Abstracts away the difference between an `IntType`
  109. // instruction defined type, a singleton instruction defined type, and a class
  110. // adapting such a type. Uses IntId::None for types that have a
  111. // non-constant width and for IntLiteral.
  112. auto GetIntTypeInfo(TypeId int_type_id) const -> IntTypeInfo;
  113. // Returns whether `type_id` represents a facet type.
  114. auto IsFacetType(SemIR::TypeId type_id) const -> bool {
  115. return type_id == SemIR::TypeType::SingletonTypeId ||
  116. Is<SemIR::FacetType>(type_id);
  117. }
  118. // Returns a list of types that were completed in this file, in the order in
  119. // which they were completed. Earlier types in this list cannot contain
  120. // instances of later types.
  121. auto complete_types() const -> llvm::ArrayRef<TypeId> {
  122. return complete_types_;
  123. }
  124. auto OutputYaml() const -> Yaml::OutputMapping {
  125. return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {
  126. for (auto type_id : complete_types_) {
  127. map.Add(PrintToString(type_id),
  128. Yaml::OutputScalar(GetValueRepr(type_id)));
  129. }
  130. });
  131. }
  132. auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
  133. -> void {
  134. mem_usage.Collect(MemUsage::ConcatLabel(label, "complete_type_info_"),
  135. complete_type_info_);
  136. mem_usage.Collect(MemUsage::ConcatLabel(label, "complete_types_"),
  137. complete_types_);
  138. }
  139. private:
  140. File* file_;
  141. Map<TypeId, CompleteTypeInfo> complete_type_info_;
  142. llvm::SmallVector<TypeId> complete_types_;
  143. };
  144. } // namespace Carbon::SemIR
  145. #endif // CARBON_TOOLCHAIN_SEM_IR_TYPE_H_