inst_namer.cpp 31 KB

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