inst_namer.cpp 45 KB

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