formatter.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  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/formatter.h"
  5. #include "common/ostream.h"
  6. #include "llvm/ADT/Sequence.h"
  7. #include "llvm/ADT/StringExtras.h"
  8. #include "llvm/Support/SaveAndRestore.h"
  9. #include "toolchain/base/kind_switch.h"
  10. #include "toolchain/base/value_store.h"
  11. #include "toolchain/lex/tokenized_buffer.h"
  12. #include "toolchain/parse/tree.h"
  13. #include "toolchain/sem_ir/builtin_function_kind.h"
  14. #include "toolchain/sem_ir/function.h"
  15. #include "toolchain/sem_ir/ids.h"
  16. #include "toolchain/sem_ir/inst_namer.h"
  17. #include "toolchain/sem_ir/name_scope.h"
  18. #include "toolchain/sem_ir/typed_insts.h"
  19. namespace Carbon::SemIR {
  20. // Formatter for printing textual Semantics IR.
  21. class Formatter {
  22. public:
  23. enum class AddSpace : bool { Before, After };
  24. explicit Formatter(const Lex::TokenizedBuffer& tokenized_buffer,
  25. const Parse::Tree& parse_tree, const File& sem_ir,
  26. llvm::raw_ostream& out)
  27. : sem_ir_(sem_ir),
  28. out_(out),
  29. inst_namer_(tokenized_buffer, parse_tree, sem_ir) {}
  30. // Prints the SemIR.
  31. //
  32. // Constants are printed first and may be referenced by later sections,
  33. // including file-scoped instructions. The file scope may contain entity
  34. // declarations which are defined later, such as classes.
  35. auto Format() -> void {
  36. out_ << "--- " << sem_ir_.filename() << "\n\n";
  37. FormatConstants();
  38. FormatImportRefs();
  39. out_ << inst_namer_.GetScopeName(InstNamer::ScopeId::File) << " ";
  40. OpenBrace();
  41. // TODO: Handle the case where there are multiple top-level instruction
  42. // blocks. For example, there may be branching in the initializer of a
  43. // global or a type expression.
  44. if (auto block_id = sem_ir_.top_inst_block_id(); block_id.is_valid()) {
  45. llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeId::File);
  46. FormatCodeBlock(block_id);
  47. }
  48. CloseBrace();
  49. out_ << '\n';
  50. for (int i : llvm::seq(sem_ir_.interfaces().size())) {
  51. FormatInterface(InterfaceId(i));
  52. }
  53. for (int i : llvm::seq(sem_ir_.impls().size())) {
  54. FormatImpl(ImplId(i));
  55. }
  56. for (int i : llvm::seq(sem_ir_.classes().size())) {
  57. FormatClass(ClassId(i));
  58. }
  59. for (int i : llvm::seq(sem_ir_.functions().size())) {
  60. FormatFunction(FunctionId(i));
  61. }
  62. // End-of-file newline.
  63. out_ << "\n";
  64. }
  65. // Begins a braced block. Writes an open brace, and prepares to insert a
  66. // newline after it if the braced block is non-empty.
  67. auto OpenBrace() -> void {
  68. // Put the constant value of an instruction before any braced block, rather
  69. // than at the end.
  70. FormatPendingConstantValue(AddSpace::After);
  71. out_ << '{';
  72. indent_ += 2;
  73. after_open_brace_ = true;
  74. }
  75. // Ends a braced block by writing a close brace.
  76. auto CloseBrace() -> void {
  77. indent_ -= 2;
  78. if (!after_open_brace_) {
  79. Indent();
  80. }
  81. out_ << '}';
  82. after_open_brace_ = false;
  83. }
  84. // Adds beginning-of-line indentation. If we're at the start of a braced
  85. // block, first starts a new line.
  86. auto Indent(int offset = 0) -> void {
  87. if (after_open_brace_) {
  88. out_ << '\n';
  89. after_open_brace_ = false;
  90. }
  91. out_.indent(indent_ + offset);
  92. }
  93. // Adds beginning-of-label indentation. This is one level less than normal
  94. // indentation. Labels also get a preceding blank line unless they're at the
  95. // start of a block.
  96. auto IndentLabel() -> void {
  97. CARBON_CHECK(indent_ >= 2);
  98. if (!after_open_brace_) {
  99. out_ << '\n';
  100. }
  101. Indent(-2);
  102. }
  103. // Wraps the current line, prior to some text that we expect to be quite long
  104. // and more readable on a separate line. This is indented two levels more than
  105. // the ambient text.
  106. auto WrapLine() -> void {
  107. out_ << '\n';
  108. Indent(4);
  109. }
  110. auto FormatConstants() -> void {
  111. if (!sem_ir_.constants().size()) {
  112. return;
  113. }
  114. llvm::SaveAndRestore constants_scope(scope_, InstNamer::ScopeId::Constants);
  115. out_ << inst_namer_.GetScopeName(InstNamer::ScopeId::Constants) << " ";
  116. OpenBrace();
  117. FormatCodeBlock(sem_ir_.constants().array_ref());
  118. CloseBrace();
  119. out_ << "\n\n";
  120. }
  121. auto FormatImportRefs() -> void {
  122. auto import_refs = sem_ir_.inst_blocks().Get(InstBlockId::ImportRefs);
  123. if (import_refs.empty()) {
  124. return;
  125. }
  126. llvm::SaveAndRestore scope(scope_, InstNamer::ScopeId::ImportRefs);
  127. out_ << inst_namer_.GetScopeName(InstNamer::ScopeId::ImportRefs) << " ";
  128. OpenBrace();
  129. FormatCodeBlock(import_refs);
  130. CloseBrace();
  131. out_ << "\n\n";
  132. }
  133. auto FormatClass(ClassId id) -> void {
  134. const Class& class_info = sem_ir_.classes().Get(id);
  135. out_ << "\nclass ";
  136. FormatClassName(id);
  137. if (class_info.generic_id.is_valid()) {
  138. FormatGeneric(class_info.generic_id);
  139. }
  140. llvm::SaveAndRestore class_scope(scope_, inst_namer_.GetScopeFor(id));
  141. if (class_info.scope_id.is_valid()) {
  142. out_ << ' ';
  143. OpenBrace();
  144. FormatCodeBlock(class_info.body_block_id);
  145. FormatNameScope(class_info.scope_id, "!members:\n");
  146. CloseBrace();
  147. out_ << '\n';
  148. } else {
  149. out_ << ";\n";
  150. }
  151. }
  152. auto FormatInterface(InterfaceId id) -> void {
  153. const Interface& interface_info = sem_ir_.interfaces().Get(id);
  154. out_ << "\ninterface ";
  155. FormatInterfaceName(id);
  156. if (interface_info.generic_id.is_valid()) {
  157. FormatGeneric(interface_info.generic_id);
  158. }
  159. llvm::SaveAndRestore interface_scope(scope_, inst_namer_.GetScopeFor(id));
  160. if (interface_info.scope_id.is_valid()) {
  161. out_ << ' ';
  162. OpenBrace();
  163. FormatCodeBlock(interface_info.body_block_id);
  164. // Always include the !members label because we always list the witness in
  165. // this section.
  166. IndentLabel();
  167. out_ << "!members:\n";
  168. FormatNameScope(interface_info.scope_id);
  169. Indent();
  170. out_ << "witness = ";
  171. FormatArg(interface_info.associated_entities_id);
  172. out_ << "\n";
  173. CloseBrace();
  174. out_ << '\n';
  175. } else {
  176. out_ << ";\n";
  177. }
  178. }
  179. auto FormatImpl(ImplId id) -> void {
  180. const Impl& impl_info = sem_ir_.impls().Get(id);
  181. out_ << "\nimpl ";
  182. FormatImplName(id);
  183. out_ << ": ";
  184. // TODO: Include the deduced parameter list if present.
  185. FormatType(impl_info.self_id);
  186. out_ << " as ";
  187. FormatType(impl_info.constraint_id);
  188. llvm::SaveAndRestore impl_scope(scope_, inst_namer_.GetScopeFor(id));
  189. if (impl_info.scope_id.is_valid()) {
  190. out_ << ' ';
  191. OpenBrace();
  192. FormatCodeBlock(impl_info.body_block_id);
  193. // Print the !members label even if the name scope is empty because we
  194. // always list the witness in this section.
  195. IndentLabel();
  196. out_ << "!members:\n";
  197. FormatNameScope(impl_info.scope_id);
  198. Indent();
  199. out_ << "witness = ";
  200. FormatArg(impl_info.witness_id);
  201. out_ << "\n";
  202. CloseBrace();
  203. out_ << '\n';
  204. } else {
  205. out_ << ";\n";
  206. }
  207. }
  208. auto FormatFunction(FunctionId id) -> void {
  209. const Function& fn = sem_ir_.functions().Get(id);
  210. out_ << "\n";
  211. if (fn.is_extern) {
  212. out_ << "extern ";
  213. }
  214. out_ << "fn ";
  215. FormatFunctionName(id);
  216. llvm::SaveAndRestore function_scope(scope_, inst_namer_.GetScopeFor(id));
  217. if (fn.implicit_param_refs_id.is_valid()) {
  218. out_ << "[";
  219. FormatParamList(fn.implicit_param_refs_id);
  220. out_ << "]";
  221. }
  222. if (fn.param_refs_id.is_valid()) {
  223. out_ << "(";
  224. FormatParamList(fn.param_refs_id);
  225. out_ << ")";
  226. }
  227. if (fn.return_storage_id.is_valid()) {
  228. out_ << " -> ";
  229. if (!fn.body_block_ids.empty() && fn.has_return_slot()) {
  230. FormatInstName(fn.return_storage_id);
  231. out_ << ": ";
  232. }
  233. FormatType(sem_ir_.insts().Get(fn.return_storage_id).type_id());
  234. }
  235. if (fn.builtin_kind != BuiltinFunctionKind::None) {
  236. out_ << " = \"";
  237. out_.write_escaped(fn.builtin_kind.name(),
  238. /*UseHexEscapes=*/true);
  239. out_ << "\"";
  240. }
  241. if (fn.generic_id.is_valid()) {
  242. FormatGeneric(fn.generic_id);
  243. }
  244. if (!fn.body_block_ids.empty()) {
  245. out_ << ' ';
  246. OpenBrace();
  247. for (auto block_id : fn.body_block_ids) {
  248. IndentLabel();
  249. FormatLabel(block_id);
  250. out_ << ":\n";
  251. FormatCodeBlock(block_id);
  252. }
  253. CloseBrace();
  254. out_ << '\n';
  255. } else {
  256. out_ << ";\n";
  257. }
  258. }
  259. auto FormatGeneric(GenericId generic_id) -> void {
  260. WrapLine();
  261. out_ << "generic [";
  262. FormatParamList(sem_ir_.generics().Get(generic_id).bindings_id);
  263. out_ << "]";
  264. }
  265. auto FormatParamList(InstBlockId param_refs_id) -> void {
  266. llvm::ListSeparator sep;
  267. for (InstId param_id : sem_ir_.inst_blocks().Get(param_refs_id)) {
  268. out_ << sep;
  269. if (!param_id.is_valid()) {
  270. out_ << "invalid";
  271. continue;
  272. }
  273. if (auto addr = sem_ir_.insts().TryGetAs<SemIR::AddrPattern>(param_id)) {
  274. out_ << "addr ";
  275. param_id = addr->inner_id;
  276. }
  277. FormatInstName(param_id);
  278. out_ << ": ";
  279. FormatType(sem_ir_.insts().Get(param_id).type_id());
  280. }
  281. }
  282. auto FormatCodeBlock(InstBlockId block_id) -> void {
  283. if (block_id.is_valid()) {
  284. FormatCodeBlock(sem_ir_.inst_blocks().Get(block_id));
  285. }
  286. }
  287. auto FormatCodeBlock(llvm::ArrayRef<InstId> block) -> void {
  288. for (const InstId inst_id : block) {
  289. FormatInstruction(inst_id);
  290. }
  291. }
  292. auto FormatTrailingBlock(InstBlockId block_id) -> void {
  293. out_ << ' ';
  294. OpenBrace();
  295. FormatCodeBlock(block_id);
  296. CloseBrace();
  297. }
  298. auto FormatNameScope(NameScopeId id, llvm::StringRef label = "") -> void {
  299. const auto& scope = sem_ir_.name_scopes().Get(id);
  300. if (scope.names.empty() && scope.extended_scopes.empty() &&
  301. !scope.has_error) {
  302. // Name scope is empty.
  303. return;
  304. }
  305. if (!label.empty()) {
  306. IndentLabel();
  307. out_ << label;
  308. }
  309. for (auto [name_id, inst_id, access_kind] : scope.names) {
  310. Indent();
  311. out_ << ".";
  312. FormatName(name_id);
  313. switch (access_kind) {
  314. case SemIR::AccessKind::Public:
  315. break;
  316. case SemIR::AccessKind::Protected:
  317. out_ << " [protected]";
  318. break;
  319. case SemIR::AccessKind::Private:
  320. out_ << " [private]";
  321. break;
  322. }
  323. out_ << " = ";
  324. FormatInstName(inst_id);
  325. out_ << "\n";
  326. }
  327. for (auto extended_scope_id : scope.extended_scopes) {
  328. // TODO: Print this scope in a better way.
  329. Indent();
  330. out_ << "extend " << extended_scope_id << "\n";
  331. }
  332. if (scope.has_error) {
  333. Indent();
  334. out_ << "has_error\n";
  335. }
  336. }
  337. auto FormatInstruction(InstId inst_id) -> void {
  338. if (!inst_id.is_valid()) {
  339. Indent();
  340. out_ << "invalid\n";
  341. return;
  342. }
  343. FormatInstruction(inst_id, sem_ir_.insts().Get(inst_id));
  344. }
  345. auto FormatInstruction(InstId inst_id, Inst inst) -> void {
  346. CARBON_KIND_SWITCH(inst) {
  347. #define CARBON_SEM_IR_INST_KIND(InstT) \
  348. case CARBON_KIND(InstT typed_inst): { \
  349. FormatInstruction(inst_id, typed_inst); \
  350. break; \
  351. }
  352. #include "toolchain/sem_ir/inst_kind.def"
  353. }
  354. }
  355. template <typename InstT>
  356. auto FormatInstruction(InstId inst_id, InstT inst) -> void {
  357. Indent();
  358. FormatInstructionLHS(inst_id, inst);
  359. out_ << InstT::Kind.ir_name();
  360. pending_constant_value_ = sem_ir_.constant_values().Get(inst_id);
  361. pending_constant_value_is_self_ =
  362. sem_ir_.constant_values().GetInstId(pending_constant_value_) == inst_id;
  363. FormatInstructionRHS(inst);
  364. FormatPendingConstantValue(AddSpace::Before);
  365. out_ << "\n";
  366. }
  367. // Don't print a constant for ImportRefUnloaded.
  368. auto FormatInstruction(InstId inst_id, ImportRefUnloaded inst) -> void {
  369. Indent();
  370. FormatInstructionLHS(inst_id, inst);
  371. out_ << ImportRefUnloaded::Kind.ir_name();
  372. FormatInstructionRHS(inst);
  373. out_ << "\n";
  374. }
  375. // If there is a pending constant value attached to the current instruction,
  376. // print it now and clear it out. The constant value gets printed before the
  377. // first braced block argument, or at the end of the instruction if there are
  378. // no such arguments.
  379. auto FormatPendingConstantValue(AddSpace space_where) -> void {
  380. if (pending_constant_value_ == ConstantId::NotConstant) {
  381. return;
  382. }
  383. if (space_where == AddSpace::Before) {
  384. out_ << ' ';
  385. }
  386. out_ << '[';
  387. if (pending_constant_value_.is_valid()) {
  388. out_ << (pending_constant_value_.is_symbolic() ? "symbolic" : "template");
  389. if (!pending_constant_value_is_self_) {
  390. out_ << " = ";
  391. FormatInstName(
  392. sem_ir_.constant_values().GetInstId(pending_constant_value_));
  393. // TODO: For a symbolic constant, include the generic and index.
  394. }
  395. } else {
  396. out_ << pending_constant_value_;
  397. }
  398. out_ << ']';
  399. if (space_where == AddSpace::After) {
  400. out_ << ' ';
  401. }
  402. pending_constant_value_ = ConstantId::NotConstant;
  403. }
  404. auto FormatInstructionLHS(InstId inst_id, Inst inst) -> void {
  405. switch (inst.kind().value_kind()) {
  406. case InstValueKind::Typed:
  407. FormatInstName(inst_id);
  408. out_ << ": ";
  409. switch (GetExprCategory(sem_ir_, inst_id)) {
  410. case ExprCategory::NotExpr:
  411. case ExprCategory::Error:
  412. case ExprCategory::Value:
  413. case ExprCategory::Mixed:
  414. break;
  415. case ExprCategory::DurableRef:
  416. case ExprCategory::EphemeralRef:
  417. out_ << "ref ";
  418. break;
  419. case ExprCategory::Initializing:
  420. out_ << "init ";
  421. break;
  422. }
  423. FormatType(inst.type_id());
  424. out_ << " = ";
  425. break;
  426. case InstValueKind::None:
  427. break;
  428. }
  429. }
  430. // Format ImportDecl with its name.
  431. auto FormatInstructionLHS(InstId inst_id, ImportDecl /*inst*/) -> void {
  432. FormatInstName(inst_id);
  433. out_ << " = ";
  434. }
  435. // Print ImportRefUnloaded with type-like semantics even though it lacks a
  436. // type_id.
  437. auto FormatInstructionLHS(InstId inst_id, ImportRefUnloaded /*inst*/)
  438. -> void {
  439. FormatInstName(inst_id);
  440. out_ << " = ";
  441. }
  442. template <typename InstT>
  443. auto FormatInstructionRHS(InstT inst) -> void {
  444. // By default, an instruction has a comma-separated argument list.
  445. using Info = Internal::InstLikeTypeInfo<InstT>;
  446. if constexpr (Info::NumArgs == 2) {
  447. FormatArgs(Info::template Get<0>(inst), Info::template Get<1>(inst));
  448. } else if constexpr (Info::NumArgs == 1) {
  449. FormatArgs(Info::template Get<0>(inst));
  450. } else {
  451. FormatArgs();
  452. }
  453. }
  454. auto FormatInstructionRHS(BindSymbolicName inst) -> void {
  455. // A BindSymbolicName with no value is a purely symbolic binding, such as
  456. // the `Self` in an interface. Don't print out `invalid` for the value.
  457. if (inst.value_id.is_valid()) {
  458. FormatArgs(inst.bind_name_id, inst.value_id);
  459. } else {
  460. FormatArgs(inst.bind_name_id);
  461. }
  462. }
  463. auto FormatInstructionRHS(BlockArg inst) -> void {
  464. out_ << " ";
  465. FormatLabel(inst.block_id);
  466. }
  467. auto FormatInstructionRHS(Namespace inst) -> void {
  468. if (inst.import_id.is_valid()) {
  469. FormatArgs(inst.import_id, inst.name_scope_id);
  470. } else {
  471. FormatArgs(inst.name_scope_id);
  472. }
  473. }
  474. auto FormatInstruction(InstId /*inst_id*/, BranchIf inst) -> void {
  475. if (!in_terminator_sequence_) {
  476. Indent();
  477. }
  478. out_ << "if ";
  479. FormatInstName(inst.cond_id);
  480. out_ << " " << Branch::Kind.ir_name() << " ";
  481. FormatLabel(inst.target_id);
  482. out_ << " else ";
  483. in_terminator_sequence_ = true;
  484. }
  485. auto FormatInstruction(InstId /*inst_id*/, BranchWithArg inst) -> void {
  486. if (!in_terminator_sequence_) {
  487. Indent();
  488. }
  489. out_ << BranchWithArg::Kind.ir_name() << " ";
  490. FormatLabel(inst.target_id);
  491. out_ << "(";
  492. FormatInstName(inst.arg_id);
  493. out_ << ")\n";
  494. in_terminator_sequence_ = false;
  495. }
  496. auto FormatInstruction(InstId /*inst_id*/, Branch inst) -> void {
  497. if (!in_terminator_sequence_) {
  498. Indent();
  499. }
  500. out_ << Branch::Kind.ir_name() << " ";
  501. FormatLabel(inst.target_id);
  502. out_ << "\n";
  503. in_terminator_sequence_ = false;
  504. }
  505. auto FormatInstructionRHS(Call inst) -> void {
  506. out_ << " ";
  507. FormatArg(inst.callee_id);
  508. if (!inst.args_id.is_valid()) {
  509. out_ << "(<invalid>)";
  510. return;
  511. }
  512. llvm::ArrayRef<InstId> args = sem_ir_.inst_blocks().Get(inst.args_id);
  513. bool has_return_slot = GetInitRepr(sem_ir_, inst.type_id).has_return_slot();
  514. InstId return_slot_id = InstId::Invalid;
  515. if (has_return_slot) {
  516. return_slot_id = args.back();
  517. args = args.drop_back();
  518. }
  519. llvm::ListSeparator sep;
  520. out_ << '(';
  521. for (auto inst_id : args) {
  522. out_ << sep;
  523. FormatArg(inst_id);
  524. }
  525. out_ << ')';
  526. if (has_return_slot) {
  527. FormatReturnSlot(return_slot_id);
  528. }
  529. }
  530. auto FormatInstructionRHS(ArrayInit inst) -> void {
  531. FormatArgs(inst.inits_id);
  532. FormatReturnSlot(inst.dest_id);
  533. }
  534. auto FormatInstructionRHS(InitializeFrom inst) -> void {
  535. FormatArgs(inst.src_id);
  536. FormatReturnSlot(inst.dest_id);
  537. }
  538. auto FormatInstructionRHS(ReturnExpr ret) -> void {
  539. FormatArgs(ret.expr_id);
  540. if (ret.dest_id.is_valid()) {
  541. FormatReturnSlot(ret.dest_id);
  542. }
  543. }
  544. auto FormatInstructionRHS(StructInit init) -> void {
  545. FormatArgs(init.elements_id);
  546. FormatReturnSlot(init.dest_id);
  547. }
  548. auto FormatInstructionRHS(TupleInit init) -> void {
  549. FormatArgs(init.elements_id);
  550. FormatReturnSlot(init.dest_id);
  551. }
  552. auto FormatInstructionRHS(FunctionDecl inst) -> void {
  553. FormatArgs(inst.function_id);
  554. FormatTrailingBlock(inst.decl_block_id);
  555. }
  556. auto FormatInstructionRHS(ClassDecl inst) -> void {
  557. FormatArgs(inst.class_id);
  558. FormatTrailingBlock(inst.decl_block_id);
  559. }
  560. auto FormatInstructionRHS(ClassType inst) -> void {
  561. if (inst.instance_id.is_valid()) {
  562. FormatArgs(inst.class_id, inst.instance_id);
  563. } else {
  564. FormatArgs(inst.class_id);
  565. }
  566. }
  567. auto FormatInstructionRHS(ImplDecl inst) -> void {
  568. FormatArgs(inst.impl_id);
  569. FormatTrailingBlock(inst.decl_block_id);
  570. }
  571. auto FormatInstructionRHS(InterfaceDecl inst) -> void {
  572. FormatArgs(inst.interface_id);
  573. FormatTrailingBlock(inst.decl_block_id);
  574. }
  575. auto FormatInstructionRHS(InterfaceType inst) -> void {
  576. if (inst.instance_id.is_valid()) {
  577. FormatArgs(inst.interface_id, inst.instance_id);
  578. } else {
  579. FormatArgs(inst.interface_id);
  580. }
  581. }
  582. auto FormatInstructionRHS(IntLiteral inst) -> void {
  583. out_ << " ";
  584. sem_ir_.ints()
  585. .Get(inst.int_id)
  586. .print(out_, sem_ir_.types().IsSignedInt(inst.type_id));
  587. }
  588. auto FormatInstructionRHS(FloatLiteral inst) -> void {
  589. llvm::SmallVector<char, 16> buffer;
  590. sem_ir_.floats().Get(inst.float_id).toString(buffer);
  591. out_ << " " << buffer;
  592. }
  593. auto FormatInstructionRHS(ImportRefUnloaded inst) -> void {
  594. FormatArgs(inst.import_ir_inst_id);
  595. out_ << ", unloaded";
  596. }
  597. auto FormatInstructionRHS(ImportRefLoaded inst) -> void {
  598. FormatArgs(inst.import_ir_inst_id);
  599. out_ << ", loaded";
  600. }
  601. auto FormatInstructionRHS(SpliceBlock inst) -> void {
  602. FormatArgs(inst.result_id);
  603. FormatTrailingBlock(inst.block_id);
  604. }
  605. // StructTypeFields are formatted as part of their StructType.
  606. auto FormatInstruction(InstId /*inst_id*/, StructTypeField /*inst*/) -> void {
  607. }
  608. auto FormatInstructionRHS(StructType inst) -> void {
  609. out_ << " {";
  610. llvm::ListSeparator sep;
  611. for (auto field_id : sem_ir_.inst_blocks().Get(inst.fields_id)) {
  612. out_ << sep << ".";
  613. auto field = sem_ir_.insts().GetAs<StructTypeField>(field_id);
  614. FormatName(field.name_id);
  615. out_ << ": ";
  616. FormatType(field.field_type_id);
  617. }
  618. out_ << "}";
  619. }
  620. auto FormatArgs() -> void {}
  621. template <typename... Args>
  622. auto FormatArgs(Args... args) -> void {
  623. out_ << ' ';
  624. llvm::ListSeparator sep;
  625. ((out_ << sep, FormatArg(args)), ...);
  626. }
  627. auto FormatArg(BoolValue v) -> void { out_ << v; }
  628. auto FormatArg(BuiltinKind kind) -> void { out_ << kind.label(); }
  629. auto FormatArg(BindNameId id) -> void {
  630. const auto& info = sem_ir_.bind_names().Get(id);
  631. FormatName(info.name_id);
  632. if (info.bind_index.is_valid()) {
  633. out_ << " " << info.bind_index.index;
  634. }
  635. }
  636. auto FormatArg(FunctionId id) -> void { FormatFunctionName(id); }
  637. auto FormatArg(ClassId id) -> void { FormatClassName(id); }
  638. auto FormatArg(InterfaceId id) -> void { FormatInterfaceName(id); }
  639. auto FormatArg(IntKind k) -> void { k.Print(out_); }
  640. auto FormatArg(FloatKind k) -> void { k.Print(out_); }
  641. auto FormatArg(ImplId id) -> void { FormatImplName(id); }
  642. auto FormatArg(ImportIRId id) -> void { out_ << id; }
  643. auto FormatArg(ImportIRInstId id) -> void {
  644. // Don't format the inst_id because it refers to a different IR.
  645. // TODO: Consider a better way to format the InstID from other IRs.
  646. auto import_ir_inst = sem_ir_.import_ir_insts().Get(id);
  647. out_ << import_ir_inst.ir_id << ", " << import_ir_inst.inst_id;
  648. }
  649. auto FormatArg(IntId id) -> void {
  650. // We don't know the signedness to use here. Default to unsigned.
  651. sem_ir_.ints().Get(id).print(out_, /*isSigned=*/false);
  652. }
  653. auto FormatArg(LocId id) -> void {
  654. if (id.is_import_ir_inst_id()) {
  655. out_ << "{";
  656. FormatArg(id.import_ir_inst_id());
  657. out_ << "}";
  658. } else {
  659. // TODO: For a NodeId, this prints the index of the node. Do we want it to
  660. // print a line number or something in order to make it less dependent on
  661. // parse?
  662. out_ << id;
  663. }
  664. }
  665. auto FormatArg(ElementIndex index) -> void { out_ << index; }
  666. auto FormatArg(NameScopeId id) -> void {
  667. OpenBrace();
  668. FormatNameScope(id);
  669. CloseBrace();
  670. }
  671. auto FormatArg(InstId id) -> void { FormatInstName(id); }
  672. auto FormatArg(InstBlockId id) -> void {
  673. if (!id.is_valid()) {
  674. out_ << "invalid";
  675. return;
  676. }
  677. out_ << '(';
  678. llvm::ListSeparator sep;
  679. for (auto inst_id : sem_ir_.inst_blocks().Get(id)) {
  680. out_ << sep;
  681. FormatArg(inst_id);
  682. }
  683. out_ << ')';
  684. }
  685. auto FormatArg(GenericInstanceId id) -> void {
  686. const auto& instance = sem_ir_.generic_instances().Get(id);
  687. FormatArg(instance.args_id);
  688. }
  689. auto FormatArg(RealId id) -> void {
  690. // TODO: Format with a `.` when the exponent is near zero.
  691. const auto& real = sem_ir_.reals().Get(id);
  692. real.mantissa.print(out_, /*isSigned=*/false);
  693. out_ << (real.is_decimal ? 'e' : 'p') << real.exponent;
  694. }
  695. auto FormatArg(StringLiteralValueId id) -> void {
  696. out_ << '"';
  697. out_.write_escaped(sem_ir_.string_literal_values().Get(id),
  698. /*UseHexEscapes=*/true);
  699. out_ << '"';
  700. }
  701. auto FormatArg(NameId id) -> void { FormatName(id); }
  702. auto FormatArg(TypeId id) -> void { FormatType(id); }
  703. auto FormatArg(TypeBlockId id) -> void {
  704. out_ << '(';
  705. llvm::ListSeparator sep;
  706. for (auto type_id : sem_ir_.type_blocks().Get(id)) {
  707. out_ << sep;
  708. FormatArg(type_id);
  709. }
  710. out_ << ')';
  711. }
  712. auto FormatReturnSlot(InstId dest_id) -> void {
  713. out_ << " to ";
  714. FormatArg(dest_id);
  715. }
  716. auto FormatName(NameId id) -> void {
  717. out_ << sem_ir_.names().GetFormatted(id);
  718. }
  719. auto FormatInstName(InstId id) -> void {
  720. out_ << inst_namer_.GetNameFor(scope_, id);
  721. }
  722. auto FormatLabel(InstBlockId id) -> void {
  723. out_ << inst_namer_.GetLabelFor(scope_, id);
  724. }
  725. auto FormatFunctionName(FunctionId id) -> void {
  726. out_ << inst_namer_.GetNameFor(id);
  727. }
  728. auto FormatClassName(ClassId id) -> void {
  729. out_ << inst_namer_.GetNameFor(id);
  730. }
  731. auto FormatInterfaceName(InterfaceId id) -> void {
  732. out_ << inst_namer_.GetNameFor(id);
  733. }
  734. auto FormatImplName(ImplId id) -> void { out_ << inst_namer_.GetNameFor(id); }
  735. auto FormatType(TypeId id) -> void {
  736. if (!id.is_valid()) {
  737. out_ << "invalid";
  738. } else {
  739. // Types are formatted in the `constants` scope because they only refer to
  740. // constants.
  741. llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeId::Constants);
  742. FormatInstName(sem_ir_.types().GetInstId(id));
  743. }
  744. }
  745. private:
  746. const File& sem_ir_;
  747. llvm::raw_ostream& out_;
  748. InstNamer inst_namer_;
  749. // The current scope that we are formatting within. References to names in
  750. // this scope will not have a `@scope.` prefix added.
  751. InstNamer::ScopeId scope_ = InstNamer::ScopeId::None;
  752. // Whether we are formatting in a terminator sequence, that is, a sequence of
  753. // branches at the end of a block. The entirety of a terminator sequence is
  754. // formatted on a single line, despite being multiple instructions.
  755. bool in_terminator_sequence_ = false;
  756. // The indent depth to use for new instructions.
  757. int indent_ = 0;
  758. // Whether we are currently formatting immediately after an open brace. If so,
  759. // a newline will be inserted before the next line indent.
  760. bool after_open_brace_ = false;
  761. // The constant value of the current instruction, if it has one that has not
  762. // yet been printed. The value `NotConstant` is used as a sentinel to indicate
  763. // there is nothing to print.
  764. ConstantId pending_constant_value_ = ConstantId::NotConstant;
  765. // Whether `pending_constant_value_`'s instruction is the same as the
  766. // instruction currently being printed. If true, only the phase of the
  767. // constant is printed, and the value is omitted.
  768. bool pending_constant_value_is_self_ = false;
  769. };
  770. auto FormatFile(const Lex::TokenizedBuffer& tokenized_buffer,
  771. const Parse::Tree& parse_tree, const File& sem_ir,
  772. llvm::raw_ostream& out) -> void {
  773. Formatter(tokenized_buffer, parse_tree, sem_ir, out).Format();
  774. }
  775. } // namespace Carbon::SemIR