inst_namer.cpp 28 KB

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