inst_namer.cpp 38 KB

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