inst_namer.cpp 33 KB

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