inst_namer.cpp 31 KB

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