inst_namer.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976
  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, sem_ir->inst_blocks().Get(
  37. SemIR::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. auto assoc_const_loc = sem_ir->insts().GetLocId(assoc_const_info.decl_id);
  93. GetScopeInfo(assoc_const_scope).name = globals_.AllocateName(
  94. *this, assoc_const_loc,
  95. sem_ir->names().GetIRBaseName(assoc_const_info.name_id).str());
  96. CollectNamesInGeneric(assoc_const_scope, assoc_const_info.generic_id);
  97. }
  98. // Build each impl scope.
  99. for (auto [impl_id, impl_info] : sem_ir->impls().enumerate()) {
  100. auto impl_scope = GetScopeFor(impl_id);
  101. auto impl_fingerprint = fingerprinter_.GetOrCompute(sem_ir_, impl_id);
  102. // TODO: Invent a name based on the self and constraint types.
  103. GetScopeInfo(impl_scope).name =
  104. globals_.AllocateName(*this, impl_fingerprint, "impl");
  105. CollectNamesInBlock(impl_scope, impl_info.pattern_block_id);
  106. AddBlockLabel(impl_scope, impl_info.body_block_id, "impl",
  107. impl_fingerprint);
  108. CollectNamesInBlock(impl_scope, impl_info.body_block_id);
  109. CollectNamesInGeneric(impl_scope, impl_info.generic_id);
  110. }
  111. }
  112. auto InstNamer::GetScopeName(ScopeId scope) const -> std::string {
  113. switch (scope) {
  114. case ScopeId::None:
  115. return "<no scope>";
  116. // These are treated as SemIR keywords.
  117. case ScopeId::File:
  118. return "file";
  119. case ScopeId::ImportRefs:
  120. return "imports";
  121. case ScopeId::Constants:
  122. return "constants";
  123. // For everything else, use an @ prefix.
  124. default:
  125. return ("@" + GetScopeInfo(scope).name.str()).str();
  126. }
  127. }
  128. auto InstNamer::GetUnscopedNameFor(InstId inst_id) const -> llvm::StringRef {
  129. if (!inst_id.has_value()) {
  130. return "";
  131. }
  132. const auto& inst_name = insts_[inst_id.index].second;
  133. return inst_name ? inst_name.str() : "";
  134. }
  135. auto InstNamer::GetNameFor(ScopeId scope_id, InstId inst_id) const
  136. -> std::string {
  137. if (!inst_id.has_value()) {
  138. return "invalid";
  139. }
  140. // Check for a builtin.
  141. if (SemIR::IsSingletonInstId(inst_id)) {
  142. return sem_ir_->insts().Get(inst_id).kind().ir_name().str();
  143. }
  144. if (inst_id == SemIR::Namespace::PackageInstId) {
  145. return "package";
  146. }
  147. const auto& [inst_scope, inst_name] = insts_[inst_id.index];
  148. if (!inst_name) {
  149. // This should not happen in valid IR.
  150. RawStringOstream out;
  151. out << "<unexpected>." << inst_id;
  152. auto loc_id = sem_ir_->insts().GetLocId(inst_id);
  153. // TODO: Consider handling other kinds.
  154. if (loc_id.kind() == SemIR::LocId::Kind::NodeId) {
  155. const auto& tree = sem_ir_->parse_tree();
  156. auto token = tree.node_token(loc_id.node_id());
  157. out << ".loc" << tree.tokens().GetLineNumber(token) << "_"
  158. << tree.tokens().GetColumnNumber(token);
  159. }
  160. return out.TakeStr();
  161. }
  162. if (inst_scope == scope_id) {
  163. return ("%" + inst_name.str()).str();
  164. }
  165. return (GetScopeName(inst_scope) + ".%" + inst_name.str()).str();
  166. }
  167. auto InstNamer::GetUnscopedLabelFor(InstBlockId block_id) const
  168. -> llvm::StringRef {
  169. if (!block_id.has_value()) {
  170. return "";
  171. }
  172. const auto& label_name = labels_[block_id.index].second;
  173. return label_name ? label_name.str() : "";
  174. }
  175. // Returns the IR name to use for a label, when referenced from a given scope.
  176. auto InstNamer::GetLabelFor(ScopeId scope_id, InstBlockId block_id) const
  177. -> std::string {
  178. if (!block_id.has_value()) {
  179. return "!invalid";
  180. }
  181. const auto& [label_scope, label_name] = labels_[block_id.index];
  182. if (!label_name) {
  183. // This should not happen in valid IR.
  184. RawStringOstream out;
  185. out << "<unexpected instblockref " << block_id << ">";
  186. return out.TakeStr();
  187. }
  188. if (label_scope == scope_id) {
  189. return ("!" + label_name.str()).str();
  190. }
  191. return (GetScopeName(label_scope) + ".!" + label_name.str()).str();
  192. }
  193. auto InstNamer::Namespace::Name::str() const -> llvm::StringRef {
  194. llvm::StringMapEntry<NameResult>* value = value_;
  195. CARBON_CHECK(value, "cannot print a null name");
  196. while (value->second.ambiguous && value->second.fallback) {
  197. value = value->second.fallback.value_;
  198. }
  199. return value->first();
  200. }
  201. auto InstNamer::Namespace::AllocateName(
  202. const InstNamer& inst_namer,
  203. std::variant<SemIR::LocId, uint64_t> loc_id_or_fingerprint,
  204. std::string name) -> Name {
  205. // The best (shortest) name for this instruction so far, and the current
  206. // name for it.
  207. Name best;
  208. Name current;
  209. // Add `name` as a name for this entity.
  210. auto add_name = [&](bool mark_ambiguous = true) {
  211. auto [it, added] = allocated.insert({name, NameResult()});
  212. Name new_name = Name(it);
  213. if (!added) {
  214. if (mark_ambiguous) {
  215. // This name was allocated for a different instruction. Mark it as
  216. // ambiguous and keep looking for a name for this instruction.
  217. new_name.SetAmbiguous();
  218. }
  219. } else {
  220. if (!best) {
  221. best = new_name;
  222. } else {
  223. CARBON_CHECK(current);
  224. current.SetFallback(new_name);
  225. }
  226. current = new_name;
  227. }
  228. return added;
  229. };
  230. // Use the given name if it's available.
  231. if (!name.empty()) {
  232. add_name();
  233. }
  234. // Append location information to try to disambiguate.
  235. if (auto* loc_id = std::get_if<LocId>(&loc_id_or_fingerprint)) {
  236. // TODO: Consider handling other kinds.
  237. if (loc_id->kind() == SemIR::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<SemIR::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 = sem_ir_->insts().GetLocId(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, SemIR::LocId loc_id,
  291. AnyBranch branch) -> void {
  292. if (!loc_id.node_id().has_value()) {
  293. AddBlockLabel(scope_id, branch.target_id, "", loc_id);
  294. return;
  295. }
  296. llvm::StringRef name;
  297. switch (sem_ir_->parse_tree().node_kind(loc_id.node_id())) {
  298. case Parse::NodeKind::IfExprIf:
  299. switch (branch.kind) {
  300. case BranchIf::Kind:
  301. name = "if.expr.then";
  302. break;
  303. case Branch::Kind:
  304. name = "if.expr.else";
  305. break;
  306. case BranchWithArg::Kind:
  307. name = "if.expr.result";
  308. break;
  309. default:
  310. break;
  311. }
  312. break;
  313. case Parse::NodeKind::IfCondition:
  314. switch (branch.kind) {
  315. case BranchIf::Kind:
  316. name = "if.then";
  317. break;
  318. case Branch::Kind:
  319. name = "if.else";
  320. break;
  321. default:
  322. break;
  323. }
  324. break;
  325. case Parse::NodeKind::IfStatement:
  326. name = "if.done";
  327. break;
  328. case Parse::NodeKind::ShortCircuitOperandAnd:
  329. name = branch.kind == BranchIf::Kind ? "and.rhs" : "and.result";
  330. break;
  331. case Parse::NodeKind::ShortCircuitOperandOr:
  332. name = branch.kind == BranchIf::Kind ? "or.rhs" : "or.result";
  333. break;
  334. case Parse::NodeKind::WhileConditionStart:
  335. name = "while.cond";
  336. break;
  337. case Parse::NodeKind::WhileCondition:
  338. switch (branch.kind) {
  339. case BranchIf::Kind:
  340. name = "while.body";
  341. break;
  342. case Branch::Kind:
  343. name = "while.done";
  344. break;
  345. default:
  346. break;
  347. }
  348. break;
  349. default:
  350. break;
  351. }
  352. AddBlockLabel(scope_id, branch.target_id, name.str(), loc_id);
  353. }
  354. auto InstNamer::CollectNamesInBlock(ScopeId scope_id, InstBlockId block_id)
  355. -> void {
  356. if (block_id.has_value()) {
  357. CollectNamesInBlock(scope_id, sem_ir_->inst_blocks().Get(block_id));
  358. }
  359. }
  360. auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id,
  361. llvm::ArrayRef<InstId> block) -> void {
  362. llvm::SmallVector<std::pair<ScopeId, InstId>> insts;
  363. // Adds a scope and instructions to walk. Avoids recursion while allowing
  364. // the loop to below add more instructions during iteration. The new
  365. // instructions are queued such that they will be the next to be walked.
  366. // Internally that means they are reversed and added to the end of the vector,
  367. // since we pop from the back of the vector.
  368. auto queue_block_insts = [&](ScopeId scope_id,
  369. llvm::ArrayRef<InstId> inst_ids) {
  370. for (auto inst_id : llvm::reverse(inst_ids)) {
  371. if (inst_id.has_value() && !SemIR::IsSingletonInstId(inst_id)) {
  372. insts.push_back(std::make_pair(scope_id, inst_id));
  373. }
  374. }
  375. };
  376. auto queue_block_id = [&](ScopeId scope_id, InstBlockId block_id) {
  377. if (block_id.has_value()) {
  378. queue_block_insts(scope_id, sem_ir_->inst_blocks().Get(block_id));
  379. }
  380. };
  381. queue_block_insts(top_scope_id, block);
  382. // Use bound names where available. Otherwise, assign a backup name.
  383. while (!insts.empty()) {
  384. auto [scope_id, inst_id] = insts.pop_back_val();
  385. Scope& scope = GetScopeInfo(scope_id);
  386. auto untyped_inst = sem_ir_->insts().Get(inst_id);
  387. auto add_inst_name = [&](std::string name) {
  388. ScopeId old_scope_id = insts_[inst_id.index].first;
  389. if (old_scope_id == ScopeId::None) {
  390. std::variant<SemIR::LocId, uint64_t> loc_id_or_fingerprint =
  391. SemIR::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 = sem_ir_->insts().GetLocId(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. SemIR::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 = sem_ir_->insts().GetAs<SemIR::ImplWitnessTable>(
  425. 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, sem_ir_->insts().GetLocId(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 =
  518. SemIR::GetCalleeFunction(*sem_ir_, inst.callee_id);
  519. if (!callee_function.function_id.has_value()) {
  520. break;
  521. }
  522. const auto& function =
  523. sem_ir_->functions().Get(callee_function.function_id);
  524. // Name the call's result based on the callee.
  525. if (function.builtin_function_kind !=
  526. SemIR::BuiltinFunctionKind::None) {
  527. // For a builtin, use the builtin name. Otherwise, we'd typically pick
  528. // the name `Op` below, which is probably not very useful.
  529. add_inst_name(function.builtin_function_kind.name().str());
  530. continue;
  531. }
  532. add_inst_name_id(function.name_id, ".call");
  533. continue;
  534. }
  535. case CARBON_KIND(ClassDecl inst): {
  536. const auto& class_info = sem_ir_->classes().Get(inst.class_id);
  537. add_inst_name_id(class_info.name_id, ".decl");
  538. auto class_scope_id = GetScopeFor(inst.class_id);
  539. queue_block_id(class_scope_id, inst.decl_block_id);
  540. continue;
  541. }
  542. case CARBON_KIND(ClassType inst): {
  543. if (auto literal_info = NumericTypeLiteralInfo::ForType(*sem_ir_, inst);
  544. literal_info.is_valid()) {
  545. add_inst_name(literal_info.GetLiteralAsString(*sem_ir_));
  546. break;
  547. }
  548. add_inst_name_id(sem_ir_->classes().Get(inst.class_id).name_id);
  549. continue;
  550. }
  551. case CompleteTypeWitness::Kind: {
  552. // TODO: Can we figure out the name of the type this is a witness for?
  553. add_inst_name("complete_type");
  554. continue;
  555. }
  556. case ConstType::Kind: {
  557. // TODO: Can we figure out the name of the type argument?
  558. add_inst_name("const");
  559. continue;
  560. }
  561. case CARBON_KIND(FacetAccessType inst): {
  562. auto name_id = facet_access_name_id(inst.facet_value_inst_id);
  563. if (name_id.has_value()) {
  564. add_inst_name_id(name_id, ".as_type");
  565. } else {
  566. add_inst_name("as_type");
  567. }
  568. continue;
  569. }
  570. case CARBON_KIND(FacetType inst): {
  571. const auto& facet_type_info =
  572. sem_ir_->facet_types().Get(inst.facet_type_id);
  573. bool has_where = facet_type_info.other_requirements ||
  574. !facet_type_info.self_impls_constraints.empty() ||
  575. !facet_type_info.rewrite_constraints.empty();
  576. if (facet_type_info.extend_constraints.size() == 1) {
  577. const auto& interface_info = sem_ir_->interfaces().Get(
  578. facet_type_info.extend_constraints.front().interface_id);
  579. add_inst_name_id(interface_info.name_id,
  580. has_where ? "_where.type" : ".type");
  581. } else if (facet_type_info.extend_constraints.empty()) {
  582. add_inst_name(has_where ? "type_where" : "type");
  583. } else {
  584. add_inst_name("facet_type");
  585. }
  586. continue;
  587. }
  588. case CARBON_KIND(FacetValue inst): {
  589. if (auto facet_type =
  590. sem_ir_->types().TryGetAs<FacetType>(inst.type_id)) {
  591. const auto& facet_type_info =
  592. sem_ir_->facet_types().Get(facet_type->facet_type_id);
  593. if (auto interface = facet_type_info.TryAsSingleInterface()) {
  594. const auto& interface_info =
  595. sem_ir_->interfaces().Get(interface->interface_id);
  596. add_inst_name_id(interface_info.name_id, ".facet");
  597. continue;
  598. }
  599. }
  600. add_inst_name("facet_value");
  601. continue;
  602. }
  603. case FloatLiteral::Kind: {
  604. add_inst_name("float");
  605. continue;
  606. }
  607. case CARBON_KIND(FloatType inst): {
  608. add_int_or_float_type_name('f', inst.bit_width_id);
  609. continue;
  610. }
  611. case CARBON_KIND(FunctionDecl inst): {
  612. const auto& function_info = sem_ir_->functions().Get(inst.function_id);
  613. add_inst_name_id(function_info.name_id, ".decl");
  614. auto function_scope_id = GetScopeFor(inst.function_id);
  615. queue_block_id(function_scope_id, inst.decl_block_id);
  616. continue;
  617. }
  618. case CARBON_KIND(FunctionType inst): {
  619. add_inst_name_id(sem_ir_->functions().Get(inst.function_id).name_id,
  620. ".type");
  621. continue;
  622. }
  623. case CARBON_KIND(GenericClassType inst): {
  624. add_inst_name_id(sem_ir_->classes().Get(inst.class_id).name_id,
  625. ".type");
  626. continue;
  627. }
  628. case CARBON_KIND(GenericInterfaceType inst): {
  629. add_inst_name_id(sem_ir_->interfaces().Get(inst.interface_id).name_id,
  630. ".type");
  631. continue;
  632. }
  633. case CARBON_KIND(ImplDecl inst): {
  634. auto impl_scope_id = GetScopeFor(inst.impl_id);
  635. queue_block_id(impl_scope_id, inst.decl_block_id);
  636. break;
  637. }
  638. case CARBON_KIND(LookupImplWitness inst): {
  639. const auto& interface = sem_ir_->specific_interfaces().Get(
  640. inst.query_specific_interface_id);
  641. add_inst_name_id(
  642. sem_ir_->interfaces().Get(interface.interface_id).name_id,
  643. ".lookup_impl_witness");
  644. continue;
  645. }
  646. case CARBON_KIND(ImplWitness inst): {
  647. add_witness_table_name(inst.witness_table_id, "impl_witness");
  648. continue;
  649. }
  650. case CARBON_KIND(ImplWitnessAccess inst): {
  651. // TODO: Include information about the impl?
  652. RawStringOstream out;
  653. out << "impl.elem" << inst.index.index;
  654. add_inst_name(out.TakeStr());
  655. continue;
  656. }
  657. case ImplWitnessAssociatedConstant::Kind: {
  658. add_inst_name("impl_witness_assoc_constant");
  659. continue;
  660. }
  661. case ImplWitnessTable::Kind: {
  662. add_witness_table_name(inst_id, "impl_witness_table");
  663. continue;
  664. }
  665. case ImportCppDecl::Kind: {
  666. add_inst_name("Cpp.import_cpp");
  667. continue;
  668. }
  669. case CARBON_KIND(ImportDecl inst): {
  670. if (inst.package_id.has_value()) {
  671. add_inst_name_id(inst.package_id, ".import");
  672. } else {
  673. add_inst_name("default.import");
  674. }
  675. continue;
  676. }
  677. case ImportRefUnloaded::Kind:
  678. case ImportRefLoaded::Kind: {
  679. // Build the base import name: <package>.<entity-name>
  680. RawStringOstream out;
  681. auto inst = untyped_inst.As<AnyImportRef>();
  682. auto import_ir_inst =
  683. sem_ir_->import_ir_insts().Get(inst.import_ir_inst_id);
  684. const auto& import_ir =
  685. *sem_ir_->import_irs().Get(import_ir_inst.ir_id).sem_ir;
  686. auto package_id = import_ir.package_id();
  687. if (auto ident_id = package_id.AsIdentifierId(); ident_id.has_value()) {
  688. out << import_ir.identifiers().Get(ident_id);
  689. } else {
  690. out << package_id.AsSpecialName();
  691. }
  692. out << ".";
  693. // Add entity name if available.
  694. if (inst.entity_name_id.has_value()) {
  695. auto name_id =
  696. sem_ir_->entity_names().Get(inst.entity_name_id).name_id;
  697. out << sem_ir_->names().GetIRBaseName(name_id);
  698. } else {
  699. out << "import_ref";
  700. }
  701. add_inst_name(out.TakeStr());
  702. // When building import refs, we frequently add instructions without
  703. // a block. Constants that refer to them need to be separately
  704. // named.
  705. auto const_id = sem_ir_->constant_values().Get(inst_id);
  706. if (const_id.has_value() && const_id.is_concrete()) {
  707. auto const_inst_id = sem_ir_->constant_values().GetInstId(const_id);
  708. if (!insts_[const_inst_id.index].second) {
  709. queue_block_insts(ScopeId::ImportRefs,
  710. llvm::ArrayRef(const_inst_id));
  711. }
  712. }
  713. continue;
  714. }
  715. case CARBON_KIND(InstValue inst): {
  716. insts.push_back({scope_id, inst.inst_id});
  717. add_inst_name(
  718. ("inst." + sem_ir_->insts().Get(inst.inst_id).kind().ir_name())
  719. .str());
  720. continue;
  721. }
  722. case CARBON_KIND(InterfaceDecl inst): {
  723. const auto& interface_info =
  724. sem_ir_->interfaces().Get(inst.interface_id);
  725. add_inst_name_id(interface_info.name_id, ".decl");
  726. auto interface_scope_id = GetScopeFor(inst.interface_id);
  727. queue_block_id(interface_scope_id, inst.decl_block_id);
  728. continue;
  729. }
  730. case CARBON_KIND(IntType inst): {
  731. add_int_or_float_type_name(inst.int_kind == IntKind::Signed ? 'i' : 'u',
  732. inst.bit_width_id, ".builtin");
  733. continue;
  734. }
  735. case CARBON_KIND(IntValue inst): {
  736. RawStringOstream out;
  737. out << "int_" << sem_ir_->ints().Get(inst.int_id);
  738. add_inst_name(out.TakeStr());
  739. continue;
  740. }
  741. case CARBON_KIND(NameBindingDecl inst): {
  742. queue_block_id(scope_id, inst.pattern_block_id);
  743. continue;
  744. }
  745. case CARBON_KIND(NameRef inst): {
  746. add_inst_name_id(inst.name_id, ".ref");
  747. continue;
  748. }
  749. // The namespace is specified here due to the name conflict.
  750. case CARBON_KIND(SemIR::Namespace inst): {
  751. add_inst_name_id(
  752. sem_ir_->name_scopes().Get(inst.name_scope_id).name_id());
  753. continue;
  754. }
  755. case OutParam::Kind:
  756. case RefParam::Kind:
  757. case ValueParam::Kind: {
  758. add_inst_name_id(untyped_inst.As<AnyParam>().pretty_name_id, ".param");
  759. continue;
  760. }
  761. case OutParamPattern::Kind:
  762. case RefParamPattern::Kind:
  763. case ValueParamPattern::Kind: {
  764. add_inst_name_id(SemIR::GetPrettyNameFromPatternId(*sem_ir_, inst_id),
  765. ".param_patt");
  766. continue;
  767. }
  768. case PointerType::Kind: {
  769. add_inst_name("ptr");
  770. continue;
  771. }
  772. case RequireCompleteType::Kind: {
  773. add_inst_name("require_complete");
  774. continue;
  775. }
  776. case ReturnSlotPattern::Kind: {
  777. add_inst_name_id(NameId::ReturnSlot, ".patt");
  778. continue;
  779. }
  780. case CARBON_KIND(SpecificFunction inst): {
  781. auto type_id = sem_ir_->insts().Get(inst.callee_id).type_id();
  782. if (auto fn_ty = sem_ir_->types().TryGetAs<FunctionType>(type_id)) {
  783. add_inst_name_id(sem_ir_->functions().Get(fn_ty->function_id).name_id,
  784. ".specific_fn");
  785. } else {
  786. add_inst_name("specific_fn");
  787. }
  788. continue;
  789. }
  790. case CARBON_KIND(SpecificImplFunction inst): {
  791. auto type_id = sem_ir_->insts().Get(inst.callee_id).type_id();
  792. if (auto fn_ty = sem_ir_->types().TryGetAs<FunctionType>(type_id)) {
  793. add_inst_name_id(sem_ir_->functions().Get(fn_ty->function_id).name_id,
  794. ".specific_impl_fn");
  795. } else {
  796. add_inst_name("specific_impl_fn");
  797. }
  798. continue;
  799. }
  800. case ReturnSlot::Kind: {
  801. add_inst_name_id(NameId::ReturnSlot);
  802. break;
  803. }
  804. case CARBON_KIND(SpliceBlock inst): {
  805. queue_block_id(scope_id, inst.block_id);
  806. break;
  807. }
  808. case StringLiteral::Kind: {
  809. add_inst_name("str");
  810. continue;
  811. }
  812. case CARBON_KIND(StructValue inst): {
  813. if (auto fn_ty =
  814. sem_ir_->types().TryGetAs<FunctionType>(inst.type_id)) {
  815. add_inst_name_id(
  816. sem_ir_->functions().Get(fn_ty->function_id).name_id);
  817. } else if (auto class_ty =
  818. sem_ir_->types().TryGetAs<ClassType>(inst.type_id)) {
  819. add_inst_name_id(sem_ir_->classes().Get(class_ty->class_id).name_id,
  820. ".val");
  821. } else if (auto generic_class_ty =
  822. sem_ir_->types().TryGetAs<GenericClassType>(
  823. inst.type_id)) {
  824. add_inst_name_id(
  825. sem_ir_->classes().Get(generic_class_ty->class_id).name_id,
  826. ".generic");
  827. } else if (auto generic_interface_ty =
  828. sem_ir_->types().TryGetAs<GenericInterfaceType>(
  829. inst.type_id)) {
  830. add_inst_name_id(sem_ir_->interfaces()
  831. .Get(generic_interface_ty->interface_id)
  832. .name_id,
  833. ".generic");
  834. } else {
  835. if (sem_ir_->inst_blocks().Get(inst.elements_id).empty()) {
  836. add_inst_name("empty_struct");
  837. } else {
  838. add_inst_name("struct");
  839. }
  840. }
  841. continue;
  842. }
  843. case CARBON_KIND(StructType inst): {
  844. const auto& fields = sem_ir_->struct_type_fields().Get(inst.fields_id);
  845. if (fields.empty()) {
  846. add_inst_name("empty_struct_type");
  847. continue;
  848. }
  849. std::string name = "struct_type";
  850. for (auto field : fields) {
  851. name += ".";
  852. name += sem_ir_->names().GetIRBaseName(field.name_id).str();
  853. }
  854. add_inst_name(std::move(name));
  855. continue;
  856. }
  857. case CARBON_KIND(TupleAccess inst): {
  858. RawStringOstream out;
  859. out << "tuple.elem" << inst.index.index;
  860. add_inst_name(out.TakeStr());
  861. continue;
  862. }
  863. case CARBON_KIND(TupleType inst): {
  864. if (inst.type_elements_id == InstBlockId::Empty) {
  865. add_inst_name("empty_tuple.type");
  866. } else {
  867. add_inst_name("tuple.type");
  868. }
  869. continue;
  870. }
  871. case CARBON_KIND(TupleValue inst): {
  872. if (sem_ir_->types().Is<ArrayType>(inst.type_id)) {
  873. add_inst_name("array");
  874. } else if (inst.elements_id == InstBlockId::Empty) {
  875. add_inst_name("empty_tuple");
  876. } else {
  877. add_inst_name("tuple");
  878. }
  879. continue;
  880. }
  881. case CARBON_KIND(UnboundElementType inst): {
  882. if (auto class_ty =
  883. sem_ir_->insts().TryGetAs<ClassType>(inst.class_type_inst_id)) {
  884. add_inst_name_id(sem_ir_->classes().Get(class_ty->class_id).name_id,
  885. ".elem");
  886. } else {
  887. add_inst_name("elem_type");
  888. }
  889. continue;
  890. }
  891. case CARBON_KIND(VarStorage inst): {
  892. add_inst_name_id(inst.pretty_name_id, ".var");
  893. continue;
  894. }
  895. default: {
  896. break;
  897. }
  898. }
  899. // Sequentially number all remaining values.
  900. if (untyped_inst.kind().value_kind() != InstValueKind::None) {
  901. add_inst_name("");
  902. }
  903. }
  904. }
  905. auto InstNamer::CollectNamesInGeneric(ScopeId scope_id, GenericId generic_id)
  906. -> void {
  907. if (!generic_id.has_value()) {
  908. return;
  909. }
  910. generic_scopes_[generic_id.index] = scope_id;
  911. const auto& generic = sem_ir_->generics().Get(generic_id);
  912. CollectNamesInBlock(scope_id, generic.decl_block_id);
  913. CollectNamesInBlock(scope_id, generic.definition_block_id);
  914. }
  915. } // namespace Carbon::SemIR