entity_name.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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_ENTITY_NAME_H_
  5. #define CARBON_TOOLCHAIN_SEM_IR_ENTITY_NAME_H_
  6. #include "common/hashing.h"
  7. #include "common/set.h"
  8. #include "toolchain/base/value_store.h"
  9. #include "toolchain/sem_ir/clang_decl.h"
  10. #include "toolchain/sem_ir/ids.h"
  11. namespace Carbon::SemIR {
  12. struct EntityName : public Printable<EntityName> {
  13. auto Print(llvm::raw_ostream& out) const -> void {
  14. out << "{name: " << name_id << ", parent_scope: " << parent_scope_id
  15. << ", index: " << bind_index_value << ", is_template: " << is_template
  16. << ", is_unused: " << is_unused << ", form: " << form_id << "}";
  17. }
  18. friend auto CarbonHashtableEq(const EntityName& lhs, const EntityName& rhs)
  19. -> bool {
  20. // This requires that there are no padding bits in the type. This is upheld
  21. // since it holds values all of the same size: each is 32 bits, with one
  22. // split into 30, 1, and 1 bits.
  23. return std::memcmp(&lhs, &rhs, sizeof(EntityName)) == 0;
  24. }
  25. // Hashing for EntityName. See common/hashing.h.
  26. friend auto CarbonHashValue(const EntityName& value, uint64_t seed)
  27. -> HashCode {
  28. Hasher hasher(seed);
  29. hasher.HashRaw(value);
  30. return static_cast<HashCode>(hasher);
  31. }
  32. // The index of the binding, if this is the name of a symbolic binding, or
  33. // `None` otherwise. This is also `None` for a `.Self` symbolic binding,
  34. // because such a binding is not assigned an index.
  35. auto bind_index() const -> CompileTimeBindIndex {
  36. return CompileTimeBindIndex(bind_index_value);
  37. }
  38. // The name.
  39. NameId name_id;
  40. // The parent scope.
  41. NameScopeId parent_scope_id;
  42. // TODO: The following two fields are only meaningful for a symbolic binding.
  43. // Consider splitting them off into a separate type so that we don't store
  44. // them for other kinds of `EntityName`.
  45. // The bind_index() value, unwrapped so it can be stored in a bit-field.
  46. int32_t bind_index_value : 30 = CompileTimeBindIndex::None.index;
  47. // Whether this binding is a template parameter.
  48. bool is_template : 1 = false;
  49. // Whether this binding is marked unused.
  50. bool is_unused : 1 = false;
  51. // The declared form of the binding. This is guaranteed to be set for
  52. // `:?` bindings, and may be set for other binding kinds as well.
  53. //
  54. // TODO: Unify this with the previous three fields, which also represent form
  55. // information.
  56. InstId form_id = InstId::None;
  57. };
  58. // Value store for EntityName. In addition to the regular ValueStore
  59. // functionality, this can provide optional canonical IDs for EntityNames.
  60. struct EntityNameStore
  61. : public ValueStore<EntityNameId, EntityName, Tag<CheckIRId>> {
  62. public:
  63. using ValueStore::ValueStore;
  64. // Adds an entity name for a symbolic binding.
  65. auto AddSymbolicBindingName(NameId name_id, NameScopeId parent_scope_id,
  66. CompileTimeBindIndex bind_index, bool is_template,
  67. bool is_unused) -> EntityNameId {
  68. EntityName name = {.name_id = name_id,
  69. .parent_scope_id = parent_scope_id,
  70. .bind_index_value = bind_index.index,
  71. .is_template = is_template,
  72. .is_unused = is_unused};
  73. CARBON_CHECK(name.bind_index_value == bind_index.index,
  74. "Bind index out of range for bit-field: {0}",
  75. bind_index.index);
  76. return Add(name);
  77. }
  78. // Convert an `EntityName` to a canonical ID. All calls to this with
  79. // equivalent `EntityName`s will return the same `EntityNameId`. Same as
  80. // `MakeCanonical(Add(name))` except that no new `EntityName` is added if we
  81. // already have a canonical `EntityNameId` for that name.
  82. auto AddCanonical(EntityName name) -> EntityNameId;
  83. // Convert an ID to a canonical ID. All calls to this with equivalent
  84. // `EntityName`s will return the same `EntityNameId`.
  85. auto MakeCanonical(EntityNameId id) -> EntityNameId;
  86. private:
  87. class KeyContext;
  88. Set<EntityNameId, /*SmallSize=*/0, KeyContext> canonical_ids_;
  89. };
  90. class EntityNameStore::KeyContext : public TranslatingKeyContext<KeyContext> {
  91. public:
  92. explicit KeyContext(const EntityNameStore* store) : store_(store) {}
  93. // Note that it is safe to return a `const` reference here as the underlying
  94. // object's lifetime is provided by the `store_`.
  95. auto TranslateKey(EntityNameId id) const -> const EntityName& {
  96. return store_->Get(id);
  97. }
  98. private:
  99. const EntityNameStore* store_;
  100. };
  101. inline auto EntityNameStore::AddCanonical(EntityName name) -> EntityNameId {
  102. return canonical_ids_
  103. .Insert(
  104. name, [&] { return Add(name); }, KeyContext(this))
  105. .key();
  106. }
  107. inline auto EntityNameStore::MakeCanonical(EntityNameId id) -> EntityNameId {
  108. return canonical_ids_.Insert(id, KeyContext(this)).key();
  109. }
  110. } // namespace Carbon::SemIR
  111. #endif // CARBON_TOOLCHAIN_SEM_IR_ENTITY_NAME_H_