index_base.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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_BASE_INDEX_BASE_H_
  5. #define CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_
  6. #include <type_traits>
  7. #include "common/ostream.h"
  8. #include "llvm/ADT/DenseMapInfo.h"
  9. namespace Carbon {
  10. template <typename DataType>
  11. class DataIterator;
  12. // A lightweight handle to an item identified by an opaque ID.
  13. //
  14. // This class is intended to be derived from by classes representing a specific
  15. // kind of ID, whose meaning as an integer is an implementation detail of the
  16. // type that vends the IDs. Typically this will be a vector index.
  17. //
  18. // Classes derived from IdBase are designed to be passed by value, not
  19. // reference or pointer. They are also designed to be small and efficient to
  20. // store in data structures.
  21. struct IdBase : public Printable<IdBase> {
  22. static constexpr int32_t InvalidIndex = -1;
  23. IdBase() = delete;
  24. constexpr explicit IdBase(int index) : index(index) {}
  25. auto Print(llvm::raw_ostream& output) const -> void {
  26. if (is_valid()) {
  27. output << index;
  28. } else {
  29. output << "<invalid>";
  30. }
  31. }
  32. auto is_valid() const -> bool { return index != InvalidIndex; }
  33. int32_t index;
  34. };
  35. // A lightweight handle to an item that behaves like an index.
  36. //
  37. // Unlike IdBase, classes derived from IndexBase are not completely opaque, and
  38. // provide at least an ordering between indexes that has meaning to an API
  39. // user. Additional semantics may be specified by the derived class.
  40. struct IndexBase : public IdBase {
  41. using IdBase::IdBase;
  42. };
  43. // Equality comparison for both IdBase and IndexBase.
  44. template <
  45. typename IndexType,
  46. typename std::enable_if_t<std::is_base_of_v<IdBase, IndexType>>* = nullptr>
  47. auto operator==(IndexType lhs, IndexType rhs) -> bool {
  48. return lhs.index == rhs.index;
  49. }
  50. template <
  51. typename IndexType,
  52. typename std::enable_if_t<std::is_base_of_v<IdBase, IndexType>>* = nullptr>
  53. auto operator!=(IndexType lhs, IndexType rhs) -> bool {
  54. return lhs.index != rhs.index;
  55. }
  56. template <
  57. typename IndexType, typename RHSType,
  58. typename std::enable_if_t<std::is_base_of_v<IdBase, IndexType>>* = nullptr,
  59. typename std::enable_if_t<std::is_convertible_v<RHSType, IndexType>>* =
  60. nullptr>
  61. auto operator==(IndexType lhs, RHSType rhs) -> bool {
  62. return lhs.index == IndexType(rhs).index;
  63. }
  64. template <
  65. typename IndexType, typename RHSType,
  66. typename std::enable_if_t<std::is_base_of_v<IdBase, IndexType>>* = nullptr,
  67. typename std::enable_if_t<std::is_convertible_v<RHSType, IndexType>>* =
  68. nullptr>
  69. auto operator!=(IndexType lhs, RHSType rhs) -> bool {
  70. return lhs.index != IndexType(rhs).index;
  71. }
  72. template <
  73. typename LHSType, typename IndexType,
  74. typename std::enable_if_t<std::is_base_of_v<IdBase, IndexType>>* = nullptr,
  75. typename std::enable_if_t<std::is_convertible_v<LHSType, IndexType>>* =
  76. nullptr>
  77. auto operator==(LHSType lhs, IndexType rhs) -> bool {
  78. return IndexType(lhs).index == rhs.index;
  79. }
  80. template <
  81. typename LHSType, typename IndexType,
  82. typename std::enable_if_t<std::is_base_of_v<IdBase, IndexType>>* = nullptr,
  83. typename std::enable_if_t<std::is_convertible_v<LHSType, IndexType>>* =
  84. nullptr>
  85. auto operator!=(LHSType lhs, IndexType rhs) -> bool {
  86. return IndexType(lhs).index != rhs.index;
  87. }
  88. // The < and > comparisons for only IndexBase.
  89. template <typename IndexType,
  90. typename std::enable_if_t<std::is_base_of_v<IndexBase, IndexType>>* =
  91. nullptr>
  92. auto operator<(IndexType lhs, IndexType rhs) -> bool {
  93. return lhs.index < rhs.index;
  94. }
  95. template <typename IndexType,
  96. typename std::enable_if_t<std::is_base_of_v<IndexBase, IndexType>>* =
  97. nullptr>
  98. auto operator<=(IndexType lhs, IndexType rhs) -> bool {
  99. return lhs.index <= rhs.index;
  100. }
  101. template <typename IndexType,
  102. typename std::enable_if_t<std::is_base_of_v<IndexBase, IndexType>>* =
  103. nullptr>
  104. auto operator>(IndexType lhs, IndexType rhs) -> bool {
  105. return lhs.index > rhs.index;
  106. }
  107. template <typename IndexType,
  108. typename std::enable_if_t<std::is_base_of_v<IndexBase, IndexType>>* =
  109. nullptr>
  110. auto operator>=(IndexType lhs, IndexType rhs) -> bool {
  111. return lhs.index >= rhs.index;
  112. }
  113. // Provides base support for use of IdBase types as DenseMap/DenseSet keys.
  114. //
  115. // Usage (in global namespace):
  116. // template <>
  117. // struct llvm::DenseMapInfo<Carbon::MyType>
  118. // : public Carbon::IndexMapInfo<Carbon::MyType> {};
  119. template <typename Index>
  120. struct IndexMapInfo {
  121. static inline auto getEmptyKey() -> Index {
  122. return Index(llvm::DenseMapInfo<int32_t>::getEmptyKey());
  123. }
  124. static inline auto getTombstoneKey() -> Index {
  125. return Index(llvm::DenseMapInfo<int32_t>::getTombstoneKey());
  126. }
  127. static auto getHashValue(const Index& val) -> unsigned {
  128. return llvm::DenseMapInfo<int32_t>::getHashValue(val.index);
  129. }
  130. static auto isEqual(const Index& lhs, const Index& rhs) -> bool {
  131. return lhs == rhs;
  132. }
  133. };
  134. } // namespace Carbon
  135. #endif // CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_