inst_namer.cpp 36 KB

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