inst_namer.cpp 33 KB

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