inst_namer.cpp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175
  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/entity_with_params_base.h"
  19. #include "toolchain/sem_ir/function.h"
  20. #include "toolchain/sem_ir/ids.h"
  21. #include "toolchain/sem_ir/inst_kind.h"
  22. #include "toolchain/sem_ir/pattern.h"
  23. #include "toolchain/sem_ir/singleton_insts.h"
  24. #include "toolchain/sem_ir/type_info.h"
  25. #include "toolchain/sem_ir/typed_insts.h"
  26. namespace Carbon::SemIR {
  27. class InstNamer::NamingContext {
  28. public:
  29. explicit NamingContext(InstNamer* inst_namer, InstNamer::ScopeId scope_id,
  30. InstId inst_id);
  31. // Names the single instruction. Use bound names where available. Otherwise,
  32. // assign a backup name.
  33. //
  34. // Insts with a type_id are required to add names; other insts may
  35. // optionally set a name. All insts may push other insts to be named.
  36. auto NameInst() -> void;
  37. private:
  38. // Adds the instruction's name.
  39. auto AddInstName(std::string name) -> void;
  40. // Adds the instruction's name by `NameId`.
  41. auto AddInstNameId(NameId name_id, llvm::StringRef suffix = "") -> void {
  42. AddInstName((sem_ir().names().GetIRBaseName(name_id) + suffix).str());
  43. }
  44. // Names an `IntType` or `FloatType`.
  45. auto AddIntOrFloatTypeName(char type_literal_prefix, InstId bit_width_id,
  46. llvm::StringRef suffix = "") -> void;
  47. // Names an `ImplWitnessTable` instruction.
  48. auto AddWitnessTableName(InstId witness_table_inst_id, std::string name)
  49. -> void;
  50. // Pushes all instructions in a block, by ID.
  51. auto PushBlockId(ScopeId scope_id, InstBlockId block_id) -> void {
  52. inst_namer_->PushBlockId(scope_id, block_id);
  53. }
  54. // Names the instruction as an entity. May push processing of the entity.
  55. template <typename EntityIdT>
  56. auto AddEntityNameAndMaybePush(EntityIdT id, llvm::StringRef suffix = "")
  57. -> void {
  58. AddInstName((inst_namer_->MaybePushEntity(id) + suffix).str());
  59. }
  60. auto sem_ir() -> const File& { return *inst_namer_->sem_ir_; }
  61. InstNamer* inst_namer_;
  62. ScopeId scope_id_;
  63. InstId inst_id_;
  64. Inst inst_;
  65. };
  66. InstNamer::InstNamer(const File* sem_ir, int total_ir_count)
  67. : sem_ir_(sem_ir), fingerprinter_(total_ir_count) {
  68. insts_.resize(sem_ir->insts().size(), {ScopeId::None, Namespace::Name()});
  69. labels_.resize(sem_ir->inst_blocks().size());
  70. scopes_.resize(GetScopeIdOffset(ScopeIdTypeEnum::None));
  71. generic_scopes_.resize(sem_ir->generics().size(), ScopeId::None);
  72. // We process the stack between each large block in order to reduce the
  73. // temporary size of the stack.
  74. auto process_stack = [&] {
  75. while (!inst_stack_.empty() || !inst_block_stack_.empty()) {
  76. if (inst_stack_.empty()) {
  77. auto [scope_id, block_id] = inst_block_stack_.pop_back_val();
  78. PushBlockInsts(scope_id, sem_ir_->inst_blocks().Get(block_id));
  79. }
  80. while (!inst_stack_.empty()) {
  81. auto [scope_id, inst_id] = inst_stack_.pop_back_val();
  82. NamingContext context(this, scope_id, inst_id);
  83. context.NameInst();
  84. }
  85. }
  86. };
  87. // Name each of the top-level scopes, in order. We use these as the roots of
  88. // walking the IR.
  89. PushBlockInsts(ScopeId::Constants, sem_ir->constants().array_ref());
  90. process_stack();
  91. PushBlockId(ScopeId::Imports, InstBlockId::Imports);
  92. process_stack();
  93. PushBlockId(ScopeId::File, sem_ir->top_inst_block_id());
  94. process_stack();
  95. // Global init won't have any other references, so we add it directly.
  96. if (sem_ir_->global_ctor_id().has_value()) {
  97. MaybePushEntity(sem_ir_->global_ctor_id());
  98. process_stack();
  99. }
  100. }
  101. auto InstNamer::GetScopeIdOffset(ScopeIdTypeEnum id_enum) const -> int {
  102. int offset = 0;
  103. // For each Id type, add the number of entities *above* its case; for example,
  104. // the offset for functions excludes the functions themselves. The fallthrough
  105. // handles summing to get uniqueness; order isn't special.
  106. switch (id_enum) {
  107. case ScopeIdTypeEnum::None:
  108. // `None` will be getting a full count of scopes.
  109. offset += sem_ir_->associated_constants().size();
  110. [[fallthrough]];
  111. case ScopeIdTypeEnum::For<AssociatedConstantId>:
  112. offset += sem_ir_->classes().size();
  113. [[fallthrough]];
  114. case ScopeIdTypeEnum::For<ClassId>:
  115. offset += sem_ir_->vtables().size();
  116. [[fallthrough]];
  117. case ScopeIdTypeEnum::For<VtableId>:
  118. offset += sem_ir_->functions().size();
  119. [[fallthrough]];
  120. case ScopeIdTypeEnum::For<CppOverloadSetId>:
  121. offset += sem_ir_->cpp_overload_sets().size();
  122. [[fallthrough]];
  123. case ScopeIdTypeEnum::For<FunctionId>:
  124. offset += sem_ir_->impls().size();
  125. [[fallthrough]];
  126. case ScopeIdTypeEnum::For<ImplId>:
  127. offset += sem_ir_->interfaces().size();
  128. [[fallthrough]];
  129. case ScopeIdTypeEnum::For<InterfaceId>:
  130. offset += sem_ir_->specific_interfaces().size();
  131. [[fallthrough]];
  132. case ScopeIdTypeEnum::For<SpecificInterfaceId>:
  133. // All type-specific scopes are offset by `FirstEntityScope`.
  134. offset += static_cast<int>(ScopeId::FirstEntityScope);
  135. return offset;
  136. default:
  137. CARBON_FATAL("Unexpected ScopeIdTypeEnum: {0}", id_enum);
  138. }
  139. }
  140. auto InstNamer::GetScopeName(ScopeId scope) const -> std::string {
  141. switch (scope) {
  142. case ScopeId::None:
  143. return "<no scope>";
  144. // These are treated as SemIR keywords.
  145. case ScopeId::File:
  146. return "file";
  147. case ScopeId::Imports:
  148. return "imports";
  149. case ScopeId::Constants:
  150. return "constants";
  151. // For everything else, use an @ prefix.
  152. default:
  153. return ("@" + GetScopeInfo(scope).name.GetFullName()).str();
  154. }
  155. }
  156. auto InstNamer::GetUnscopedNameFor(InstId inst_id) const -> llvm::StringRef {
  157. if (!inst_id.has_value()) {
  158. return "";
  159. }
  160. if (IsSingletonInstId(inst_id)) {
  161. return sem_ir_->insts().Get(inst_id).kind().ir_name();
  162. }
  163. const auto& inst_name = insts_[inst_id.index].second;
  164. return inst_name ? inst_name.GetFullName() : "";
  165. }
  166. auto InstNamer::GetNameFor(ScopeId scope_id, InstId inst_id) const
  167. -> std::string {
  168. if (!inst_id.has_value()) {
  169. return "invalid";
  170. }
  171. // Check for a builtin.
  172. if (IsSingletonInstId(inst_id)) {
  173. return sem_ir_->insts().Get(inst_id).kind().ir_name().str();
  174. }
  175. if (inst_id == SemIR::Namespace::PackageInstId) {
  176. return "package";
  177. }
  178. const auto& [inst_scope, inst_name] = insts_[inst_id.index];
  179. if (!inst_name) {
  180. // This should not happen in valid IR.
  181. RawStringOstream out;
  182. out << "<unexpected>." << inst_id;
  183. auto loc_id = sem_ir_->insts().GetCanonicalLocId(inst_id);
  184. // TODO: Consider handling other kinds.
  185. if (loc_id.kind() == LocId::Kind::NodeId) {
  186. const auto& tree = sem_ir_->parse_tree();
  187. auto token = tree.node_token(loc_id.node_id());
  188. out << ".loc" << tree.tokens().GetLineNumber(token) << "_"
  189. << tree.tokens().GetColumnNumber(token);
  190. }
  191. return out.TakeStr();
  192. }
  193. if (inst_scope == scope_id) {
  194. return ("%" + inst_name.GetFullName()).str();
  195. }
  196. return (GetScopeName(inst_scope) + ".%" + inst_name.GetFullName()).str();
  197. }
  198. auto InstNamer::GetUnscopedLabelFor(InstBlockId block_id) const
  199. -> llvm::StringRef {
  200. if (!block_id.has_value()) {
  201. return "";
  202. }
  203. const auto& label_name = labels_[block_id.index].second;
  204. return label_name ? label_name.GetFullName() : "";
  205. }
  206. // Returns the IR name to use for a label, when referenced from a given scope.
  207. auto InstNamer::GetLabelFor(ScopeId scope_id, InstBlockId block_id) const
  208. -> std::string {
  209. if (!block_id.has_value()) {
  210. return "!invalid";
  211. }
  212. const auto& [label_scope, label_name] = labels_[block_id.index];
  213. if (!label_name) {
  214. // This should not happen in valid IR.
  215. RawStringOstream out;
  216. out << "<unexpected instblockref " << block_id << ">";
  217. return out.TakeStr();
  218. }
  219. if (label_scope == scope_id) {
  220. return ("!" + label_name.GetFullName()).str();
  221. }
  222. return (GetScopeName(label_scope) + ".!" + label_name.GetFullName()).str();
  223. }
  224. auto InstNamer::Namespace::Name::GetFullName() const -> llvm::StringRef {
  225. if (!value_) {
  226. return "<null name>";
  227. }
  228. llvm::StringMapEntry<NameResult>* value = value_;
  229. while (value->second.ambiguous && value->second.fallback) {
  230. value = value->second.fallback.value_;
  231. }
  232. return value->first();
  233. }
  234. auto InstNamer::Namespace::Name::GetBaseName() const -> llvm::StringRef {
  235. if (!value_) {
  236. return "<null name>";
  237. }
  238. return value_->first().take_front(base_name_size_);
  239. }
  240. auto InstNamer::Namespace::AllocateName(
  241. const InstNamer& inst_namer,
  242. std::variant<LocId, uint64_t> loc_id_or_fingerprint, std::string name)
  243. -> Name {
  244. // The best (shortest) name for this instruction so far, and the current
  245. // name for it.
  246. Name best;
  247. Name current;
  248. const size_t base_name_size = name.size();
  249. // Add `name` as a name for this entity.
  250. auto add_name = [&](bool mark_ambiguous = true) {
  251. auto [it, added] = allocated_.insert({name, NameResult()});
  252. Name new_name = Name(it, base_name_size);
  253. if (!added) {
  254. if (mark_ambiguous) {
  255. // This name was allocated for a different instruction. Mark it as
  256. // ambiguous and keep looking for a name for this instruction.
  257. new_name.SetAmbiguous();
  258. }
  259. } else {
  260. if (!best) {
  261. best = new_name;
  262. } else {
  263. CARBON_CHECK(current);
  264. current.SetFallback(new_name);
  265. }
  266. current = new_name;
  267. }
  268. return added;
  269. };
  270. // Use the given name if it's available.
  271. if (!name.empty()) {
  272. add_name();
  273. }
  274. // Append location information to try to disambiguate.
  275. if (auto* loc_id = std::get_if<LocId>(&loc_id_or_fingerprint)) {
  276. *loc_id = inst_namer.sem_ir_->insts().GetCanonicalLocId(*loc_id);
  277. // TODO: Consider handling other kinds.
  278. if (loc_id->kind() == LocId::Kind::NodeId) {
  279. const auto& tree = inst_namer.sem_ir_->parse_tree();
  280. auto token = tree.node_token(loc_id->node_id());
  281. llvm::raw_string_ostream(name)
  282. << ".loc" << tree.tokens().GetLineNumber(token);
  283. add_name();
  284. llvm::raw_string_ostream(name)
  285. << "_" << tree.tokens().GetColumnNumber(token);
  286. add_name();
  287. }
  288. } else {
  289. uint64_t fingerprint = std::get<uint64_t>(loc_id_or_fingerprint);
  290. llvm::raw_string_ostream out(name);
  291. out << ".";
  292. // Include names with 3-6 characters from the fingerprint. Then fall back to
  293. // sequential numbering.
  294. for (int n : llvm::seq(1, 7)) {
  295. out.write_hex((fingerprint >> (64 - 4 * n)) & 0xF);
  296. if (n >= 3) {
  297. add_name();
  298. }
  299. }
  300. }
  301. // Append numbers until we find an available name.
  302. name += ".";
  303. auto name_size_without_counter = name.size();
  304. for (int counter = 1;; ++counter) {
  305. name.resize(name_size_without_counter);
  306. llvm::raw_string_ostream(name) << counter;
  307. if (add_name(/*mark_ambiguous=*/false)) {
  308. return best;
  309. }
  310. }
  311. }
  312. auto InstNamer::AddBlockLabel(
  313. ScopeId scope_id, InstBlockId block_id, std::string name,
  314. std::variant<LocId, uint64_t> loc_id_or_fingerprint) -> void {
  315. if (!block_id.has_value() || labels_[block_id.index].second) {
  316. return;
  317. }
  318. if (auto* loc_id = std::get_if<LocId>(&loc_id_or_fingerprint);
  319. loc_id && !loc_id->has_value()) {
  320. if (const auto& block = sem_ir_->inst_blocks().Get(block_id);
  321. !block.empty()) {
  322. loc_id_or_fingerprint = LocId(block.front());
  323. }
  324. }
  325. labels_[block_id.index] = {
  326. scope_id, GetScopeInfo(scope_id).labels.AllocateName(
  327. *this, loc_id_or_fingerprint, std::move(name))};
  328. }
  329. // Provides names for `AddBlockLabel`.
  330. struct BranchNames {
  331. // Returns names for a branching parse node, or nullopt if not a branch.
  332. static auto For(Parse::NodeKind node_kind) -> std::optional<BranchNames> {
  333. switch (node_kind) {
  334. case Parse::NodeKind::ForHeaderStart:
  335. return {{.prefix = "for", .branch = "next"}};
  336. case Parse::NodeKind::ForHeader:
  337. return {{.prefix = "for", .branch_if = "body", .branch = "done"}};
  338. case Parse::NodeKind::IfExprIf:
  339. return {{.prefix = "if.expr",
  340. .branch_if = "then",
  341. .branch = "else",
  342. .branch_with_arg = "result"}};
  343. case Parse::NodeKind::IfCondition:
  344. return {{.prefix = "if", .branch_if = "then", .branch = "else"}};
  345. case Parse::NodeKind::IfStatement:
  346. return {{.prefix = "if", .branch = "done"}};
  347. case Parse::NodeKind::ShortCircuitOperandAnd:
  348. return {
  349. {.prefix = "and", .branch_if = "rhs", .branch_with_arg = "result"}};
  350. case Parse::NodeKind::ShortCircuitOperandOr:
  351. return {
  352. {.prefix = "or", .branch_if = "rhs", .branch_with_arg = "result"}};
  353. case Parse::NodeKind::WhileConditionStart:
  354. return {{.prefix = "while", .branch = "cond"}};
  355. case Parse::NodeKind::WhileCondition:
  356. return {{.prefix = "while", .branch_if = "body", .branch = "done"}};
  357. default:
  358. return std::nullopt;
  359. }
  360. }
  361. // Returns the provided suffix for the instruction kind, or an empty string.
  362. auto GetSuffix(InstKind inst_kind) -> llvm::StringLiteral {
  363. switch (inst_kind) {
  364. case BranchIf::Kind:
  365. return branch_if;
  366. case Branch::Kind:
  367. return branch;
  368. case BranchWithArg::Kind:
  369. return branch_with_arg;
  370. default:
  371. return "";
  372. }
  373. }
  374. // The kind of branch, based on the node kind.
  375. llvm::StringLiteral prefix;
  376. // For labeling branch instruction kinds. Only expected kinds need a value;
  377. // the empty string is for unexpected kinds.
  378. llvm::StringLiteral branch_if = "";
  379. llvm::StringLiteral branch = "";
  380. llvm::StringLiteral branch_with_arg = "";
  381. };
  382. // Finds and adds a suitable block label for the given SemIR instruction that
  383. // represents some kind of branch.
  384. auto InstNamer::AddBlockLabel(ScopeId scope_id, LocId loc_id, AnyBranch branch)
  385. -> void {
  386. std::string label;
  387. loc_id = sem_ir_->insts().GetCanonicalLocId(loc_id);
  388. if (loc_id.node_id().has_value()) {
  389. if (auto names = BranchNames::For(
  390. sem_ir_->parse_tree().node_kind(loc_id.node_id()))) {
  391. if (auto suffix = names->GetSuffix(branch.kind); !suffix.empty()) {
  392. label = llvm::formatv("{0}.{1}", names->prefix, suffix);
  393. } else {
  394. label =
  395. llvm::formatv("{0}.<unexpected {1}>", names->prefix, branch.kind);
  396. }
  397. }
  398. }
  399. AddBlockLabel(scope_id, branch.target_id, label, loc_id);
  400. }
  401. auto InstNamer::PushBlockId(ScopeId scope_id, InstBlockId block_id) -> void {
  402. if (block_id.has_value()) {
  403. inst_block_stack_.push_back({scope_id, block_id});
  404. }
  405. }
  406. auto InstNamer::PushBlockInsts(ScopeId scope_id,
  407. llvm::ArrayRef<InstId> inst_ids) -> void {
  408. for (auto inst_id : llvm::reverse(inst_ids)) {
  409. if (inst_id.has_value() && !IsSingletonInstId(inst_id)) {
  410. inst_stack_.push_back(std::make_pair(scope_id, inst_id));
  411. }
  412. }
  413. }
  414. auto InstNamer::PushGeneric(ScopeId scope_id, GenericId generic_id) -> void {
  415. if (!generic_id.has_value()) {
  416. return;
  417. }
  418. generic_scopes_[generic_id.index] = scope_id;
  419. const auto& generic = sem_ir_->generics().Get(generic_id);
  420. // Push blocks in reverse order.
  421. PushBlockId(scope_id, generic.definition_block_id);
  422. PushBlockId(scope_id, generic.decl_block_id);
  423. }
  424. auto InstNamer::PushEntity(AssociatedConstantId associated_constant_id,
  425. ScopeId scope_id, Scope& scope) -> void {
  426. const auto& assoc_const =
  427. sem_ir_->associated_constants().Get(associated_constant_id);
  428. scope.name = globals_.AllocateName(
  429. *this, LocId(assoc_const.decl_id),
  430. sem_ir_->names().GetIRBaseName(assoc_const.name_id).str());
  431. // Push blocks in reverse order.
  432. PushGeneric(scope_id, assoc_const.generic_id);
  433. }
  434. auto InstNamer::PushEntity(ClassId class_id, ScopeId scope_id, Scope& scope)
  435. -> void {
  436. const auto& class_info = sem_ir_->classes().Get(class_id);
  437. LocId class_loc(class_info.latest_decl_id());
  438. scope.name = globals_.AllocateName(
  439. *this, class_loc,
  440. sem_ir_->names().GetIRBaseName(class_info.name_id).str());
  441. AddBlockLabel(scope_id, class_info.body_block_id, "class", class_loc);
  442. PushGeneric(scope_id, class_info.generic_id);
  443. // Push blocks in reverse order.
  444. PushBlockId(scope_id, class_info.body_block_id);
  445. PushBlockId(scope_id, class_info.pattern_block_id);
  446. }
  447. auto InstNamer::GetNameForParentNameScope(NameScopeId name_scope_id)
  448. -> llvm::StringRef {
  449. if (!name_scope_id.has_value()) {
  450. return "";
  451. }
  452. auto scope_inst =
  453. sem_ir_->insts().Get(sem_ir_->name_scopes().Get(name_scope_id).inst_id());
  454. CARBON_KIND_SWITCH(scope_inst) {
  455. case CARBON_KIND(ClassDecl class_decl): {
  456. return MaybePushEntity(class_decl.class_id);
  457. }
  458. case CARBON_KIND(ImplDecl impl): {
  459. return MaybePushEntity(impl.impl_id);
  460. }
  461. case CARBON_KIND(InterfaceDecl interface): {
  462. return MaybePushEntity(interface.interface_id);
  463. }
  464. case SemIR::Namespace::Kind: {
  465. // Only prefix type scopes.
  466. return "";
  467. }
  468. default: {
  469. return "<unsupported scope>";
  470. }
  471. }
  472. }
  473. auto InstNamer::PushEntity(FunctionId function_id, ScopeId scope_id,
  474. Scope& scope) -> void {
  475. const auto& fn = sem_ir_->functions().Get(function_id);
  476. LocId fn_loc(fn.latest_decl_id());
  477. auto scope_prefix = GetNameForParentNameScope(fn.parent_scope_id);
  478. scope.name = globals_.AllocateName(
  479. *this, fn_loc,
  480. llvm::formatv("{0}{1}{2}", scope_prefix, scope_prefix.empty() ? "" : ".",
  481. sem_ir_->names().GetIRBaseName(fn.name_id)));
  482. if (!fn.body_block_ids.empty()) {
  483. AddBlockLabel(scope_id, fn.body_block_ids.front(), "entry", fn_loc);
  484. }
  485. // Push blocks in reverse order.
  486. PushGeneric(scope_id, fn.generic_id);
  487. for (auto block_id : llvm::reverse(fn.body_block_ids)) {
  488. PushBlockId(scope_id, block_id);
  489. }
  490. PushBlockId(scope_id, fn.pattern_block_id);
  491. PushBlockId(scope_id, fn.call_params_id);
  492. }
  493. auto InstNamer::PushEntity(ImplId impl_id, ScopeId scope_id, Scope& scope)
  494. -> void {
  495. const auto& impl = sem_ir_->impls().Get(impl_id);
  496. auto impl_fingerprint = fingerprinter_.GetOrCompute(sem_ir_, impl_id);
  497. llvm::StringRef self_name;
  498. auto self_const_id =
  499. sem_ir_->constant_values().GetConstantInstId(impl.self_id);
  500. if (IsSingletonInstId(self_const_id)) {
  501. self_name = sem_ir_->insts().Get(self_const_id).kind().ir_name();
  502. } else if (const auto& inst_name = insts_[self_const_id.index].second) {
  503. self_name = inst_name.GetBaseName();
  504. } else {
  505. self_name = "<unexpected self>";
  506. }
  507. llvm::StringRef interface_name;
  508. if (impl.interface.interface_id.has_value()) {
  509. interface_name = MaybePushEntity(impl.interface.interface_id);
  510. } else {
  511. interface_name = "<error>";
  512. }
  513. scope.name = globals_.AllocateName(
  514. *this, impl_fingerprint,
  515. llvm::formatv("{0}.as.{1}.impl", self_name, interface_name));
  516. AddBlockLabel(scope_id, impl.body_block_id, "impl", impl_fingerprint);
  517. // Push blocks in reverse order.
  518. PushGeneric(scope_id, impl.generic_id);
  519. PushBlockId(scope_id, impl.body_block_id);
  520. PushBlockId(scope_id, impl.pattern_block_id);
  521. }
  522. auto InstNamer::PushEntity(InterfaceId interface_id, ScopeId scope_id,
  523. Scope& scope) -> void {
  524. const auto& interface = sem_ir_->interfaces().Get(interface_id);
  525. LocId interface_loc(interface.latest_decl_id());
  526. scope.name = globals_.AllocateName(
  527. *this, interface_loc,
  528. sem_ir_->names().GetIRBaseName(interface.name_id).str());
  529. AddBlockLabel(scope_id, interface.body_block_id, "interface", interface_loc);
  530. // Push blocks in reverse order.
  531. PushGeneric(scope_id, interface.generic_id);
  532. PushBlockId(scope_id, interface.body_block_id);
  533. PushBlockId(scope_id, interface.pattern_block_id);
  534. }
  535. auto InstNamer::PushEntity(VtableId vtable_id, ScopeId /*scope_id*/,
  536. Scope& scope) -> void {
  537. const auto& vtable = sem_ir_->vtables().Get(vtable_id);
  538. const auto& class_info = sem_ir_->classes().Get(vtable.class_id);
  539. LocId vtable_loc(class_info.latest_decl_id());
  540. scope.name = globals_.AllocateName(
  541. *this, vtable_loc,
  542. sem_ir_->names().GetIRBaseName(class_info.name_id).str() + ".vtable");
  543. // TODO: Add support for generic vtables here and elsewhere.
  544. // PushGeneric(scope_id, vtable_info.generic_id);
  545. }
  546. InstNamer::NamingContext::NamingContext(InstNamer* inst_namer,
  547. InstNamer::ScopeId scope_id,
  548. InstId inst_id)
  549. : inst_namer_(inst_namer),
  550. scope_id_(scope_id),
  551. inst_id_(inst_id),
  552. inst_(sem_ir().insts().Get(inst_id)) {}
  553. auto InstNamer::NamingContext::AddInstName(std::string name) -> void {
  554. ScopeId old_scope_id = inst_namer_->insts_[inst_id_.index].first;
  555. if (old_scope_id == ScopeId::None) {
  556. std::variant<LocId, uint64_t> loc_id_or_fingerprint = LocId::None;
  557. if (scope_id_ == ScopeId::Constants || scope_id_ == ScopeId::Imports) {
  558. loc_id_or_fingerprint =
  559. inst_namer_->fingerprinter_.GetOrCompute(&sem_ir(), inst_id_);
  560. } else {
  561. loc_id_or_fingerprint = LocId(inst_id_);
  562. }
  563. auto scoped_name = inst_namer_->GetScopeInfo(scope_id_).insts.AllocateName(
  564. *inst_namer_, loc_id_or_fingerprint, std::move(name));
  565. inst_namer_->insts_[inst_id_.index] = {scope_id_, scoped_name};
  566. } else {
  567. CARBON_CHECK(old_scope_id == scope_id_,
  568. "Attempting to name inst in multiple scopes");
  569. }
  570. }
  571. auto InstNamer::NamingContext::AddIntOrFloatTypeName(char type_literal_prefix,
  572. InstId bit_width_id,
  573. llvm::StringRef suffix)
  574. -> void {
  575. RawStringOstream out;
  576. out << type_literal_prefix;
  577. if (auto bit_width = sem_ir().insts().TryGetAs<IntValue>(bit_width_id)) {
  578. out << sem_ir().ints().Get(bit_width->int_id);
  579. } else {
  580. out << "N";
  581. }
  582. out << suffix;
  583. AddInstName(out.TakeStr());
  584. }
  585. auto InstNamer::NamingContext::AddWitnessTableName(InstId witness_table_inst_id,
  586. std::string name) -> void {
  587. auto witness_table =
  588. sem_ir().insts().GetAs<ImplWitnessTable>(witness_table_inst_id);
  589. if (!witness_table.impl_id.has_value()) {
  590. // TODO: The witness comes from a facet value. Can we get the
  591. // interface names from it? Store the facet value instruction in the
  592. // table?
  593. AddInstName(name);
  594. return;
  595. }
  596. const auto& impl = sem_ir().impls().Get(witness_table.impl_id);
  597. auto name_id = sem_ir().interfaces().Get(impl.interface.interface_id).name_id;
  598. std::string suffix = llvm::formatv(".{}", name);
  599. AddInstNameId(name_id, suffix);
  600. }
  601. auto InstNamer::NamingContext::NameInst() -> void {
  602. CARBON_KIND_SWITCH(inst_) {
  603. case AddrOf::Kind: {
  604. AddInstName("addr");
  605. return;
  606. }
  607. case ArrayType::Kind: {
  608. // TODO: Can we figure out the name of the type this is an array of?
  609. AddInstName("array_type");
  610. return;
  611. }
  612. case CARBON_KIND(AssociatedConstantDecl inst): {
  613. AddEntityNameAndMaybePush(inst.assoc_const_id);
  614. PushBlockId(inst_namer_->GetScopeFor(inst.assoc_const_id),
  615. inst.decl_block_id);
  616. return;
  617. }
  618. case CARBON_KIND(AssociatedEntity inst): {
  619. RawStringOstream out;
  620. out << "assoc" << inst.index.index;
  621. AddInstName(out.TakeStr());
  622. return;
  623. }
  624. case CARBON_KIND(AssociatedEntityType inst): {
  625. AddEntityNameAndMaybePush(inst.interface_id, ".assoc_type");
  626. return;
  627. }
  628. case BindAlias::Kind:
  629. case BindName::Kind:
  630. case BindSymbolicName::Kind:
  631. case ExportDecl::Kind: {
  632. auto inst = inst_.As<AnyBindNameOrExportDecl>();
  633. AddInstNameId(sem_ir().entity_names().Get(inst.entity_name_id).name_id);
  634. return;
  635. }
  636. case BindingPattern::Kind:
  637. case SymbolicBindingPattern::Kind: {
  638. auto inst = inst_.As<AnyBindingPattern>();
  639. auto name_id = NameId::Underscore;
  640. if (inst.entity_name_id.has_value()) {
  641. name_id = sem_ir().entity_names().Get(inst.entity_name_id).name_id;
  642. }
  643. AddInstNameId(name_id, ".patt");
  644. return;
  645. }
  646. case CARBON_KIND(BoolLiteral inst): {
  647. if (inst.value.ToBool()) {
  648. AddInstName("true");
  649. } else {
  650. AddInstName("false");
  651. }
  652. return;
  653. }
  654. case CARBON_KIND(BoundMethod inst): {
  655. auto type_id = sem_ir().insts().Get(inst.function_decl_id).type_id();
  656. if (auto fn_ty = sem_ir().types().TryGetAs<FunctionType>(type_id)) {
  657. AddEntityNameAndMaybePush(fn_ty->function_id, ".bound");
  658. } else {
  659. AddInstName("bound_method");
  660. }
  661. return;
  662. }
  663. case Branch::Kind:
  664. case BranchIf::Kind:
  665. case BranchWithArg::Kind: {
  666. auto branch = inst_.As<AnyBranch>();
  667. inst_namer_->AddBlockLabel(scope_id_, LocId(inst_id_), branch);
  668. return;
  669. }
  670. case CARBON_KIND(Call inst): {
  671. auto callee_function = GetCalleeFunction(sem_ir(), inst.callee_id);
  672. if (!callee_function.function_id.has_value()) {
  673. AddInstName("");
  674. return;
  675. }
  676. AddEntityNameAndMaybePush(callee_function.function_id, ".call");
  677. return;
  678. }
  679. case CARBON_KIND(ClassDecl inst): {
  680. AddEntityNameAndMaybePush(inst.class_id, ".decl");
  681. auto class_scope_id = inst_namer_->GetScopeFor(inst.class_id);
  682. PushBlockId(class_scope_id, inst.decl_block_id);
  683. return;
  684. }
  685. case CARBON_KIND(ClassType inst): {
  686. if (auto literal_info = TypeLiteralInfo::ForType(sem_ir(), inst);
  687. literal_info.is_valid()) {
  688. AddInstName(literal_info.GetLiteralAsString(sem_ir()));
  689. } else {
  690. AddEntityNameAndMaybePush(inst.class_id);
  691. }
  692. return;
  693. }
  694. case CompleteTypeWitness::Kind: {
  695. // TODO: Can we figure out the name of the type this is a witness for?
  696. AddInstName("complete_type");
  697. return;
  698. }
  699. case CARBON_KIND(VtableDecl inst): {
  700. const auto& vtable = sem_ir().vtables().Get(inst.vtable_id);
  701. inst_namer_->MaybePushEntity(inst.vtable_id);
  702. if (inst_namer_->GetScopeFor(vtable.class_id) == scope_id_) {
  703. inst_namer_->MaybePushEntity(vtable.class_id);
  704. AddInstName("vtable_decl");
  705. } else {
  706. AddEntityNameAndMaybePush(vtable.class_id, ".vtable_decl");
  707. }
  708. return;
  709. }
  710. case CARBON_KIND(VtablePtr inst): {
  711. const auto& vtable = sem_ir().vtables().Get(inst.vtable_id);
  712. inst_namer_->MaybePushEntity(inst.vtable_id);
  713. AddEntityNameAndMaybePush(vtable.class_id, ".vtable_ptr");
  714. return;
  715. }
  716. case ConstType::Kind: {
  717. // TODO: Can we figure out the name of the type argument?
  718. AddInstName("const");
  719. return;
  720. }
  721. case CARBON_KIND(FacetAccessType inst): {
  722. auto name_id = NameId::None;
  723. if (auto name =
  724. sem_ir().insts().TryGetAs<NameRef>(inst.facet_value_inst_id)) {
  725. name_id = name->name_id;
  726. } else if (auto symbolic = sem_ir().insts().TryGetAs<BindSymbolicName>(
  727. inst.facet_value_inst_id)) {
  728. name_id = sem_ir().entity_names().Get(symbolic->entity_name_id).name_id;
  729. }
  730. if (name_id.has_value()) {
  731. AddInstNameId(name_id, ".as_type");
  732. } else {
  733. AddInstName("as_type");
  734. }
  735. return;
  736. }
  737. case CARBON_KIND(FacetType inst): {
  738. const auto& facet_type_info =
  739. sem_ir().facet_types().Get(inst.facet_type_id);
  740. bool has_where = facet_type_info.other_requirements ||
  741. !facet_type_info.builtin_constraint_mask.empty() ||
  742. !facet_type_info.self_impls_constraints.empty() ||
  743. !facet_type_info.rewrite_constraints.empty();
  744. if (facet_type_info.extend_constraints.size() == 1) {
  745. AddEntityNameAndMaybePush(
  746. facet_type_info.extend_constraints.front().interface_id,
  747. has_where ? "_where.type" : ".type");
  748. } else if (facet_type_info.extend_constraints.empty()) {
  749. AddInstName(has_where ? "type_where" : "type");
  750. } else {
  751. AddInstName("facet_type");
  752. }
  753. return;
  754. }
  755. case CARBON_KIND(FacetValue inst): {
  756. if (auto facet_type =
  757. sem_ir().types().TryGetAs<FacetType>(inst.type_id)) {
  758. const auto& facet_type_info =
  759. sem_ir().facet_types().Get(facet_type->facet_type_id);
  760. if (auto interface = facet_type_info.TryAsSingleInterface()) {
  761. AddEntityNameAndMaybePush(interface->interface_id, ".facet");
  762. return;
  763. }
  764. }
  765. AddInstName("facet_value");
  766. return;
  767. }
  768. case CARBON_KIND(FloatType inst): {
  769. AddIntOrFloatTypeName('f', inst.bit_width_id);
  770. return;
  771. }
  772. case FloatLiteralValue::Kind:
  773. case FloatValue::Kind: {
  774. AddInstName("float");
  775. return;
  776. }
  777. case CARBON_KIND(FunctionDecl inst): {
  778. AddEntityNameAndMaybePush(inst.function_id, ".decl");
  779. auto function_scope_id = inst_namer_->GetScopeFor(inst.function_id);
  780. PushBlockId(function_scope_id, inst.decl_block_id);
  781. return;
  782. }
  783. case CARBON_KIND(FunctionType inst): {
  784. AddEntityNameAndMaybePush(inst.function_id, ".type");
  785. return;
  786. }
  787. case CARBON_KIND(GenericClassType inst): {
  788. AddEntityNameAndMaybePush(inst.class_id, ".type");
  789. return;
  790. }
  791. case CARBON_KIND(GenericInterfaceType inst): {
  792. AddEntityNameAndMaybePush(inst.interface_id, ".type");
  793. return;
  794. }
  795. case CARBON_KIND(ImplDecl inst): {
  796. // `impl` declarations aren't named because they aren't added to any
  797. // namespace, and so aren't referenced directly.
  798. inst_namer_->MaybePushEntity(inst.impl_id);
  799. PushBlockId(inst_namer_->GetScopeFor(inst.impl_id), inst.decl_block_id);
  800. return;
  801. }
  802. case CARBON_KIND(LookupImplWitness inst): {
  803. const auto& interface =
  804. sem_ir().specific_interfaces().Get(inst.query_specific_interface_id);
  805. AddEntityNameAndMaybePush(interface.interface_id, ".lookup_impl_witness");
  806. return;
  807. }
  808. case CARBON_KIND(ImplWitness inst): {
  809. AddWitnessTableName(inst.witness_table_id, "impl_witness");
  810. return;
  811. }
  812. case CARBON_KIND(ImplWitnessAccess inst): {
  813. // TODO: Include information about the impl?
  814. RawStringOstream out;
  815. out << "impl.elem" << inst.index.index;
  816. AddInstName(out.TakeStr());
  817. return;
  818. }
  819. case CARBON_KIND(ImplWitnessAccessSubstituted inst): {
  820. // TODO: Include information about the impl?
  821. RawStringOstream out;
  822. auto access = sem_ir().insts().GetAs<ImplWitnessAccess>(
  823. inst.impl_witness_access_id);
  824. out << "impl.elem" << access.index.index << ".subst";
  825. AddInstName(out.TakeStr());
  826. return;
  827. }
  828. case ImplWitnessAssociatedConstant::Kind: {
  829. AddInstName("impl_witness_assoc_constant");
  830. return;
  831. }
  832. case ImplWitnessTable::Kind: {
  833. AddWitnessTableName(inst_id_, "impl_witness_table");
  834. return;
  835. }
  836. case ImportCppDecl::Kind: {
  837. AddInstName("Cpp.import_cpp");
  838. return;
  839. }
  840. case CARBON_KIND(ImportDecl inst): {
  841. if (inst.package_id.has_value()) {
  842. AddInstNameId(inst.package_id, ".import");
  843. } else {
  844. AddInstName("default.import");
  845. }
  846. return;
  847. }
  848. case ImportRefUnloaded::Kind:
  849. case ImportRefLoaded::Kind: {
  850. // Build the base import name: <package>.<entity-name>
  851. RawStringOstream out;
  852. auto inst = inst_.As<AnyImportRef>();
  853. auto import_ir_inst =
  854. sem_ir().import_ir_insts().Get(inst.import_ir_inst_id);
  855. const auto& import_ir =
  856. *sem_ir().import_irs().Get(import_ir_inst.ir_id()).sem_ir;
  857. auto package_id = import_ir.package_id();
  858. if (auto ident_id = package_id.AsIdentifierId(); ident_id.has_value()) {
  859. out << import_ir.identifiers().Get(ident_id);
  860. } else {
  861. out << package_id.AsSpecialName();
  862. }
  863. out << ".";
  864. // Add entity name if available.
  865. if (inst.entity_name_id.has_value()) {
  866. auto name_id = sem_ir().entity_names().Get(inst.entity_name_id).name_id;
  867. out << sem_ir().names().GetIRBaseName(name_id);
  868. } else {
  869. out << "import_ref";
  870. }
  871. AddInstName(out.TakeStr());
  872. // When building import refs, we frequently add instructions without
  873. // a block. Constants that refer to them need to be separately
  874. // named.
  875. auto const_id = sem_ir().constant_values().Get(inst_id_);
  876. if (const_id.has_value() && const_id.is_concrete()) {
  877. auto const_inst_id = sem_ir().constant_values().GetInstId(const_id);
  878. if (!inst_namer_->insts_[const_inst_id.index].second) {
  879. inst_namer_->PushBlockInsts(ScopeId::Imports, const_inst_id);
  880. }
  881. }
  882. return;
  883. }
  884. case CARBON_KIND(InstValue inst): {
  885. inst_namer_->PushBlockInsts(scope_id_, inst.inst_id);
  886. AddInstName(
  887. ("inst." + sem_ir().insts().Get(inst.inst_id).kind().ir_name())
  888. .str());
  889. return;
  890. }
  891. case CARBON_KIND(InterfaceDecl inst): {
  892. AddEntityNameAndMaybePush(inst.interface_id, ".decl");
  893. auto interface_scope_id = inst_namer_->GetScopeFor(inst.interface_id);
  894. PushBlockId(interface_scope_id, inst.decl_block_id);
  895. return;
  896. }
  897. case CARBON_KIND(IntType inst): {
  898. AddIntOrFloatTypeName(inst.int_kind == IntKind::Signed ? 'i' : 'u',
  899. inst.bit_width_id, ".builtin");
  900. return;
  901. }
  902. case CARBON_KIND(IntValue inst): {
  903. RawStringOstream out;
  904. out << "int_" << sem_ir().ints().Get(inst.int_id);
  905. AddInstName(out.TakeStr());
  906. return;
  907. }
  908. case CARBON_KIND(NameBindingDecl inst): {
  909. PushBlockId(scope_id_, inst.pattern_block_id);
  910. return;
  911. }
  912. case CARBON_KIND(NameRef inst): {
  913. AddInstNameId(inst.name_id, ".ref");
  914. return;
  915. }
  916. // The namespace is specified here due to the name conflict.
  917. case CARBON_KIND(SemIR::Namespace inst): {
  918. AddInstNameId(sem_ir().name_scopes().Get(inst.name_scope_id).name_id());
  919. return;
  920. }
  921. case OutParam::Kind:
  922. case RefParam::Kind:
  923. case ValueParam::Kind: {
  924. AddInstNameId(inst_.As<AnyParam>().pretty_name_id, ".param");
  925. return;
  926. }
  927. case OutParamPattern::Kind:
  928. case RefParamPattern::Kind:
  929. case ValueParamPattern::Kind: {
  930. AddInstNameId(GetPrettyNameFromPatternId(sem_ir(), inst_id_),
  931. ".param_patt");
  932. return;
  933. }
  934. case PatternType::Kind: {
  935. AddInstName("pattern_type");
  936. return;
  937. }
  938. case PointerType::Kind: {
  939. AddInstName("ptr");
  940. return;
  941. }
  942. case RequireCompleteType::Kind: {
  943. AddInstName("require_complete");
  944. return;
  945. }
  946. case ReturnSlotPattern::Kind: {
  947. AddInstNameId(NameId::ReturnSlot, ".patt");
  948. return;
  949. }
  950. case CARBON_KIND(SpecificFunction inst): {
  951. auto type_id = sem_ir().insts().Get(inst.callee_id).type_id();
  952. if (auto fn_ty = sem_ir().types().TryGetAs<FunctionType>(type_id)) {
  953. AddEntityNameAndMaybePush(fn_ty->function_id, ".specific_fn");
  954. } else {
  955. AddInstName("specific_fn");
  956. }
  957. return;
  958. }
  959. case CARBON_KIND(SpecificImplFunction inst): {
  960. auto type_id = sem_ir().insts().Get(inst.callee_id).type_id();
  961. if (auto fn_ty = sem_ir().types().TryGetAs<FunctionType>(type_id)) {
  962. AddEntityNameAndMaybePush(fn_ty->function_id, ".specific_impl_fn");
  963. } else {
  964. AddInstName("specific_impl_fn");
  965. }
  966. return;
  967. }
  968. case ReturnSlot::Kind: {
  969. AddInstNameId(NameId::ReturnSlot);
  970. return;
  971. }
  972. case CARBON_KIND(SpliceBlock inst): {
  973. PushBlockId(scope_id_, inst.block_id);
  974. AddInstName("");
  975. return;
  976. }
  977. case StringLiteral::Kind: {
  978. AddInstName("str");
  979. return;
  980. }
  981. case CARBON_KIND(StructValue inst): {
  982. if (auto fn_ty = sem_ir().types().TryGetAs<FunctionType>(inst.type_id)) {
  983. AddEntityNameAndMaybePush(fn_ty->function_id);
  984. } else if (auto class_ty =
  985. sem_ir().types().TryGetAs<ClassType>(inst.type_id)) {
  986. AddEntityNameAndMaybePush(class_ty->class_id, ".val");
  987. } else if (auto generic_class_ty =
  988. sem_ir().types().TryGetAs<GenericClassType>(
  989. inst.type_id)) {
  990. AddEntityNameAndMaybePush(generic_class_ty->class_id, ".generic");
  991. } else if (auto generic_interface_ty =
  992. sem_ir().types().TryGetAs<GenericInterfaceType>(
  993. inst.type_id)) {
  994. AddInstNameId(sem_ir()
  995. .interfaces()
  996. .Get(generic_interface_ty->interface_id)
  997. .name_id,
  998. ".generic");
  999. } else {
  1000. if (sem_ir().inst_blocks().Get(inst.elements_id).empty()) {
  1001. AddInstName("empty_struct");
  1002. } else {
  1003. AddInstName("struct");
  1004. }
  1005. }
  1006. return;
  1007. }
  1008. case CARBON_KIND(StructType inst): {
  1009. const auto& fields = sem_ir().struct_type_fields().Get(inst.fields_id);
  1010. if (fields.empty()) {
  1011. AddInstName("empty_struct_type");
  1012. return;
  1013. }
  1014. std::string name = "struct_type";
  1015. for (auto field : fields) {
  1016. name += ".";
  1017. name += sem_ir().names().GetIRBaseName(field.name_id).str();
  1018. }
  1019. AddInstName(std::move(name));
  1020. return;
  1021. }
  1022. case CARBON_KIND(TupleAccess inst): {
  1023. RawStringOstream out;
  1024. out << "tuple.elem" << inst.index.index;
  1025. AddInstName(out.TakeStr());
  1026. return;
  1027. }
  1028. case CARBON_KIND(TupleType inst): {
  1029. if (inst.type_elements_id == InstBlockId::Empty) {
  1030. AddInstName("empty_tuple.type");
  1031. } else {
  1032. AddInstName("tuple.type");
  1033. }
  1034. return;
  1035. }
  1036. case CARBON_KIND(TupleValue inst): {
  1037. if (sem_ir().types().Is<ArrayType>(inst.type_id)) {
  1038. AddInstName("array");
  1039. } else if (inst.elements_id == InstBlockId::Empty) {
  1040. AddInstName("empty_tuple");
  1041. } else {
  1042. AddInstName("tuple");
  1043. }
  1044. return;
  1045. }
  1046. case CARBON_KIND(UnboundElementType inst): {
  1047. if (auto class_ty =
  1048. sem_ir().insts().TryGetAs<ClassType>(inst.class_type_inst_id)) {
  1049. AddEntityNameAndMaybePush(class_ty->class_id, ".elem");
  1050. } else {
  1051. AddInstName("elem_type");
  1052. }
  1053. return;
  1054. }
  1055. case VarPattern::Kind: {
  1056. AddInstNameId(GetPrettyNameFromPatternId(sem_ir(), inst_id_),
  1057. ".var_patt");
  1058. return;
  1059. }
  1060. case CARBON_KIND(VarStorage inst): {
  1061. if (inst.pattern_id.has_value()) {
  1062. AddInstNameId(GetPrettyNameFromPatternId(sem_ir(), inst.pattern_id),
  1063. ".var");
  1064. } else {
  1065. AddInstName("var");
  1066. }
  1067. return;
  1068. }
  1069. default: {
  1070. // Sequentially number all remaining values.
  1071. if (inst_.kind().has_type()) {
  1072. AddInstName("");
  1073. }
  1074. return;
  1075. }
  1076. }
  1077. }
  1078. } // namespace Carbon::SemIR