inst_namer.cpp 28 KB

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