inst_namer.cpp 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. #include "toolchain/sem_ir/inst_namer.h"
  5. #include <string>
  6. #include <utility>
  7. #include <variant>
  8. #include "common/ostream.h"
  9. #include "common/raw_string_ostream.h"
  10. #include "llvm/ADT/STLExtras.h"
  11. #include "llvm/ADT/SmallVector.h"
  12. #include "llvm/ADT/StableHashing.h"
  13. #include "toolchain/base/kind_switch.h"
  14. #include "toolchain/base/shared_value_stores.h"
  15. #include "toolchain/base/value_ids.h"
  16. #include "toolchain/lex/tokenized_buffer.h"
  17. #include "toolchain/parse/tree.h"
  18. #include "toolchain/sem_ir/builtin_function_kind.h"
  19. #include "toolchain/sem_ir/entity_with_params_base.h"
  20. #include "toolchain/sem_ir/function.h"
  21. #include "toolchain/sem_ir/ids.h"
  22. #include "toolchain/sem_ir/inst_kind.h"
  23. #include "toolchain/sem_ir/pattern.h"
  24. #include "toolchain/sem_ir/singleton_insts.h"
  25. #include "toolchain/sem_ir/type_info.h"
  26. #include "toolchain/sem_ir/typed_insts.h"
  27. namespace Carbon::SemIR {
  28. InstNamer::InstNamer(const File* sem_ir) : sem_ir_(sem_ir) {
  29. insts_.resize(sem_ir->insts().size(), {ScopeId::None, Namespace::Name()});
  30. labels_.resize(sem_ir->inst_blocks().size());
  31. scopes_.resize(static_cast<size_t>(GetScopeFor(NumberOfScopesTag())));
  32. generic_scopes_.resize(sem_ir->generics().size(), ScopeId::None);
  33. // Build the constants scope.
  34. CollectNamesInBlock(ScopeId::Constants, sem_ir->constants().array_ref());
  35. // Build the ImportRef scope.
  36. CollectNamesInBlock(ScopeId::ImportRefs,
  37. sem_ir->inst_blocks().Get(InstBlockId::ImportRefs));
  38. // Build the file scope.
  39. CollectNamesInBlock(ScopeId::File, sem_ir->top_inst_block_id());
  40. // Build each function scope.
  41. for (auto [fn_id, fn] : sem_ir->functions().enumerate()) {
  42. auto fn_scope = GetScopeFor(fn_id);
  43. // TODO: Provide a location for the function for use as a
  44. // disambiguator.
  45. auto fn_loc = Parse::NodeId::None;
  46. GetScopeInfo(fn_scope).name = globals_.AllocateName(
  47. *this, fn_loc, sem_ir->names().GetIRBaseName(fn.name_id).str());
  48. CollectNamesInBlock(fn_scope, fn.call_params_id);
  49. CollectNamesInBlock(fn_scope, fn.pattern_block_id);
  50. if (!fn.body_block_ids.empty()) {
  51. AddBlockLabel(fn_scope, fn.body_block_ids.front(), "entry", fn_loc);
  52. }
  53. for (auto block_id : fn.body_block_ids) {
  54. CollectNamesInBlock(fn_scope, block_id);
  55. }
  56. for (auto block_id : fn.body_block_ids) {
  57. AddBlockLabel(fn_scope, block_id);
  58. }
  59. CollectNamesInGeneric(fn_scope, fn.generic_id);
  60. }
  61. // Build each class scope.
  62. for (auto [class_id, class_info] : sem_ir->classes().enumerate()) {
  63. auto class_scope = GetScopeFor(class_id);
  64. // TODO: Provide a location for the class for use as a disambiguator.
  65. auto class_loc = Parse::NodeId::None;
  66. GetScopeInfo(class_scope).name = globals_.AllocateName(
  67. *this, class_loc,
  68. sem_ir->names().GetIRBaseName(class_info.name_id).str());
  69. CollectNamesInBlock(class_scope, class_info.pattern_block_id);
  70. AddBlockLabel(class_scope, class_info.body_block_id, "class", class_loc);
  71. CollectNamesInBlock(class_scope, class_info.body_block_id);
  72. CollectNamesInGeneric(class_scope, class_info.generic_id);
  73. }
  74. // Build each interface scope.
  75. for (auto [interface_id, interface_info] : sem_ir->interfaces().enumerate()) {
  76. auto interface_scope = GetScopeFor(interface_id);
  77. // TODO: Provide a location for the interface for use as a disambiguator.
  78. auto interface_loc = Parse::NodeId::None;
  79. GetScopeInfo(interface_scope).name = globals_.AllocateName(
  80. *this, interface_loc,
  81. sem_ir->names().GetIRBaseName(interface_info.name_id).str());
  82. CollectNamesInBlock(interface_scope, interface_info.pattern_block_id);
  83. AddBlockLabel(interface_scope, interface_info.body_block_id, "interface",
  84. interface_loc);
  85. CollectNamesInBlock(interface_scope, interface_info.body_block_id);
  86. CollectNamesInGeneric(interface_scope, interface_info.generic_id);
  87. }
  88. // Build each associated constant scope.
  89. for (auto [assoc_const_id, assoc_const_info] :
  90. sem_ir->associated_constants().enumerate()) {
  91. auto assoc_const_scope = GetScopeFor(assoc_const_id);
  92. GetScopeInfo(assoc_const_scope).name = globals_.AllocateName(
  93. *this, LocId(assoc_const_info.decl_id),
  94. sem_ir->names().GetIRBaseName(assoc_const_info.name_id).str());
  95. CollectNamesInGeneric(assoc_const_scope, assoc_const_info.generic_id);
  96. }
  97. // Build each impl scope.
  98. for (auto [impl_id, impl_info] : sem_ir->impls().enumerate()) {
  99. auto impl_scope = GetScopeFor(impl_id);
  100. auto impl_fingerprint = fingerprinter_.GetOrCompute(sem_ir_, impl_id);
  101. // TODO: Invent a name based on the self and constraint types.
  102. GetScopeInfo(impl_scope).name =
  103. globals_.AllocateName(*this, impl_fingerprint, "impl");
  104. CollectNamesInBlock(impl_scope, impl_info.pattern_block_id);
  105. AddBlockLabel(impl_scope, impl_info.body_block_id, "impl",
  106. impl_fingerprint);
  107. CollectNamesInBlock(impl_scope, impl_info.body_block_id);
  108. CollectNamesInGeneric(impl_scope, impl_info.generic_id);
  109. }
  110. }
  111. auto InstNamer::GetScopeName(ScopeId scope) const -> std::string {
  112. switch (scope) {
  113. case ScopeId::None:
  114. return "<no scope>";
  115. // These are treated as SemIR keywords.
  116. case ScopeId::File:
  117. return "file";
  118. case ScopeId::ImportRefs:
  119. return "imports";
  120. case ScopeId::Constants:
  121. return "constants";
  122. // For everything else, use an @ prefix.
  123. default:
  124. return ("@" + GetScopeInfo(scope).name.str()).str();
  125. }
  126. }
  127. auto InstNamer::GetUnscopedNameFor(InstId inst_id) const -> llvm::StringRef {
  128. if (!inst_id.has_value()) {
  129. return "";
  130. }
  131. const auto& inst_name = insts_[inst_id.index].second;
  132. return inst_name ? inst_name.str() : "";
  133. }
  134. auto InstNamer::GetNameFor(ScopeId scope_id, InstId inst_id) const
  135. -> std::string {
  136. if (!inst_id.has_value()) {
  137. return "invalid";
  138. }
  139. // Check for a builtin.
  140. if (IsSingletonInstId(inst_id)) {
  141. return sem_ir_->insts().Get(inst_id).kind().ir_name().str();
  142. }
  143. if (inst_id == SemIR::Namespace::PackageInstId) {
  144. return "package";
  145. }
  146. const auto& [inst_scope, inst_name] = insts_[inst_id.index];
  147. if (!inst_name) {
  148. // This should not happen in valid IR.
  149. RawStringOstream out;
  150. out << "<unexpected>." << inst_id;
  151. auto loc_id = sem_ir_->insts().GetCanonicalLocId(inst_id);
  152. // TODO: Consider handling other kinds.
  153. if (loc_id.kind() == LocId::Kind::NodeId) {
  154. const auto& tree = sem_ir_->parse_tree();
  155. auto token = tree.node_token(loc_id.node_id());
  156. out << ".loc" << tree.tokens().GetLineNumber(token) << "_"
  157. << tree.tokens().GetColumnNumber(token);
  158. }
  159. return out.TakeStr();
  160. }
  161. if (inst_scope == scope_id) {
  162. return ("%" + inst_name.str()).str();
  163. }
  164. return (GetScopeName(inst_scope) + ".%" + inst_name.str()).str();
  165. }
  166. auto InstNamer::GetUnscopedLabelFor(InstBlockId block_id) const
  167. -> llvm::StringRef {
  168. if (!block_id.has_value()) {
  169. return "";
  170. }
  171. const auto& label_name = labels_[block_id.index].second;
  172. return label_name ? label_name.str() : "";
  173. }
  174. // Returns the IR name to use for a label, when referenced from a given scope.
  175. auto InstNamer::GetLabelFor(ScopeId scope_id, InstBlockId block_id) const
  176. -> std::string {
  177. if (!block_id.has_value()) {
  178. return "!invalid";
  179. }
  180. const auto& [label_scope, label_name] = labels_[block_id.index];
  181. if (!label_name) {
  182. // This should not happen in valid IR.
  183. RawStringOstream out;
  184. out << "<unexpected instblockref " << block_id << ">";
  185. return out.TakeStr();
  186. }
  187. if (label_scope == scope_id) {
  188. return ("!" + label_name.str()).str();
  189. }
  190. return (GetScopeName(label_scope) + ".!" + label_name.str()).str();
  191. }
  192. auto InstNamer::Namespace::Name::str() const -> llvm::StringRef {
  193. llvm::StringMapEntry<NameResult>* value = value_;
  194. CARBON_CHECK(value, "cannot print a null name");
  195. while (value->second.ambiguous && value->second.fallback) {
  196. value = value->second.fallback.value_;
  197. }
  198. return value->first();
  199. }
  200. auto InstNamer::Namespace::AllocateName(
  201. const InstNamer& inst_namer,
  202. std::variant<LocId, uint64_t> loc_id_or_fingerprint, std::string name)
  203. -> Name {
  204. // The best (shortest) name for this instruction so far, and the current
  205. // name for it.
  206. Name best;
  207. Name current;
  208. // Add `name` as a name for this entity.
  209. auto add_name = [&](bool mark_ambiguous = true) {
  210. auto [it, added] = allocated.insert({name, NameResult()});
  211. Name new_name = Name(it);
  212. if (!added) {
  213. if (mark_ambiguous) {
  214. // This name was allocated for a different instruction. Mark it as
  215. // ambiguous and keep looking for a name for this instruction.
  216. new_name.SetAmbiguous();
  217. }
  218. } else {
  219. if (!best) {
  220. best = new_name;
  221. } else {
  222. CARBON_CHECK(current);
  223. current.SetFallback(new_name);
  224. }
  225. current = new_name;
  226. }
  227. return added;
  228. };
  229. // Use the given name if it's available.
  230. if (!name.empty()) {
  231. add_name();
  232. }
  233. // Append location information to try to disambiguate.
  234. if (auto* loc_id = std::get_if<LocId>(&loc_id_or_fingerprint)) {
  235. *loc_id = inst_namer.sem_ir_->insts().GetCanonicalLocId(*loc_id);
  236. // TODO: Consider handling other kinds.
  237. if (loc_id->kind() == LocId::Kind::NodeId) {
  238. const auto& tree = inst_namer.sem_ir_->parse_tree();
  239. auto token = tree.node_token(loc_id->node_id());
  240. llvm::raw_string_ostream(name)
  241. << ".loc" << tree.tokens().GetLineNumber(token);
  242. add_name();
  243. llvm::raw_string_ostream(name)
  244. << "_" << tree.tokens().GetColumnNumber(token);
  245. add_name();
  246. }
  247. } else {
  248. uint64_t fingerprint = std::get<uint64_t>(loc_id_or_fingerprint);
  249. llvm::raw_string_ostream out(name);
  250. out << ".";
  251. // Include names with 3-6 characters from the fingerprint. Then fall back to
  252. // sequential numbering.
  253. for (int n : llvm::seq(1, 7)) {
  254. out.write_hex((fingerprint >> (64 - 4 * n)) & 0xF);
  255. if (n >= 3) {
  256. add_name();
  257. }
  258. }
  259. }
  260. // Append numbers until we find an available name.
  261. name += ".";
  262. auto name_size_without_counter = name.size();
  263. for (int counter = 1;; ++counter) {
  264. name.resize(name_size_without_counter);
  265. llvm::raw_string_ostream(name) << counter;
  266. if (add_name(/*mark_ambiguous=*/false)) {
  267. return best;
  268. }
  269. }
  270. }
  271. auto InstNamer::AddBlockLabel(
  272. ScopeId scope_id, InstBlockId block_id, std::string name,
  273. std::variant<LocId, uint64_t> loc_id_or_fingerprint) -> void {
  274. if (!block_id.has_value() || labels_[block_id.index].second) {
  275. return;
  276. }
  277. if (auto* loc_id = std::get_if<LocId>(&loc_id_or_fingerprint);
  278. loc_id && !loc_id->has_value()) {
  279. if (const auto& block = sem_ir_->inst_blocks().Get(block_id);
  280. !block.empty()) {
  281. loc_id_or_fingerprint = LocId(block.front());
  282. }
  283. }
  284. labels_[block_id.index] = {
  285. scope_id, GetScopeInfo(scope_id).labels.AllocateName(
  286. *this, loc_id_or_fingerprint, std::move(name))};
  287. }
  288. // Finds and adds a suitable block label for the given SemIR instruction that
  289. // represents some kind of branch.
  290. auto InstNamer::AddBlockLabel(ScopeId scope_id, LocId loc_id, AnyBranch branch)
  291. -> void {
  292. loc_id = sem_ir_->insts().GetCanonicalLocId(loc_id);
  293. if (!loc_id.node_id().has_value()) {
  294. AddBlockLabel(scope_id, branch.target_id, "", loc_id);
  295. return;
  296. }
  297. llvm::StringRef name;
  298. switch (sem_ir_->parse_tree().node_kind(loc_id.node_id())) {
  299. case Parse::NodeKind::IfExprIf:
  300. switch (branch.kind) {
  301. case BranchIf::Kind:
  302. name = "if.expr.then";
  303. break;
  304. case Branch::Kind:
  305. name = "if.expr.else";
  306. break;
  307. case BranchWithArg::Kind:
  308. name = "if.expr.result";
  309. break;
  310. default:
  311. break;
  312. }
  313. break;
  314. case Parse::NodeKind::IfCondition:
  315. switch (branch.kind) {
  316. case BranchIf::Kind:
  317. name = "if.then";
  318. break;
  319. case Branch::Kind:
  320. name = "if.else";
  321. break;
  322. default:
  323. break;
  324. }
  325. break;
  326. case Parse::NodeKind::IfStatement:
  327. name = "if.done";
  328. break;
  329. case Parse::NodeKind::ShortCircuitOperandAnd:
  330. name = branch.kind == BranchIf::Kind ? "and.rhs" : "and.result";
  331. break;
  332. case Parse::NodeKind::ShortCircuitOperandOr:
  333. name = branch.kind == BranchIf::Kind ? "or.rhs" : "or.result";
  334. break;
  335. case Parse::NodeKind::WhileConditionStart:
  336. name = "while.cond";
  337. break;
  338. case Parse::NodeKind::WhileCondition:
  339. switch (branch.kind) {
  340. case BranchIf::Kind:
  341. name = "while.body";
  342. break;
  343. case Branch::Kind:
  344. name = "while.done";
  345. break;
  346. default:
  347. break;
  348. }
  349. break;
  350. default:
  351. break;
  352. }
  353. AddBlockLabel(scope_id, branch.target_id, name.str(), loc_id);
  354. }
  355. auto InstNamer::CollectNamesInBlock(ScopeId scope_id, InstBlockId block_id)
  356. -> void {
  357. if (block_id.has_value()) {
  358. CollectNamesInBlock(scope_id, sem_ir_->inst_blocks().Get(block_id));
  359. }
  360. }
  361. auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id,
  362. llvm::ArrayRef<InstId> block) -> void {
  363. llvm::SmallVector<std::pair<ScopeId, InstId>> insts;
  364. // Adds a scope and instructions to walk. Avoids recursion while allowing
  365. // the loop to below add more instructions during iteration. The new
  366. // instructions are queued such that they will be the next to be walked.
  367. // Internally that means they are reversed and added to the end of the vector,
  368. // since we pop from the back of the vector.
  369. auto queue_block_insts = [&](ScopeId scope_id,
  370. llvm::ArrayRef<InstId> inst_ids) {
  371. for (auto inst_id : llvm::reverse(inst_ids)) {
  372. if (inst_id.has_value() && !IsSingletonInstId(inst_id)) {
  373. insts.push_back(std::make_pair(scope_id, inst_id));
  374. }
  375. }
  376. };
  377. auto queue_block_id = [&](ScopeId scope_id, InstBlockId block_id) {
  378. if (block_id.has_value()) {
  379. queue_block_insts(scope_id, sem_ir_->inst_blocks().Get(block_id));
  380. }
  381. };
  382. queue_block_insts(top_scope_id, block);
  383. // Use bound names where available. Otherwise, assign a backup name.
  384. while (!insts.empty()) {
  385. auto [scope_id, inst_id] = insts.pop_back_val();
  386. Scope& scope = GetScopeInfo(scope_id);
  387. auto untyped_inst = sem_ir_->insts().Get(inst_id);
  388. auto add_inst_name = [&](std::string name) {
  389. ScopeId old_scope_id = insts_[inst_id.index].first;
  390. if (old_scope_id == ScopeId::None) {
  391. std::variant<LocId, uint64_t> loc_id_or_fingerprint = LocId::None;
  392. if (scope_id == ScopeId::Constants || scope_id == ScopeId::ImportRefs) {
  393. loc_id_or_fingerprint = fingerprinter_.GetOrCompute(sem_ir_, inst_id);
  394. } else {
  395. loc_id_or_fingerprint = LocId(inst_id);
  396. }
  397. insts_[inst_id.index] = {
  398. scope_id,
  399. scope.insts.AllocateName(*this, loc_id_or_fingerprint, name)};
  400. } else {
  401. CARBON_CHECK(old_scope_id == scope_id,
  402. "Attempting to name inst in multiple scopes");
  403. }
  404. };
  405. auto add_inst_name_id = [&](NameId name_id, llvm::StringRef suffix = "") {
  406. add_inst_name(
  407. (sem_ir_->names().GetIRBaseName(name_id).str() + suffix).str());
  408. };
  409. auto add_int_or_float_type_name = [&](char type_literal_prefix,
  410. InstId bit_width_id,
  411. llvm::StringRef suffix = "") {
  412. RawStringOstream out;
  413. out << type_literal_prefix;
  414. if (auto bit_width = sem_ir_->insts().TryGetAs<IntValue>(bit_width_id)) {
  415. out << sem_ir_->ints().Get(bit_width->int_id);
  416. } else {
  417. out << "N";
  418. }
  419. out << suffix;
  420. add_inst_name(out.TakeStr());
  421. };
  422. auto add_witness_table_name = [&](InstId witness_table_inst_id,
  423. std::string name) {
  424. auto witness_table =
  425. sem_ir_->insts().GetAs<ImplWitnessTable>(witness_table_inst_id);
  426. if (!witness_table.impl_id.has_value()) {
  427. // TODO: The witness comes from a facet value. Can we get the
  428. // interface names from it? Store the facet value instruction in the
  429. // table?
  430. add_inst_name(name);
  431. return;
  432. }
  433. const auto& impl = sem_ir_->impls().Get(witness_table.impl_id);
  434. auto name_id =
  435. sem_ir_->interfaces().Get(impl.interface.interface_id).name_id;
  436. std::string suffix = llvm::formatv(".{}", name);
  437. add_inst_name_id(name_id, suffix);
  438. };
  439. auto facet_access_name_id = [&](InstId facet_value_inst_id) -> NameId {
  440. if (auto name = sem_ir_->insts().TryGetAs<NameRef>(facet_value_inst_id)) {
  441. return name->name_id;
  442. } else if (auto symbolic = sem_ir_->insts().TryGetAs<BindSymbolicName>(
  443. facet_value_inst_id)) {
  444. return sem_ir_->entity_names().Get(symbolic->entity_name_id).name_id;
  445. }
  446. return NameId::None;
  447. };
  448. if (auto branch = untyped_inst.TryAs<AnyBranch>()) {
  449. AddBlockLabel(scope_id, LocId(inst_id), *branch);
  450. }
  451. CARBON_KIND_SWITCH(untyped_inst) {
  452. case AddrOf::Kind: {
  453. add_inst_name("addr");
  454. continue;
  455. }
  456. case ArrayType::Kind: {
  457. // TODO: Can we figure out the name of the type this is an array of?
  458. add_inst_name("array_type");
  459. continue;
  460. }
  461. case CARBON_KIND(AssociatedConstantDecl inst): {
  462. add_inst_name_id(
  463. sem_ir_->associated_constants().Get(inst.assoc_const_id).name_id);
  464. queue_block_id(GetScopeFor(inst.assoc_const_id), inst.decl_block_id);
  465. continue;
  466. }
  467. case CARBON_KIND(AssociatedEntity inst): {
  468. RawStringOstream out;
  469. out << "assoc" << inst.index.index;
  470. add_inst_name(out.TakeStr());
  471. continue;
  472. }
  473. case CARBON_KIND(AssociatedEntityType inst): {
  474. const auto& interface_info =
  475. sem_ir_->interfaces().Get(inst.interface_id);
  476. add_inst_name_id(interface_info.name_id, ".assoc_type");
  477. continue;
  478. }
  479. case BindAlias::Kind:
  480. case BindName::Kind:
  481. case BindSymbolicName::Kind:
  482. case ExportDecl::Kind: {
  483. auto inst = untyped_inst.As<AnyBindNameOrExportDecl>();
  484. add_inst_name_id(
  485. sem_ir_->entity_names().Get(inst.entity_name_id).name_id);
  486. continue;
  487. }
  488. case BindingPattern::Kind:
  489. case SymbolicBindingPattern::Kind: {
  490. auto inst = untyped_inst.As<AnyBindingPattern>();
  491. auto name_id = NameId::Underscore;
  492. if (inst.entity_name_id.has_value()) {
  493. name_id = sem_ir_->entity_names().Get(inst.entity_name_id).name_id;
  494. }
  495. add_inst_name_id(name_id, ".patt");
  496. continue;
  497. }
  498. case CARBON_KIND(BoolLiteral inst): {
  499. if (inst.value.ToBool()) {
  500. add_inst_name("true");
  501. } else {
  502. add_inst_name("false");
  503. }
  504. continue;
  505. }
  506. case CARBON_KIND(BoundMethod inst): {
  507. auto type_id = sem_ir_->insts().Get(inst.function_decl_id).type_id();
  508. if (auto fn_ty = sem_ir_->types().TryGetAs<FunctionType>(type_id)) {
  509. add_inst_name_id(sem_ir_->functions().Get(fn_ty->function_id).name_id,
  510. ".bound");
  511. } else {
  512. add_inst_name("bound_method");
  513. }
  514. continue;
  515. }
  516. case CARBON_KIND(Call inst): {
  517. auto callee_function = GetCalleeFunction(*sem_ir_, inst.callee_id);
  518. if (!callee_function.function_id.has_value()) {
  519. break;
  520. }
  521. const auto& function =
  522. sem_ir_->functions().Get(callee_function.function_id);
  523. // Name the call's result based on the callee.
  524. if (function.builtin_function_kind != BuiltinFunctionKind::None) {
  525. // For a builtin, use the builtin name. Otherwise, we'd typically pick
  526. // the name `Op` below, which is probably not very useful.
  527. add_inst_name(function.builtin_function_kind.name().str());
  528. continue;
  529. }
  530. add_inst_name_id(function.name_id, ".call");
  531. continue;
  532. }
  533. case CARBON_KIND(ClassDecl inst): {
  534. const auto& class_info = sem_ir_->classes().Get(inst.class_id);
  535. add_inst_name_id(class_info.name_id, ".decl");
  536. auto class_scope_id = GetScopeFor(inst.class_id);
  537. queue_block_id(class_scope_id, inst.decl_block_id);
  538. continue;
  539. }
  540. case CARBON_KIND(ClassType inst): {
  541. if (auto literal_info = NumericTypeLiteralInfo::ForType(*sem_ir_, inst);
  542. literal_info.is_valid()) {
  543. add_inst_name(literal_info.GetLiteralAsString(*sem_ir_));
  544. break;
  545. }
  546. add_inst_name_id(sem_ir_->classes().Get(inst.class_id).name_id);
  547. continue;
  548. }
  549. case CompleteTypeWitness::Kind: {
  550. // TODO: Can we figure out the name of the type this is a witness for?
  551. add_inst_name("complete_type");
  552. continue;
  553. }
  554. case ConstType::Kind: {
  555. // TODO: Can we figure out the name of the type argument?
  556. add_inst_name("const");
  557. continue;
  558. }
  559. case CARBON_KIND(FacetAccessType inst): {
  560. auto name_id = facet_access_name_id(inst.facet_value_inst_id);
  561. if (name_id.has_value()) {
  562. add_inst_name_id(name_id, ".as_type");
  563. } else {
  564. add_inst_name("as_type");
  565. }
  566. continue;
  567. }
  568. case CARBON_KIND(FacetType inst): {
  569. const auto& facet_type_info =
  570. sem_ir_->facet_types().Get(inst.facet_type_id);
  571. bool has_where = facet_type_info.other_requirements ||
  572. !facet_type_info.self_impls_constraints.empty() ||
  573. !facet_type_info.rewrite_constraints.empty();
  574. if (facet_type_info.extend_constraints.size() == 1) {
  575. const auto& interface_info = sem_ir_->interfaces().Get(
  576. facet_type_info.extend_constraints.front().interface_id);
  577. add_inst_name_id(interface_info.name_id,
  578. has_where ? "_where.type" : ".type");
  579. } else if (facet_type_info.extend_constraints.empty()) {
  580. add_inst_name(has_where ? "type_where" : "type");
  581. } else {
  582. add_inst_name("facet_type");
  583. }
  584. continue;
  585. }
  586. case CARBON_KIND(FacetValue inst): {
  587. if (auto facet_type =
  588. sem_ir_->types().TryGetAs<FacetType>(inst.type_id)) {
  589. const auto& facet_type_info =
  590. sem_ir_->facet_types().Get(facet_type->facet_type_id);
  591. if (auto interface = facet_type_info.TryAsSingleInterface()) {
  592. const auto& interface_info =
  593. sem_ir_->interfaces().Get(interface->interface_id);
  594. add_inst_name_id(interface_info.name_id, ".facet");
  595. continue;
  596. }
  597. }
  598. add_inst_name("facet_value");
  599. continue;
  600. }
  601. case FloatLiteral::Kind: {
  602. add_inst_name("float");
  603. continue;
  604. }
  605. case CARBON_KIND(FloatType inst): {
  606. add_int_or_float_type_name('f', inst.bit_width_id);
  607. continue;
  608. }
  609. case CARBON_KIND(FunctionDecl inst): {
  610. const auto& function_info = sem_ir_->functions().Get(inst.function_id);
  611. add_inst_name_id(function_info.name_id, ".decl");
  612. auto function_scope_id = GetScopeFor(inst.function_id);
  613. queue_block_id(function_scope_id, inst.decl_block_id);
  614. continue;
  615. }
  616. case CARBON_KIND(FunctionType inst): {
  617. add_inst_name_id(sem_ir_->functions().Get(inst.function_id).name_id,
  618. ".type");
  619. continue;
  620. }
  621. case CARBON_KIND(GenericClassType inst): {
  622. add_inst_name_id(sem_ir_->classes().Get(inst.class_id).name_id,
  623. ".type");
  624. continue;
  625. }
  626. case CARBON_KIND(GenericInterfaceType inst): {
  627. add_inst_name_id(sem_ir_->interfaces().Get(inst.interface_id).name_id,
  628. ".type");
  629. continue;
  630. }
  631. case CARBON_KIND(ImplDecl inst): {
  632. auto impl_scope_id = GetScopeFor(inst.impl_id);
  633. queue_block_id(impl_scope_id, inst.decl_block_id);
  634. break;
  635. }
  636. case CARBON_KIND(LookupImplWitness inst): {
  637. const auto& interface = sem_ir_->specific_interfaces().Get(
  638. inst.query_specific_interface_id);
  639. add_inst_name_id(
  640. sem_ir_->interfaces().Get(interface.interface_id).name_id,
  641. ".lookup_impl_witness");
  642. continue;
  643. }
  644. case CARBON_KIND(ImplWitness inst): {
  645. add_witness_table_name(inst.witness_table_id, "impl_witness");
  646. continue;
  647. }
  648. case CARBON_KIND(ImplWitnessAccess inst): {
  649. // TODO: Include information about the impl?
  650. RawStringOstream out;
  651. out << "impl.elem" << inst.index.index;
  652. add_inst_name(out.TakeStr());
  653. continue;
  654. }
  655. case ImplWitnessAssociatedConstant::Kind: {
  656. add_inst_name("impl_witness_assoc_constant");
  657. continue;
  658. }
  659. case ImplWitnessTable::Kind: {
  660. add_witness_table_name(inst_id, "impl_witness_table");
  661. continue;
  662. }
  663. case ImportCppDecl::Kind: {
  664. add_inst_name("Cpp.import_cpp");
  665. continue;
  666. }
  667. case CARBON_KIND(ImportDecl inst): {
  668. if (inst.package_id.has_value()) {
  669. add_inst_name_id(inst.package_id, ".import");
  670. } else {
  671. add_inst_name("default.import");
  672. }
  673. continue;
  674. }
  675. case ImportRefUnloaded::Kind:
  676. case ImportRefLoaded::Kind: {
  677. // Build the base import name: <package>.<entity-name>
  678. RawStringOstream out;
  679. auto inst = untyped_inst.As<AnyImportRef>();
  680. auto import_ir_inst =
  681. sem_ir_->import_ir_insts().Get(inst.import_ir_inst_id);
  682. const auto& import_ir =
  683. *sem_ir_->import_irs().Get(import_ir_inst.ir_id()).sem_ir;
  684. auto package_id = import_ir.package_id();
  685. if (auto ident_id = package_id.AsIdentifierId(); ident_id.has_value()) {
  686. out << import_ir.identifiers().Get(ident_id);
  687. } else {
  688. out << package_id.AsSpecialName();
  689. }
  690. out << ".";
  691. // Add entity name if available.
  692. if (inst.entity_name_id.has_value()) {
  693. auto name_id =
  694. sem_ir_->entity_names().Get(inst.entity_name_id).name_id;
  695. out << sem_ir_->names().GetIRBaseName(name_id);
  696. } else {
  697. out << "import_ref";
  698. }
  699. add_inst_name(out.TakeStr());
  700. // When building import refs, we frequently add instructions without
  701. // a block. Constants that refer to them need to be separately
  702. // named.
  703. auto const_id = sem_ir_->constant_values().Get(inst_id);
  704. if (const_id.has_value() && const_id.is_concrete()) {
  705. auto const_inst_id = sem_ir_->constant_values().GetInstId(const_id);
  706. if (!insts_[const_inst_id.index].second) {
  707. queue_block_insts(ScopeId::ImportRefs,
  708. llvm::ArrayRef(const_inst_id));
  709. }
  710. }
  711. continue;
  712. }
  713. case CARBON_KIND(InstValue inst): {
  714. insts.push_back({scope_id, inst.inst_id});
  715. add_inst_name(
  716. ("inst." + sem_ir_->insts().Get(inst.inst_id).kind().ir_name())
  717. .str());
  718. continue;
  719. }
  720. case CARBON_KIND(InterfaceDecl inst): {
  721. const auto& interface_info =
  722. sem_ir_->interfaces().Get(inst.interface_id);
  723. add_inst_name_id(interface_info.name_id, ".decl");
  724. auto interface_scope_id = GetScopeFor(inst.interface_id);
  725. queue_block_id(interface_scope_id, inst.decl_block_id);
  726. continue;
  727. }
  728. case CARBON_KIND(IntType inst): {
  729. add_int_or_float_type_name(inst.int_kind == IntKind::Signed ? 'i' : 'u',
  730. inst.bit_width_id, ".builtin");
  731. continue;
  732. }
  733. case CARBON_KIND(IntValue inst): {
  734. RawStringOstream out;
  735. out << "int_" << sem_ir_->ints().Get(inst.int_id);
  736. add_inst_name(out.TakeStr());
  737. continue;
  738. }
  739. case CARBON_KIND(NameBindingDecl inst): {
  740. queue_block_id(scope_id, inst.pattern_block_id);
  741. continue;
  742. }
  743. case CARBON_KIND(NameRef inst): {
  744. add_inst_name_id(inst.name_id, ".ref");
  745. continue;
  746. }
  747. // The namespace is specified here due to the name conflict.
  748. case CARBON_KIND(SemIR::Namespace inst): {
  749. add_inst_name_id(
  750. sem_ir_->name_scopes().Get(inst.name_scope_id).name_id());
  751. continue;
  752. }
  753. case OutParam::Kind:
  754. case RefParam::Kind:
  755. case ValueParam::Kind: {
  756. add_inst_name_id(untyped_inst.As<AnyParam>().pretty_name_id, ".param");
  757. continue;
  758. }
  759. case OutParamPattern::Kind:
  760. case RefParamPattern::Kind:
  761. case ValueParamPattern::Kind: {
  762. add_inst_name_id(GetPrettyNameFromPatternId(*sem_ir_, inst_id),
  763. ".param_patt");
  764. continue;
  765. }
  766. case PatternType::Kind: {
  767. add_inst_name("pattern_type");
  768. continue;
  769. }
  770. case PointerType::Kind: {
  771. add_inst_name("ptr");
  772. continue;
  773. }
  774. case RequireCompleteType::Kind: {
  775. add_inst_name("require_complete");
  776. continue;
  777. }
  778. case ReturnSlotPattern::Kind: {
  779. add_inst_name_id(NameId::ReturnSlot, ".patt");
  780. continue;
  781. }
  782. case CARBON_KIND(SpecificFunction inst): {
  783. auto type_id = sem_ir_->insts().Get(inst.callee_id).type_id();
  784. if (auto fn_ty = sem_ir_->types().TryGetAs<FunctionType>(type_id)) {
  785. add_inst_name_id(sem_ir_->functions().Get(fn_ty->function_id).name_id,
  786. ".specific_fn");
  787. } else {
  788. add_inst_name("specific_fn");
  789. }
  790. continue;
  791. }
  792. case CARBON_KIND(SpecificImplFunction inst): {
  793. auto type_id = sem_ir_->insts().Get(inst.callee_id).type_id();
  794. if (auto fn_ty = sem_ir_->types().TryGetAs<FunctionType>(type_id)) {
  795. add_inst_name_id(sem_ir_->functions().Get(fn_ty->function_id).name_id,
  796. ".specific_impl_fn");
  797. } else {
  798. add_inst_name("specific_impl_fn");
  799. }
  800. continue;
  801. }
  802. case ReturnSlot::Kind: {
  803. add_inst_name_id(NameId::ReturnSlot);
  804. break;
  805. }
  806. case CARBON_KIND(SpliceBlock inst): {
  807. queue_block_id(scope_id, inst.block_id);
  808. break;
  809. }
  810. case StringLiteral::Kind: {
  811. add_inst_name("str");
  812. continue;
  813. }
  814. case CARBON_KIND(StructValue inst): {
  815. if (auto fn_ty =
  816. sem_ir_->types().TryGetAs<FunctionType>(inst.type_id)) {
  817. add_inst_name_id(
  818. sem_ir_->functions().Get(fn_ty->function_id).name_id);
  819. } else if (auto class_ty =
  820. sem_ir_->types().TryGetAs<ClassType>(inst.type_id)) {
  821. add_inst_name_id(sem_ir_->classes().Get(class_ty->class_id).name_id,
  822. ".val");
  823. } else if (auto generic_class_ty =
  824. sem_ir_->types().TryGetAs<GenericClassType>(
  825. inst.type_id)) {
  826. add_inst_name_id(
  827. sem_ir_->classes().Get(generic_class_ty->class_id).name_id,
  828. ".generic");
  829. } else if (auto generic_interface_ty =
  830. sem_ir_->types().TryGetAs<GenericInterfaceType>(
  831. inst.type_id)) {
  832. add_inst_name_id(sem_ir_->interfaces()
  833. .Get(generic_interface_ty->interface_id)
  834. .name_id,
  835. ".generic");
  836. } else {
  837. if (sem_ir_->inst_blocks().Get(inst.elements_id).empty()) {
  838. add_inst_name("empty_struct");
  839. } else {
  840. add_inst_name("struct");
  841. }
  842. }
  843. continue;
  844. }
  845. case CARBON_KIND(StructType inst): {
  846. const auto& fields = sem_ir_->struct_type_fields().Get(inst.fields_id);
  847. if (fields.empty()) {
  848. add_inst_name("empty_struct_type");
  849. continue;
  850. }
  851. std::string name = "struct_type";
  852. for (auto field : fields) {
  853. name += ".";
  854. name += sem_ir_->names().GetIRBaseName(field.name_id).str();
  855. }
  856. add_inst_name(std::move(name));
  857. continue;
  858. }
  859. case CARBON_KIND(TupleAccess inst): {
  860. RawStringOstream out;
  861. out << "tuple.elem" << inst.index.index;
  862. add_inst_name(out.TakeStr());
  863. continue;
  864. }
  865. case CARBON_KIND(TupleType inst): {
  866. if (inst.type_elements_id == InstBlockId::Empty) {
  867. add_inst_name("empty_tuple.type");
  868. } else {
  869. add_inst_name("tuple.type");
  870. }
  871. continue;
  872. }
  873. case CARBON_KIND(TupleValue inst): {
  874. if (sem_ir_->types().Is<ArrayType>(inst.type_id)) {
  875. add_inst_name("array");
  876. } else if (inst.elements_id == InstBlockId::Empty) {
  877. add_inst_name("empty_tuple");
  878. } else {
  879. add_inst_name("tuple");
  880. }
  881. continue;
  882. }
  883. case CARBON_KIND(UnboundElementType inst): {
  884. if (auto class_ty =
  885. sem_ir_->insts().TryGetAs<ClassType>(inst.class_type_inst_id)) {
  886. add_inst_name_id(sem_ir_->classes().Get(class_ty->class_id).name_id,
  887. ".elem");
  888. } else {
  889. add_inst_name("elem_type");
  890. }
  891. continue;
  892. }
  893. case CARBON_KIND(VarStorage inst): {
  894. add_inst_name_id(inst.pretty_name_id, ".var");
  895. continue;
  896. }
  897. default: {
  898. break;
  899. }
  900. }
  901. // Sequentially number all remaining values.
  902. if (untyped_inst.kind().value_kind() != InstValueKind::None) {
  903. add_inst_name("");
  904. }
  905. }
  906. }
  907. auto InstNamer::CollectNamesInGeneric(ScopeId scope_id, GenericId generic_id)
  908. -> void {
  909. if (!generic_id.has_value()) {
  910. return;
  911. }
  912. generic_scopes_[generic_id.index] = scope_id;
  913. const auto& generic = sem_ir_->generics().Get(generic_id);
  914. CollectNamesInBlock(scope_id, generic.decl_block_id);
  915. CollectNamesInBlock(scope_id, generic.definition_block_id);
  916. }
  917. } // namespace Carbon::SemIR