inst_namer.cpp 42 KB

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