inst_namer.cpp 33 KB

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