inst_namer.cpp 29 KB

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