inst_namer.cpp 33 KB

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