value_stores.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. #include "toolchain/sem_ir/value_stores.h"
  5. #include "llvm/ADT/StringSwitch.h"
  6. #include "toolchain/sem_ir/file.h"
  7. #include "toolchain/sem_ir/inst_profile.h"
  8. namespace Carbon::SemIR {
  9. auto ConstantStore::GetOrAdd(Inst inst, bool is_symbolic) -> ConstantId {
  10. // Compute the instruction's profile.
  11. ConstantNode node = {.inst = inst, .constant_id = ConstantId::NotConstant};
  12. llvm::FoldingSetNodeID id;
  13. node.Profile(id, constants_.getContext());
  14. // Check if we have already created this constant.
  15. void* insert_pos;
  16. if (ConstantNode* found = constants_.FindNodeOrInsertPos(id, insert_pos)) {
  17. CARBON_CHECK(found->constant_id.is_constant())
  18. << "Found non-constant in constant store for " << inst;
  19. CARBON_CHECK(found->constant_id.is_symbolic() == is_symbolic)
  20. << "Mismatch in phase for constant " << inst;
  21. return found->constant_id;
  22. }
  23. // Create the new inst and insert the new node.
  24. auto inst_id = constants_.getContext()->insts().AddInNoBlock(
  25. ParseNodeAndInst::Untyped(Parse::NodeId::Invalid, inst));
  26. auto constant_id = is_symbolic
  27. ? SemIR::ConstantId::ForSymbolicConstant(inst_id)
  28. : SemIR::ConstantId::ForTemplateConstant(inst_id);
  29. node.constant_id = constant_id;
  30. constants_.InsertNode(new (*allocator_) ConstantNode(node), insert_pos);
  31. // The constant value of any constant instruction is that instruction itself.
  32. constants_.getContext()->constant_values().Set(inst_id, constant_id);
  33. return constant_id;
  34. }
  35. auto ConstantStore::GetAsVector() const -> llvm::SmallVector<InstId, 0> {
  36. llvm::SmallVector<InstId, 0> result;
  37. result.reserve(constants_.size());
  38. for (const ConstantNode& node : constants_) {
  39. result.push_back(node.constant_id.inst_id());
  40. }
  41. // For stability, put the results into index order. This happens to also be
  42. // insertion order.
  43. std::sort(result.begin(), result.end(),
  44. [](InstId a, InstId b) { return a.index < b.index; });
  45. return result;
  46. }
  47. auto ConstantStore::ConstantNode::Profile(llvm::FoldingSetNodeID& id,
  48. File* sem_ir) -> void {
  49. ProfileConstant(id, *sem_ir, inst);
  50. }
  51. // Get the spelling to use for a special name.
  52. static auto GetSpecialName(NameId name_id, bool for_ir) -> llvm::StringRef {
  53. switch (name_id.index) {
  54. case NameId::Invalid.index:
  55. return for_ir ? "" : "<invalid>";
  56. case NameId::SelfValue.index:
  57. return "self";
  58. case NameId::SelfType.index:
  59. return "Self";
  60. case NameId::ReturnSlot.index:
  61. return for_ir ? "return" : "<return slot>";
  62. case NameId::PackageNamespace.index:
  63. return "package";
  64. case NameId::Base.index:
  65. return "base";
  66. default:
  67. CARBON_FATAL() << "Unknown special name";
  68. }
  69. }
  70. auto NameStoreWrapper::GetFormatted(NameId name_id) const -> llvm::StringRef {
  71. // If the name is an identifier name with a keyword spelling, format it with
  72. // an `r#` prefix. Format any other identifier name as just the identifier.
  73. if (auto string_name = GetAsStringIfIdentifier(name_id)) {
  74. return llvm::StringSwitch<llvm::StringRef>(*string_name)
  75. #define CARBON_KEYWORD_TOKEN(Name, Spelling) .Case(Spelling, "r#" Spelling)
  76. #include "toolchain/lex/token_kind.def"
  77. .Default(*string_name);
  78. }
  79. return GetSpecialName(name_id, /*for_ir=*/false);
  80. }
  81. auto NameStoreWrapper::GetIRBaseName(NameId name_id) const -> llvm::StringRef {
  82. if (auto string_name = GetAsStringIfIdentifier(name_id)) {
  83. return *string_name;
  84. }
  85. return GetSpecialName(name_id, /*for_ir=*/true);
  86. }
  87. auto NameScope::Print(llvm::raw_ostream& out) const -> void {
  88. out << "{inst: " << inst_id << ", enclosing_scope: " << enclosing_scope_id
  89. << ", has_error: " << (has_error ? "true" : "false");
  90. out << ", extended_scopes: [";
  91. llvm::ListSeparator scope_sep;
  92. for (auto id : extended_scopes) {
  93. out << scope_sep << id;
  94. }
  95. out << "]";
  96. out << ", names: {";
  97. // Sort name keys to get stable output.
  98. llvm::SmallVector<NameId> keys;
  99. for (auto [key, _] : names) {
  100. keys.push_back(key);
  101. }
  102. llvm::sort(keys,
  103. [](NameId lhs, NameId rhs) { return lhs.index < rhs.index; });
  104. llvm::ListSeparator key_sep;
  105. for (auto key : keys) {
  106. out << key_sep << key << ": " << names.find(key)->second;
  107. }
  108. out << "}";
  109. out << "}";
  110. }
  111. } // namespace Carbon::SemIR