From 65d6e3e221fb0d58cb4524025a25f18af9c31f51 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Wed, 17 Jul 2024 15:05:19 -0700 Subject: [PATCH] Use verbose formatting of instructions on crash messages. (#4125) Changes crash messages to start printing verbose forms of instructions, rather than just the ID. Fixes some indentation issues with stacks. Also switches unexpected inst formatting, because now there are lots, and it'd be helpful to know where they are. This uses a pimpl pattern for Formatter due to the number of member functions on Formatter. Maybe we should refactor that, but this didn't feel like a good place to do so. Note, I have two concerns about this change... to note them here, to make sure others are considering them when evaluating the implementation: 1. Some instructions are very verbose to print, as evidenced by the fn_decl printing (which includes function params) or scope printing (which includes scope members). - I'm not sure whether there's a way to simply reduce this, as it seems essential to the requested printing of instructions. - Long-term, we may at least want to limit the number of lines printed here. However, I've already spent a fair amount of time here and I think it's in a good state to evaluate. 2. Increased complexity in the crash handler may result in crash messages failing to generate. - For example, a crash in Formatter (and its deps, such as InstNamer or location handling) prevents a stack from being printed. I'm pretty sure I've written crashes in Formatter before. Here's an example crash snippet (generated by adding a crash inside `return` handling) before: ``` 2. NodeStack: 0. FunctionDefinitionStart -> function2 1. ReturnStatementStart -> no value 2. IntLiteral -> inst+26 inst_block_stack_: 0. block {inst+0, inst+1, inst+2, inst+23} 1. block9 {inst+26} param_and_arg_refs_stack: args_type_info_stack_: ``` And after: ``` 2. Check::Context NodeStack: 0. FunctionDefinitionStart: function2 1. ReturnStatementStart: no value 2. IntLiteral: unexpected.inst+26.loc12_10: i32 = int_literal 0 [template = constants.%.2] inst_block_stack_: 0. block { package: = namespace [template] { .Core = unexpected.inst+2 .F = unexpected.inst+23.loc11_22 } unexpected.inst+1 = import Core unexpected.inst+2: = namespace unexpected.inst+1, [template] {} unexpected.inst+23.loc11_22: %F.type = fn_decl @F [template = constants.%F] { unexpected.inst+9.loc11_9: init type = call constants.%Bool() [template = bool] unexpected.inst+10.loc11_9: type = value_of_initializer unexpected.inst+9.loc11_9 [template = bool] unexpected.inst+11.loc11_9: type = converted unexpected.inst+9.loc11_9, unexpected.inst+10.loc11_9 [template = bool] unexpected.inst+12.loc11_6: bool = param b @F.%b: bool = bind_name b, unexpected.inst+12.loc11_6 unexpected.inst+19.loc11_18: init type = call constants.%Int32() [template = i32] unexpected.inst+20.loc11_18: type = value_of_initializer unexpected.inst+19.loc11_18 [template = i32] unexpected.inst+21.loc11_18: type = converted unexpected.inst+19.loc11_18, unexpected.inst+20.loc11_18 [template = i32] @F.%return: ref i32 = var } } 1. block9 { unexpected.inst+26.loc12_10: i32 = int_literal 0 [template = constants.%.2] } param_and_arg_refs_stack: args_type_info_stack_: ``` --- toolchain/check/BUILD | 1 + toolchain/check/context.cpp | 18 ++- toolchain/check/inst_block_stack.cpp | 15 +-- toolchain/check/inst_block_stack.h | 4 +- toolchain/check/node_stack.cpp | 16 ++- toolchain/check/node_stack.h | 4 +- toolchain/check/param_and_arg_refs_stack.h | 5 +- .../testdata/class/fail_generic_method.carbon | 2 +- .../check/testdata/class/generic/basic.carbon | 12 +- .../class/generic/fail_todo_use.carbon | 16 +-- .../check/testdata/class/generic/field.carbon | 24 ++-- .../testdata/class/generic/import.carbon | 12 +- .../testdata/class/generic_method.carbon | 8 +- .../function/generic/redeclare.carbon | 2 +- .../if_expr/fail_not_in_function.carbon | 4 +- .../impl/fail_extend_impl_forall.carbon | 4 +- .../impl/fail_impl_bad_assoc_fn.carbon | 2 +- .../testdata/impl/fail_redefinition.carbon | 2 +- .../impl/no_prelude/self_in_signature.carbon | 2 +- .../fail_assoc_const_not_binding.carbon | 2 +- .../fail_assoc_const_template.carbon | 2 +- .../no_prelude/fail_duplicate.carbon | 2 +- .../fail_generic_redeclaration.carbon | 4 +- .../fail_todo_generic_default_fn.carbon | 18 +-- .../interface/no_prelude/generic.carbon | 8 +- .../no_prelude/generic_import.carbon | 6 +- .../fail_and_or_not_in_function.carbon | 2 +- .../no_prelude/fail_export_name_params.carbon | 2 +- .../testdata/return/fail_let_in_type.carbon | 6 +- toolchain/check/testdata/struct/import.carbon | 6 +- toolchain/check/testdata/tuples/import.carbon | 6 +- toolchain/driver/driver.cpp | 17 +-- toolchain/sem_ir/formatter.cpp | 115 ++++++++++++------ toolchain/sem_ir/formatter.h | 27 +++- toolchain/sem_ir/inst_namer.cpp | 10 +- 35 files changed, 238 insertions(+), 148 deletions(-) diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index abf01dad08bf..b77dc369a4bc 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -241,6 +241,7 @@ cc_library( "//common:vlog", "//toolchain/parse:node_kind", "//toolchain/parse:tree", + "//toolchain/sem_ir:formatter", "//toolchain/sem_ir:ids", "@llvm-project//llvm:Support", ], diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index b158b323d0ce..d3edcd199eee 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -1193,14 +1193,22 @@ auto Context::GetUnqualifiedType(SemIR::TypeId type_id) -> SemIR::TypeId { } auto Context::PrintForStackDump(llvm::raw_ostream& output) const -> void { - node_stack_.PrintForStackDump(output); - inst_block_stack_.PrintForStackDump(output); - param_and_arg_refs_stack_.PrintForStackDump(output); - args_type_info_stack_.PrintForStackDump(output); + output << "Check::Context\n"; + + // In a stack dump, this is probably indented by a tab. We treat that as 8 + // spaces then add a couple to indent past the Context label. + constexpr int Indent = 10; + + SemIR::Formatter formatter(*tokens_, *parse_tree_, *sem_ir_); + node_stack_.PrintForStackDump(formatter, Indent, output); + inst_block_stack_.PrintForStackDump(formatter, Indent, output); + param_and_arg_refs_stack_.PrintForStackDump(formatter, Indent, output); + args_type_info_stack_.PrintForStackDump(formatter, Indent, output); } auto Context::DumpFormattedFile() const -> void { - FormatFile(*tokens_, *parse_tree_, *sem_ir_, llvm::errs()); + SemIR::Formatter formatter(*tokens_, *parse_tree_, *sem_ir_); + formatter.Print(llvm::errs()); } } // namespace Carbon::Check diff --git a/toolchain/check/inst_block_stack.cpp b/toolchain/check/inst_block_stack.cpp index 7220e49af1d5..9ffcc3540b51 100644 --- a/toolchain/check/inst_block_stack.cpp +++ b/toolchain/check/inst_block_stack.cpp @@ -61,16 +61,17 @@ auto InstBlockStack::PopAndDiscard() -> void { CARBON_VLOG() << name_ << " PopAndDiscard " << id_stack_.size() << "\n"; } -auto InstBlockStack::PrintForStackDump(llvm::raw_ostream& output) const +auto InstBlockStack::PrintForStackDump(SemIR::Formatter& formatter, int indent, + llvm::raw_ostream& output) const -> void { + output.indent(indent); output << name_ << ":\n"; for (const auto& [i, id] : llvm::enumerate(id_stack_)) { - output << "\t" << i << ".\t" << id << "\t{"; - llvm::ListSeparator sep; - for (auto id : insts_stack_.PeekArrayAt(i)) { - output << sep << id; - } - output << "}\n"; + output.indent(indent + 2); + output << i << ". " << id; + formatter.PrintPartialTrailingCodeBlock(insts_stack_.PeekArrayAt(i), + indent + 4, output); + output << "\n"; } } diff --git a/toolchain/check/inst_block_stack.h b/toolchain/check/inst_block_stack.h index 159cf3ccb340..0115861d4bcf 100644 --- a/toolchain/check/inst_block_stack.h +++ b/toolchain/check/inst_block_stack.h @@ -8,6 +8,7 @@ #include "common/array_stack.h" #include "llvm/ADT/SmallVector.h" #include "toolchain/sem_ir/file.h" +#include "toolchain/sem_ir/formatter.h" namespace Carbon::Check { @@ -69,7 +70,8 @@ class InstBlockStack { } // Prints the stack for a stack dump. - auto PrintForStackDump(llvm::raw_ostream& output) const -> void; + auto PrintForStackDump(SemIR::Formatter& formatter, int indent, + llvm::raw_ostream& output) const -> void; // Runs verification that the processing cleanly finished. auto VerifyOnFinish() const -> void { diff --git a/toolchain/check/node_stack.cpp b/toolchain/check/node_stack.cpp index 13cb9f432e97..8b28e0707d78 100644 --- a/toolchain/check/node_stack.cpp +++ b/toolchain/check/node_stack.cpp @@ -8,21 +8,28 @@ namespace Carbon::Check { -auto NodeStack::PrintForStackDump(llvm::raw_ostream& output) const -> void { +auto NodeStack::PrintForStackDump(SemIR::Formatter& formatter, int indent, + llvm::raw_ostream& output) const -> void { auto print_id = [&](Id id) { if constexpr (Kind == Id::Kind::None) { - output << " -> no value"; + output << "no value\n"; } else if constexpr (Kind == Id::Kind::Invalid) { CARBON_FATAL() << "Should not be in node stack"; + } else if constexpr (Kind == Id::KindFor()) { + output << "\n"; + formatter.PrintInst(id.As()>(), indent + 4, + output); } else { - output << " -> " << id.As(); + output << id.As() << "\n"; } }; + output.indent(indent); output << "NodeStack:\n"; for (auto [i, entry] : llvm::enumerate(stack_)) { auto node_kind = parse_tree_->node_kind(entry.node_id); - output << "\t" << i << ".\t" << node_kind; + output.indent(indent + 2); + output << i << ". " << node_kind << ": "; switch (node_kind) { #define CARBON_PARSE_NODE_KIND(Kind) \ case Parse::NodeKind::Kind: \ @@ -30,7 +37,6 @@ auto NodeStack::PrintForStackDump(llvm::raw_ostream& output) const -> void { break; #include "toolchain/parse/node_kind.def" } - output << "\n"; } } diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index 989f964c4c06..463979cb8105 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -11,6 +11,7 @@ #include "toolchain/parse/node_kind.h" #include "toolchain/parse/tree.h" #include "toolchain/parse/typed_nodes.h" +#include "toolchain/sem_ir/formatter.h" #include "toolchain/sem_ir/id_kind.h" #include "toolchain/sem_ir/ids.h" @@ -325,7 +326,8 @@ class NodeStack { } // Prints the stack for a stack dump. - auto PrintForStackDump(llvm::raw_ostream& output) const -> void; + auto PrintForStackDump(SemIR::Formatter& formatter, int indent, + llvm::raw_ostream& output) const -> void; auto empty() const -> bool { return stack_.empty(); } auto size() const -> size_t { return stack_.size(); } diff --git a/toolchain/check/param_and_arg_refs_stack.h b/toolchain/check/param_and_arg_refs_stack.h index aa91838f5b7b..dbdfa516fedd 100644 --- a/toolchain/check/param_and_arg_refs_stack.h +++ b/toolchain/check/param_and_arg_refs_stack.h @@ -72,8 +72,9 @@ class ParamAndArgRefsStack { auto VerifyOnFinish() -> void { stack_.VerifyOnFinish(); } // Prints the stack for a stack dump. - auto PrintForStackDump(llvm::raw_ostream& output) const -> void { - return stack_.PrintForStackDump(output); + auto PrintForStackDump(SemIR::Formatter& formatter, int indent, + llvm::raw_ostream& output) const -> void { + return stack_.PrintForStackDump(formatter, indent, output); } private: diff --git a/toolchain/check/testdata/class/fail_generic_method.carbon b/toolchain/check/testdata/class/fail_generic_method.carbon index 2de067d5cfbd..ae4646874cee 100644 --- a/toolchain/check/testdata/class/fail_generic_method.carbon +++ b/toolchain/check/testdata/class/fail_generic_method.carbon @@ -83,7 +83,7 @@ fn Class(N:! i32).F[self: Self](n: T) {} // CHECK:STDOUT: class @Class // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] -// CHECK:STDOUT: %.loc12: (%.2) = field_decl a, element0 [template] +// CHECK:STDOUT: %.loc12: .inst+28 (%.2) = field_decl a, element0 [template] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { // CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc13 (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc13 [symbolic = %.loc13 (constants.%Class.2)] diff --git a/toolchain/check/testdata/class/generic/basic.carbon b/toolchain/check/testdata/class/generic/basic.carbon index ba7e2326d20d..4128b3cd320d 100644 --- a/toolchain/check/testdata/class/generic/basic.carbon +++ b/toolchain/check/testdata/class/generic/basic.carbon @@ -76,7 +76,7 @@ class Class(T:! type) { // CHECK:STDOUT: %return.var.loc17: ref %T = var // CHECK:STDOUT: } // CHECK:STDOUT: %T.ref.loc21: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] -// CHECK:STDOUT: %.loc21: (%.4) = field_decl k, element0 [template] +// CHECK:STDOUT: %.loc21: .inst+41 (%.4) = field_decl k, element0 [template] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Class.2 @@ -90,7 +90,7 @@ class Class(T:! type) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %self.ref: @Class.%.loc12_29 (%.2) = name_ref self, @Class.%self.loc12_19.3 // CHECK:STDOUT: %.loc13_17.1: ref @Class.%.loc12_25 (%Class.2) = deref %self.ref -// CHECK:STDOUT: %k.ref: (%.4) = name_ref k, @Class.%.loc21 [template = @Class.%.loc21] +// CHECK:STDOUT: %k.ref: .inst+49 (%.4) = name_ref k, @Class.%.loc21 [template = @Class.%.loc21] // CHECK:STDOUT: %.loc13_17.2: ref @Class.%T.ref.loc12 (%T) = class_element_access %.loc13_17.1, element0 // CHECK:STDOUT: %.loc13_12: @Class.%.loc12_38 (%.3) = addr_of %.loc13_17.2 // CHECK:STDOUT: return %.loc13_12 @@ -100,7 +100,7 @@ class Class(T:! type) { // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %self.ref: @Class.%.loc17 (%Class.2) = name_ref self, @Class.%self.loc17_15.2 -// CHECK:STDOUT: %k.ref: (%.4) = name_ref k, @Class.%.loc21 [template = @Class.%.loc21] +// CHECK:STDOUT: %k.ref: .inst+55 (%.4) = name_ref k, @Class.%.loc21 [template = @Class.%.loc21] // CHECK:STDOUT: %.loc18_16.1: ref @Class.%T.ref.loc17 (%T) = class_element_access %self.ref, element0 // CHECK:STDOUT: %.loc18_16.2: @Class.%T.ref.loc17 (%T) = bind_value %.loc18_16.1 // CHECK:STDOUT: return %.loc18_16.2 @@ -111,9 +111,9 @@ class Class(T:! type) { // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: // CHECK:STDOUT: definition: -// CHECK:STDOUT: => constants.%Class.2 -// CHECK:STDOUT: => constants.%.4 -// CHECK:STDOUT: => +// CHECK:STDOUT: .inst+40 => constants.%Class.2 +// CHECK:STDOUT: .inst+41 => constants.%.4 +// CHECK:STDOUT: .inst+37.loc21_8 => .inst+38 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class.%GetAddr.decl(constants.%T) { diff --git a/toolchain/check/testdata/class/generic/fail_todo_use.carbon b/toolchain/check/testdata/class/generic/fail_todo_use.carbon index 94e19241099b..8ab253edd1bd 100644 --- a/toolchain/check/testdata/class/generic/fail_todo_use.carbon +++ b/toolchain/check/testdata/class/generic/fail_todo_use.carbon @@ -101,7 +101,7 @@ fn Run() -> i32 { // CHECK:STDOUT: %return.var: ref %.3 = var // CHECK:STDOUT: } // CHECK:STDOUT: %T.ref.loc16: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] -// CHECK:STDOUT: %.loc16: (%.4) = field_decl k, element0 [template] +// CHECK:STDOUT: %.loc16: .inst+32 (%.4) = field_decl k, element0 [template] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Class.2 @@ -114,7 +114,7 @@ fn Run() -> i32 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %self.ref: @Class.%.loc12_25 (%.2) = name_ref self, @Class.%self.loc12_15.3 // CHECK:STDOUT: %.loc13_17.1: ref @Class.%.loc12_21 (%Class.2) = deref %self.ref -// CHECK:STDOUT: %k.ref: (%.4) = name_ref k, @Class.%.loc16 [template = @Class.%.loc16] +// CHECK:STDOUT: %k.ref: .inst+40 (%.4) = name_ref k, @Class.%.loc16 [template = @Class.%.loc16] // CHECK:STDOUT: %.loc13_17.2: ref @Class.%T.ref.loc12 (%T) = class_element_access %.loc13_17.1, element0 // CHECK:STDOUT: %.loc13_12: @Class.%.loc12_34 (%.3) = addr_of %.loc13_17.2 // CHECK:STDOUT: return %.loc13_12 @@ -149,9 +149,9 @@ fn Run() -> i32 { // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: // CHECK:STDOUT: definition: -// CHECK:STDOUT: => constants.%Class.2 -// CHECK:STDOUT: => constants.%.4 -// CHECK:STDOUT: => +// CHECK:STDOUT: .inst+31 => constants.%Class.2 +// CHECK:STDOUT: .inst+32 => constants.%.4 +// CHECK:STDOUT: .inst+28.loc16_8 => .inst+29 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class.%Get.decl(constants.%T) { @@ -172,8 +172,8 @@ fn Run() -> i32 { // CHECK:STDOUT: file.%T.loc11_13.2 => i32 // CHECK:STDOUT: // CHECK:STDOUT: definition: -// CHECK:STDOUT: => constants.%Class.3 -// CHECK:STDOUT: => constants.%.7 -// CHECK:STDOUT: => +// CHECK:STDOUT: .inst+31 => constants.%Class.3 +// CHECK:STDOUT: .inst+32 => constants.%.7 +// CHECK:STDOUT: .inst+28.loc16_8 => .inst+29 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/field.carbon b/toolchain/check/testdata/class/generic/field.carbon index 6691820b430b..ec662761be67 100644 --- a/toolchain/check/testdata/class/generic/field.carbon +++ b/toolchain/check/testdata/class/generic/field.carbon @@ -115,7 +115,7 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: class @Class // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] -// CHECK:STDOUT: %.loc12: (%.2) = field_decl x, element0 [template] +// CHECK:STDOUT: %.loc12: .inst+18 (%.2) = field_decl x, element0 [template] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Class.2 @@ -137,7 +137,7 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: generic [%T: type] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %c.ref: file.%.loc19_24 (%Class.2) = name_ref c, %c -// CHECK:STDOUT: %x.ref: (%.2) = name_ref x, @Class.%.loc12 [template = @Class.%.loc12] +// CHECK:STDOUT: %x.ref: .inst+68 (%.2) = name_ref x, @Class.%.loc12 [template = @Class.%.loc12] // CHECK:STDOUT: %.loc20_11.1: ref @G.%T (%T) = class_element_access %c.ref, element0 // CHECK:STDOUT: %.loc20_11.2: @G.%T (%T) = bind_value %.loc20_11.1 // CHECK:STDOUT: return %.loc20_11.2 @@ -147,7 +147,7 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: generic [%U: type] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %c.ref: file.%.loc23_24 (%Class.4) = name_ref c, %c -// CHECK:STDOUT: %x.ref: (%.6) = name_ref x, @Class.%.loc12 [template = @Class.%.loc12] +// CHECK:STDOUT: %x.ref: .inst+91 (%.6) = name_ref x, @Class.%.loc12 [template = @Class.%.loc12] // CHECK:STDOUT: %.loc24_11.1: ref @H.%U (%U) = class_element_access %c.ref, element0 // CHECK:STDOUT: %.loc24_11.2: @H.%U (%U) = bind_value %.loc24_11.1 // CHECK:STDOUT: return %.loc24_11.2 @@ -158,9 +158,9 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: // CHECK:STDOUT: definition: -// CHECK:STDOUT: => constants.%Class.2 -// CHECK:STDOUT: => constants.%.2 -// CHECK:STDOUT: => +// CHECK:STDOUT: .inst+17 => constants.%Class.2 +// CHECK:STDOUT: .inst+18 => constants.%.2 +// CHECK:STDOUT: .inst+14.loc12_8 => .inst+15 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%Class.decl(file.%T.loc11_13.2) { @@ -173,9 +173,9 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: file.%T.loc11_13.2 => i32 // CHECK:STDOUT: // CHECK:STDOUT: definition: -// CHECK:STDOUT: => constants.%Class.3 -// CHECK:STDOUT: => constants.%.4 -// CHECK:STDOUT: => +// CHECK:STDOUT: .inst+17 => constants.%Class.3 +// CHECK:STDOUT: .inst+18 => constants.%.4 +// CHECK:STDOUT: .inst+14.loc12_8 => .inst+15 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%G.decl(constants.%T) { @@ -189,9 +189,9 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%U // CHECK:STDOUT: // CHECK:STDOUT: definition: -// CHECK:STDOUT: => constants.%Class.4 -// CHECK:STDOUT: => constants.%.6 -// CHECK:STDOUT: => +// CHECK:STDOUT: .inst+17 => constants.%Class.4 +// CHECK:STDOUT: .inst+18 => constants.%.6 +// CHECK:STDOUT: .inst+14.loc12_8 => .inst+15 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%H.decl(constants.%U) { diff --git a/toolchain/check/testdata/class/generic/import.carbon b/toolchain/check/testdata/class/generic/import.carbon index 4644962104c7..8b1020665ad4 100644 --- a/toolchain/check/testdata/class/generic/import.carbon +++ b/toolchain/check/testdata/class/generic/import.carbon @@ -154,7 +154,7 @@ class Class(U:! type) { // CHECK:STDOUT: %int.make_type_32.loc7: init type = call constants.%Int32() [template = i32] // CHECK:STDOUT: %.loc7_10.1: type = value_of_initializer %int.make_type_32.loc7 [template = i32] // CHECK:STDOUT: %.loc7_10.2: type = converted %int.make_type_32.loc7, %.loc7_10.1 [template = i32] -// CHECK:STDOUT: %.loc7_8: (%.2) = field_decl n, element0 [template] +// CHECK:STDOUT: %.loc7_8: .inst+39 (%.2) = field_decl n, element0 [template] // CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] { // CHECK:STDOUT: %int.make_type_32.loc8: init type = call constants.%Int32() [template = i32] // CHECK:STDOUT: %.loc8_13.1: type = value_of_initializer %int.make_type_32.loc8 [template = i32] @@ -206,7 +206,7 @@ class Class(U:! type) { // CHECK:STDOUT: --- foo.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, .inst+31 [symbolic] // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] @@ -308,7 +308,7 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.type: type = generic_class_type @CompleteClass [template] // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, .inst+28 [symbolic] // CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] // CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] @@ -399,7 +399,7 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.type: type = generic_class_type @CompleteClass [template] // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, .inst+28 [symbolic] // CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] // CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] @@ -483,7 +483,7 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.type: type = generic_class_type @CompleteClass [template] // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, .inst+19 [symbolic] // CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, (%T) [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] @@ -562,7 +562,7 @@ class Class(U:! type) { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, .inst+17 [symbolic] // CHECK:STDOUT: %Class.2: type = class_type @Class, (%T) [symbolic] // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.2: %.type = struct_value () [template] diff --git a/toolchain/check/testdata/class/generic_method.carbon b/toolchain/check/testdata/class/generic_method.carbon index cb8bc1faad41..90d85dd15c05 100644 --- a/toolchain/check/testdata/class/generic_method.carbon +++ b/toolchain/check/testdata/class/generic_method.carbon @@ -57,7 +57,7 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: class @Class // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] -// CHECK:STDOUT: %.loc12: (%.2) = field_decl a, element0 [template] +// CHECK:STDOUT: %.loc12: .inst+28 (%.2) = field_decl a, element0 [template] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { // CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc13 (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc13 [symbolic = %.loc13 (constants.%Class.2)] @@ -85,9 +85,9 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: // CHECK:STDOUT: definition: -// CHECK:STDOUT: => constants.%Class.2 -// CHECK:STDOUT: => constants.%.2 -// CHECK:STDOUT: => +// CHECK:STDOUT: .inst+27 => constants.%Class.2 +// CHECK:STDOUT: .inst+28 => constants.%.2 +// CHECK:STDOUT: .inst+14.loc12_8 => .inst+15 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class.%F.decl(constants.%T) { diff --git a/toolchain/check/testdata/function/generic/redeclare.carbon b/toolchain/check/testdata/function/generic/redeclare.carbon index 255f8071dc2e..2e6ddd9f4bf2 100644 --- a/toolchain/check/testdata/function/generic/redeclare.carbon +++ b/toolchain/check/testdata/function/generic/redeclare.carbon @@ -200,7 +200,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] // CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T (constants.%T)] -// CHECK:STDOUT: %F.call: init (%.1) = call %F.ref() [template = ] +// CHECK:STDOUT: %F.call: init .inst+32 (%.1) = call %F.ref() [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/if_expr/fail_not_in_function.carbon b/toolchain/check/testdata/if_expr/fail_not_in_function.carbon index 0653948d1eab..34417d30d2ee 100644 --- a/toolchain/check/testdata/if_expr/fail_not_in_function.carbon +++ b/toolchain/check/testdata/if_expr/fail_not_in_function.carbon @@ -63,7 +63,7 @@ class C { // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: .x = +// CHECK:STDOUT: .x = .inst+12.loc23_5 // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core @@ -80,7 +80,7 @@ class C { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C -// CHECK:STDOUT: .n = +// CHECK:STDOUT: .n = .inst+49.loc37_8 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon index d80a947b486e..f8d6c6e87ad3 100644 --- a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon +++ b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon @@ -58,7 +58,7 @@ class C { // CHECK:STDOUT: // CHECK:STDOUT: interface @GenericInterface // CHECK:STDOUT: generic [file.%T.loc11_28.2: type] { -// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self: .inst+22 (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] { // CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc11_28.2 [symbolic = %T.ref (constants.%T)] // CHECK:STDOUT: %x.loc12_8.1: @GenericInterface.%T.ref (%T) = param x @@ -102,7 +102,7 @@ class C { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.1(@GenericInterface.%x.loc12_8.2: @GenericInterface.%T.ref (%T)) -// CHECK:STDOUT: generic [file.%T.loc11_28.2: type, @GenericInterface.%Self: (%.2)]; +// CHECK:STDOUT: generic [file.%T.loc11_28.2: type, @GenericInterface.%Self: .inst+22 (%.2)]; // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2(@impl.%x.loc20_10.2: @impl.%T.ref (%T)) // CHECK:STDOUT: generic [@C.%T.loc19_23.2: type] { diff --git a/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon b/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon index ca917fd270e6..04fabac611d4 100644 --- a/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon +++ b/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon @@ -899,7 +899,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: declaration: // CHECK:STDOUT: @SelfNested.%Self.ref.loc188_12 => constants.%Self.3 // CHECK:STDOUT: @SelfNested.%.loc188_16.3 => constants.%.10 -// CHECK:STDOUT: => +// CHECK:STDOUT: .inst+267.loc188_21 => .inst+268 // CHECK:STDOUT: @SelfNested.%.loc188_37 => constants.%.11 // CHECK:STDOUT: @SelfNested.%.loc188_38.2 => constants.%.13 // CHECK:STDOUT: @SelfNested.%.loc188_52 => constants.%.15 diff --git a/toolchain/check/testdata/impl/fail_redefinition.carbon b/toolchain/check/testdata/impl/fail_redefinition.carbon index c5b4564238b2..7a1646fe9e3a 100644 --- a/toolchain/check/testdata/impl/fail_redefinition.carbon +++ b/toolchain/check/testdata/impl/fail_redefinition.carbon @@ -68,7 +68,7 @@ impl i32 as I {} // CHECK:STDOUT: // CHECK:STDOUT: impl @impl: i32 as %.1 { // CHECK:STDOUT: !members: -// CHECK:STDOUT: witness = +// CHECK:STDOUT: witness = .inst+18 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon b/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon index f8e10275a85c..42b2e1567f1b 100644 --- a/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon +++ b/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon @@ -284,7 +284,7 @@ impl D as SelfNested { // CHECK:STDOUT: declaration: // CHECK:STDOUT: @SelfNested.%Self.ref.loc28_12 => constants.%Self.2 // CHECK:STDOUT: @SelfNested.%.loc28_16.3 => constants.%.10 -// CHECK:STDOUT: => +// CHECK:STDOUT: .inst+86.loc28_21 => .inst+87 // CHECK:STDOUT: @SelfNested.%.loc28_36 => constants.%.11 // CHECK:STDOUT: @SelfNested.%.loc28_37.2 => constants.%.13 // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/interface/no_prelude/fail_assoc_const_not_binding.carbon b/toolchain/check/testdata/interface/no_prelude/fail_assoc_const_not_binding.carbon index 7da0a1ced255..386e094720c7 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_assoc_const_not_binding.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_assoc_const_not_binding.carbon @@ -28,7 +28,7 @@ interface I { // CHECK:STDOUT: // CHECK:STDOUT: interface @I { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = +// CHECK:STDOUT: .Self = .inst+3 // CHECK:STDOUT: witness = invalid // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_assoc_const_template.carbon b/toolchain/check/testdata/interface/no_prelude/fail_assoc_const_template.carbon index 6168a278b042..497f29f65d53 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_assoc_const_template.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_assoc_const_template.carbon @@ -26,7 +26,7 @@ interface I { // CHECK:STDOUT: // CHECK:STDOUT: interface @I { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = +// CHECK:STDOUT: .Self = .inst+3 // CHECK:STDOUT: witness = invalid // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_duplicate.carbon b/toolchain/check/testdata/interface/no_prelude/fail_duplicate.carbon index 0e002468e456..355d6fc31ae5 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_duplicate.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_duplicate.carbon @@ -76,7 +76,7 @@ interface Class { } // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = +// CHECK:STDOUT: .Self = .inst+3 // CHECK:STDOUT: .F = // CHECK:STDOUT: witness = () // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon b/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon index e736aa31bf0e..636b57adcfe7 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon @@ -92,7 +92,7 @@ interface DifferentParams(T:! ()) {} // CHECK:STDOUT: // CHECK:STDOUT: interface @.1 // CHECK:STDOUT: generic [file.%T.loc19_22.2: type] { -// CHECK:STDOUT: %Self: (%.4) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: %Self: .inst+13 (%.4) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -115,7 +115,7 @@ interface DifferentParams(T:! ()) {} // CHECK:STDOUT: // CHECK:STDOUT: interface @.3 // CHECK:STDOUT: generic [file.%T.loc38_27.2: %.2] { -// CHECK:STDOUT: %Self: (%.7) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.3)] +// CHECK:STDOUT: %Self: .inst+39 (%.7) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.3)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self diff --git a/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon b/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon index 40d8a0aff8a0..a7d37323b55c 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon @@ -34,7 +34,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.3: type = assoc_entity_type @I, %F.type [template] // CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @I.%F.decl [template] -// CHECK:STDOUT: %Self.2: (%.2) = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %Self.2: .inst+28 (%.2) = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %.type: type = fn_type @.1 [template] // CHECK:STDOUT: %.5: %.type = struct_value () [template] // CHECK:STDOUT: } @@ -50,14 +50,14 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.5] { // CHECK:STDOUT: %T.loc22_6.1: type = param T // CHECK:STDOUT: %T.loc22_6.2: type = bind_symbolic_name T 0, %T.loc22_6.1 [symbolic = %T.loc22_6.2 (constants.%T)] -// CHECK:STDOUT: %.loc22_24.1: (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self.2)] -// CHECK:STDOUT: %Self.ref.loc22_24: (%.2) = name_ref Self, %.loc22_24.1 [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %.loc22_24.1: .inst+44 (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %Self.ref.loc22_24: .inst+44 (%.2) = name_ref Self, %.loc22_24.1 [symbolic = %.loc22_24.1 (constants.%Self.2)] // CHECK:STDOUT: %.loc22_24.2: type = facet_type_access %Self.ref.loc22_24 [symbolic = %.loc22_24.1 (constants.%Self.2)] // CHECK:STDOUT: %.loc22_24.3: type = converted %Self.ref.loc22_24, %.loc22_24.2 [symbolic = %.loc22_24.1 (constants.%Self.2)] // CHECK:STDOUT: %self.loc22_18.1: file.%.loc22_24.1 (%Self.2) = param self // CHECK:STDOUT: @.1.%self: file.%.loc22_24.1 (%Self.2) = bind_name self, %self.loc22_18.1 -// CHECK:STDOUT: %.loc22_35.1: (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self.2)] -// CHECK:STDOUT: %Self.ref.loc22_35: (%.2) = name_ref Self, %.loc22_35.1 [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %.loc22_35.1: .inst+44 (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %Self.ref.loc22_35: .inst+44 (%.2) = name_ref Self, %.loc22_35.1 [symbolic = %.loc22_24.1 (constants.%Self.2)] // CHECK:STDOUT: %.loc22_35.2: type = facet_type_access %Self.ref.loc22_35 [symbolic = %.loc22_24.1 (constants.%Self.2)] // CHECK:STDOUT: %.loc22_35.3: type = converted %Self.ref.loc22_35, %.loc22_35.2 [symbolic = %.loc22_24.1 (constants.%Self.2)] // CHECK:STDOUT: @.1.%return: ref %Self.2 = var @@ -66,7 +66,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: // CHECK:STDOUT: interface @I // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { -// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: %Self: .inst+28 (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { // CHECK:STDOUT: %.loc13_14.1: %.2 = specific_constant %Self, file.%I.decl(constants.%T) [symbolic = %.loc13_14.1 (constants.%Self.1)] // CHECK:STDOUT: %Self.ref.loc13_14: %.2 = name_ref Self, %.loc13_14.1 [symbolic = %.loc13_14.1 (constants.%Self.1)] @@ -89,7 +89,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F[@I.%self.loc13_8.2: @I.%.loc13_14.1 (%Self.1)]() -> %Self.1 -// CHECK:STDOUT: generic [file.%T.loc11_13.2: type, @I.%Self: (%.2)]; +// CHECK:STDOUT: generic [file.%T.loc11_13.2: type, @I.%Self: .inst+28 (%.2)]; // CHECK:STDOUT: // CHECK:STDOUT: fn @.1[%self: file.%.loc22_24.1 (%Self.2)]() -> %Self.2 // CHECK:STDOUT: generic [file.%T.loc22_6.2: type] { @@ -103,7 +103,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: // CHECK:STDOUT: definition: -// CHECK:STDOUT: => constants.%.2 +// CHECK:STDOUT: .inst+28 => constants.%.2 // CHECK:STDOUT: @I.%Self => constants.%Self.2 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -125,7 +125,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: specific file.%.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc22_6.2 => constants.%T -// CHECK:STDOUT: => constants.%.2 +// CHECK:STDOUT: .inst+44 => constants.%.2 // CHECK:STDOUT: file.%.loc22_24.1 => constants.%Self.2 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/generic.carbon b/toolchain/check/testdata/interface/no_prelude/generic.carbon index 00c9a2e40ac0..d43431f2a217 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic.carbon @@ -145,7 +145,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: // CHECK:STDOUT: interface @Simple // CHECK:STDOUT: generic [file.%T.loc4_18.2: type] { -// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: %Self: .inst+11 (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -154,7 +154,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: // CHECK:STDOUT: interface @WithAssocFn // CHECK:STDOUT: generic [file.%T.loc8_23.2: type] { -// CHECK:STDOUT: %Self: (%.4) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %Self: .inst+31 (%.4) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.2)] // CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] { // CHECK:STDOUT: %X.ref: type = name_ref X, file.%X.decl [template = constants.%X] // CHECK:STDOUT: %return.var: ref %X = var @@ -215,7 +215,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.1() -> %X -// CHECK:STDOUT: generic [file.%T.loc8_23.2: type, @WithAssocFn.%Self: (%.4)]; +// CHECK:STDOUT: generic [file.%T.loc8_23.2: type, @WithAssocFn.%Self: .inst+31 (%.4)]; // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2() -> @impl.2.%return.var: %X { // CHECK:STDOUT: !entry: @@ -345,7 +345,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: // CHECK:STDOUT: interface @Generic // CHECK:STDOUT: generic [file.%T.loc4_19.2: type] { -// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self: .inst+11 (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self diff --git a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon index f6315d812c94..ad2171a80bea 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon @@ -54,7 +54,7 @@ impl C as AddWith(C) { // CHECK:STDOUT: // CHECK:STDOUT: interface @AddWith // CHECK:STDOUT: generic [file.%T.loc4_19.2: type] { -// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self: .inst+17 (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} // CHECK:STDOUT: %.loc5: %.3 = assoc_entity element0, %F.decl [template = constants.%.4] // CHECK:STDOUT: @@ -65,7 +65,7 @@ impl C as AddWith(C) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() -// CHECK:STDOUT: generic [file.%T.loc4_19.2: type, @AddWith.%Self: (%.2)]; +// CHECK:STDOUT: generic [file.%T.loc4_19.2: type, @AddWith.%Self: .inst+17 (%.2)]; // CHECK:STDOUT: // CHECK:STDOUT: specific file.%AddWith.decl(constants.%T) { // CHECK:STDOUT: declaration: @@ -89,7 +89,7 @@ impl C as AddWith(C) { // CHECK:STDOUT: %AddWith.type: type = generic_interface_type @AddWith [template] // CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %AddWith: %AddWith.type = struct_value () [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, .inst+14 [symbolic] // CHECK:STDOUT: %.3: type = interface_type @AddWith, (%T) [symbolic] // CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %.4: type = interface_type @AddWith, (%C) [template] diff --git a/toolchain/check/testdata/operators/builtin/fail_and_or_not_in_function.carbon b/toolchain/check/testdata/operators/builtin/fail_and_or_not_in_function.carbon index 479e71b763d7..c698a982cc6f 100644 --- a/toolchain/check/testdata/operators/builtin/fail_and_or_not_in_function.carbon +++ b/toolchain/check/testdata/operators/builtin/fail_and_or_not_in_function.carbon @@ -66,7 +66,7 @@ var or_: F(true or true); // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: %.loc42_17: bool = block_arg [template = constants.%.3] -// CHECK:STDOUT: %F.call: init type = call (%.loc42_17) +// CHECK:STDOUT: %F.call: init type = call .inst+60.loc42_10(%.loc42_17) // CHECK:STDOUT: %.loc42_24.1: type = value_of_initializer %F.call // CHECK:STDOUT: %.loc42_24.2: type = converted %F.call, %.loc42_24.1 // CHECK:STDOUT: %or_.var: ref = var or_ diff --git a/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon b/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon index a89ec94087c8..0d3ca81b4930 100644 --- a/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon +++ b/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon @@ -78,7 +78,7 @@ export C2(T:! type); // CHECK:STDOUT: %C1.type: type = generic_class_type @C1 [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %C1.1: %C1.type = struct_value () [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, .inst+18 [symbolic] // CHECK:STDOUT: %C1.2: type = class_type @C1, (%T) [symbolic] // CHECK:STDOUT: %C2.type: type = generic_class_type @C2 [template] // CHECK:STDOUT: %C2.1: %C2.type = struct_value () [template] diff --git a/toolchain/check/testdata/return/fail_let_in_type.carbon b/toolchain/check/testdata/return/fail_let_in_type.carbon index afda030a1a4d..b3588312352b 100644 --- a/toolchain/check/testdata/return/fail_let_in_type.carbon +++ b/toolchain/check/testdata/return/fail_let_in_type.carbon @@ -55,14 +55,14 @@ fn FirstPerfectNumber() -> z { return 6; } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @HalfDozen() -> %y -// CHECK:STDOUT: generic [: type] { +// CHECK:STDOUT: generic [.inst+21.loc19_5: type] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %.loc24: i32 = int_literal 6 [template = constants.%.2] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific (constants.%y) { +// CHECK:STDOUT: specific .inst+29.loc24_21(constants.%y) { // CHECK:STDOUT: declaration: -// CHECK:STDOUT: => constants.%y +// CHECK:STDOUT: .inst+27.loc24_19 => constants.%y // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/struct/import.carbon b/toolchain/check/testdata/struct/import.carbon index 72f1147e2701..befabf76dd9e 100644 --- a/toolchain/check/testdata/struct/import.carbon +++ b/toolchain/check/testdata/struct/import.carbon @@ -217,7 +217,7 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] // CHECK:STDOUT: %.10: type = struct_type {} [template] // CHECK:STDOUT: %.11: type = struct_type {.a: i32, .b: i32} [template] -// CHECK:STDOUT: %S: %.11 = bind_symbolic_name S 0, [symbolic] +// CHECK:STDOUT: %S: %.11 = bind_symbolic_name S 0, .inst+103 [symbolic] // CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] // CHECK:STDOUT: %.12: i32 = int_literal 1 [template] // CHECK:STDOUT: %.13: i32 = int_literal 2 [template] @@ -349,7 +349,7 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = struct_type {.a: i32, .b: i32} [template] -// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, [symbolic] +// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, .inst+21 [symbolic] // CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] @@ -422,7 +422,7 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = struct_type {.a: i32, .b: i32} [template] -// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, [symbolic] +// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, .inst+21 [symbolic] // CHECK:STDOUT: %C.2: type = class_type @C, (%S) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 3 [template] // CHECK:STDOUT: %.5: i32 = int_literal 4 [template] diff --git a/toolchain/check/testdata/tuples/import.carbon b/toolchain/check/testdata/tuples/import.carbon index 704ec1e388fb..ea669d5432a9 100644 --- a/toolchain/check/testdata/tuples/import.carbon +++ b/toolchain/check/testdata/tuples/import.carbon @@ -242,7 +242,7 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %C.type: type = generic_class_type @C [template] // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] // CHECK:STDOUT: %.14: type = struct_type {} [template] -// CHECK:STDOUT: %X: %.8 = bind_symbolic_name X 0, [symbolic] +// CHECK:STDOUT: %X: %.8 = bind_symbolic_name X 0, .inst+105 [symbolic] // CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] // CHECK:STDOUT: %.15: i32 = int_literal 1 [template] // CHECK:STDOUT: %.16: i32 = int_literal 2 [template] @@ -390,7 +390,7 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] -// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, [symbolic] +// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, .inst+17 [symbolic] // CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] @@ -465,7 +465,7 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] -// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, [symbolic] +// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, .inst+17 [symbolic] // CHECK:STDOUT: %C.2: type = class_type @C, (%X) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 3 [template] // CHECK:STDOUT: %.5: i32 = int_literal 4 [template] diff --git a/toolchain/driver/driver.cpp b/toolchain/driver/driver.cpp index 66a942fbca5f..26ff39cb8c31 100644 --- a/toolchain/driver/driver.cpp +++ b/toolchain/driver/driver.cpp @@ -641,13 +641,16 @@ class Driver::CompilationUnit { } } - if (vlog_stream_) { - CARBON_VLOG() << "*** SemIR::File ***\n"; - SemIR::FormatFile(*tokens_, *parse_tree_, *sem_ir_, *vlog_stream_); - } - if (options_.dump_sem_ir && IncludeInDumps()) { - SemIR::FormatFile(*tokens_, *parse_tree_, *sem_ir_, - driver_->output_stream_); + bool print = options_.dump_sem_ir && IncludeInDumps(); + if (vlog_stream_ || print) { + SemIR::Formatter formatter(*tokens_, *parse_tree_, *sem_ir_); + if (vlog_stream_) { + CARBON_VLOG() << "*** SemIR::File ***\n"; + formatter.Print(*vlog_stream_); + } + if (print) { + formatter.Print(driver_->output_stream_); + } } if (sem_ir_->has_errors()) { success_ = false; diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index a630f10411e0..021b0b164a9d 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -22,16 +22,11 @@ namespace Carbon::SemIR { // Formatter for printing textual Semantics IR. -class Formatter { +class FormatterImpl { public: - enum class AddSpace : bool { Before, After }; - - explicit Formatter(const Lex::TokenizedBuffer& tokenized_buffer, - const Parse::Tree& parse_tree, const File& sem_ir, - llvm::raw_ostream& out) - : sem_ir_(sem_ir), - out_(out), - inst_namer_(tokenized_buffer, parse_tree, sem_ir) {} + explicit FormatterImpl(const File& sem_ir, InstNamer* inst_namer, + llvm::raw_ostream& out, int indent) + : sem_ir_(sem_ir), inst_namer_(inst_namer), out_(out), indent_(indent) {} // Prints the SemIR. // @@ -44,7 +39,7 @@ class Formatter { FormatConstants(); FormatImportRefs(); - out_ << inst_namer_.GetScopeName(InstNamer::ScopeId::File) << " "; + out_ << inst_namer_->GetScopeName(InstNamer::ScopeId::File) << " "; OpenBrace(); // TODO: Handle the case where there are multiple top-level instruction @@ -82,6 +77,37 @@ class Formatter { out_ << "\n"; } + // Prints a code block. + auto FormatPartialTrailingCodeBlock(llvm::ArrayRef block) + -> void { + out_ << ' '; + OpenBrace(); + constexpr int NumPrintedOnSkip = 9; + // Avoid only skipping one item. + if (block.size() > NumPrintedOnSkip + 1) { + Indent(); + out_ << "... skipping " << (block.size() - NumPrintedOnSkip) + << " insts ...\n"; + block = block.take_back(NumPrintedOnSkip); + } + FormatCodeBlock(block); + CloseBrace(); + } + + // Prints a single instruction. + auto FormatInstruction(InstId inst_id) -> void { + if (!inst_id.is_valid()) { + Indent(); + out_ << "invalid\n"; + return; + } + + FormatInstruction(inst_id, sem_ir_.insts().Get(inst_id)); + } + + private: + enum class AddSpace : bool { Before, After }; + // Begins a braced block. Writes an open brace, and prepares to insert a // newline after it if the braced block is non-empty. auto OpenBrace() -> void { @@ -139,7 +165,7 @@ class Formatter { } llvm::SaveAndRestore constants_scope(scope_, InstNamer::ScopeId::Constants); - out_ << inst_namer_.GetScopeName(InstNamer::ScopeId::Constants) << " "; + out_ << inst_namer_->GetScopeName(InstNamer::ScopeId::Constants) << " "; OpenBrace(); FormatCodeBlock(sem_ir_.constants().array_ref()); CloseBrace(); @@ -153,7 +179,7 @@ class Formatter { } llvm::SaveAndRestore scope(scope_, InstNamer::ScopeId::ImportRefs); - out_ << inst_namer_.GetScopeName(InstNamer::ScopeId::ImportRefs) << " "; + out_ << inst_namer_->GetScopeName(InstNamer::ScopeId::ImportRefs) << " "; OpenBrace(); FormatCodeBlock(import_refs); CloseBrace(); @@ -170,7 +196,7 @@ class Formatter { FormatGeneric(class_info.generic_id); } - llvm::SaveAndRestore class_scope(scope_, inst_namer_.GetScopeFor(id)); + llvm::SaveAndRestore class_scope(scope_, inst_namer_->GetScopeFor(id)); if (class_info.scope_id.is_valid()) { out_ << ' '; @@ -194,7 +220,7 @@ class Formatter { FormatGeneric(interface_info.generic_id); } - llvm::SaveAndRestore interface_scope(scope_, inst_namer_.GetScopeFor(id)); + llvm::SaveAndRestore interface_scope(scope_, inst_namer_->GetScopeFor(id)); if (interface_info.scope_id.is_valid()) { out_ << ' '; @@ -230,7 +256,7 @@ class Formatter { out_ << " as "; FormatType(impl_info.constraint_id); - llvm::SaveAndRestore impl_scope(scope_, inst_namer_.GetScopeFor(id)); + llvm::SaveAndRestore impl_scope(scope_, inst_namer_->GetScopeFor(id)); if (impl_info.scope_id.is_valid()) { out_ << ' '; @@ -267,7 +293,7 @@ class Formatter { out_ << "fn "; FormatFunctionName(id); - llvm::SaveAndRestore function_scope(scope_, inst_namer_.GetScopeFor(id)); + llvm::SaveAndRestore function_scope(scope_, inst_namer_->GetScopeFor(id)); if (fn.implicit_param_refs_id.is_valid()) { out_ << "["; @@ -462,16 +488,6 @@ class Formatter { } } - auto FormatInstruction(InstId inst_id) -> void { - if (!inst_id.is_valid()) { - Indent(); - out_ << "invalid\n"; - return; - } - - FormatInstruction(inst_id, sem_ir_.insts().Get(inst_id)); - } - auto FormatInstruction(InstId inst_id, Inst inst) -> void { CARBON_KIND_SWITCH(inst) { #define CARBON_SEM_IR_INST_KIND(InstT) \ @@ -909,26 +925,28 @@ class Formatter { } auto FormatInstName(InstId id) -> void { - out_ << inst_namer_.GetNameFor(scope_, id); + out_ << inst_namer_->GetNameFor(scope_, id); } auto FormatLabel(InstBlockId id) -> void { - out_ << inst_namer_.GetLabelFor(scope_, id); + out_ << inst_namer_->GetLabelFor(scope_, id); } auto FormatFunctionName(FunctionId id) -> void { - out_ << inst_namer_.GetNameFor(id); + out_ << inst_namer_->GetNameFor(id); } auto FormatClassName(ClassId id) -> void { - out_ << inst_namer_.GetNameFor(id); + out_ << inst_namer_->GetNameFor(id); } auto FormatInterfaceName(InterfaceId id) -> void { - out_ << inst_namer_.GetNameFor(id); + out_ << inst_namer_->GetNameFor(id); } - auto FormatImplName(ImplId id) -> void { out_ << inst_namer_.GetNameFor(id); } + auto FormatImplName(ImplId id) -> void { + out_ << inst_namer_->GetNameFor(id); + } auto FormatSpecificName(GenericInstanceId id) -> void { const auto& specific = sem_ir_.generic_instances().Get(id); @@ -982,10 +1000,11 @@ class Formatter { } } - private: const File& sem_ir_; + InstNamer* const inst_namer_; + + // The output stream. Set while formatting instructions. llvm::raw_ostream& out_; - InstNamer inst_namer_; // The current scope that we are formatting within. References to names in // this scope will not have a `@scope.` prefix added. @@ -997,7 +1016,7 @@ class Formatter { bool in_terminator_sequence_ = false; // The indent depth to use for new instructions. - int indent_ = 0; + int indent_; // Whether we are currently formatting immediately after an open brace. If so, // a newline will be inserted before the next line indent. @@ -1014,10 +1033,28 @@ class Formatter { bool pending_constant_value_is_self_ = false; }; -auto FormatFile(const Lex::TokenizedBuffer& tokenized_buffer, - const Parse::Tree& parse_tree, const File& sem_ir, - llvm::raw_ostream& out) -> void { - Formatter(tokenized_buffer, parse_tree, sem_ir, out).Format(); +Formatter::Formatter(const Lex::TokenizedBuffer& tokenized_buffer, + const Parse::Tree& parse_tree, const File& sem_ir) + : sem_ir_(sem_ir), inst_namer_(tokenized_buffer, parse_tree, sem_ir) {} + +Formatter::~Formatter() = default; + +auto Formatter::Print(llvm::raw_ostream& out) -> void { + FormatterImpl formatter(sem_ir_, &inst_namer_, out, /*indent=*/0); + formatter.Format(); +} + +auto Formatter::PrintPartialTrailingCodeBlock( + llvm::ArrayRef block, int indent, llvm::raw_ostream& out) + -> void { + FormatterImpl formatter(sem_ir_, &inst_namer_, out, indent); + formatter.FormatPartialTrailingCodeBlock(block); +} + +auto Formatter::PrintInst(SemIR::InstId inst_id, int indent, + llvm::raw_ostream& out) -> void { + FormatterImpl formatter(sem_ir_, &inst_namer_, out, indent); + formatter.FormatInstruction(inst_id); } } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/formatter.h b/toolchain/sem_ir/formatter.h index c7d744afd0e9..7a2ff326159b 100644 --- a/toolchain/sem_ir/formatter.h +++ b/toolchain/sem_ir/formatter.h @@ -9,12 +9,33 @@ #include "toolchain/lex/tokenized_buffer.h" #include "toolchain/parse/tree.h" #include "toolchain/sem_ir/file.h" +#include "toolchain/sem_ir/inst_namer.h" namespace Carbon::SemIR { -auto FormatFile(const Lex::TokenizedBuffer& tokenized_buffer, - const Parse::Tree& parse_tree, const File& sem_ir, - llvm::raw_ostream& out) -> void; +// Formatter for printing textual Semantics IR. +class Formatter { + public: + explicit Formatter(const Lex::TokenizedBuffer& tokenized_buffer, + const Parse::Tree& parse_tree, const File& sem_ir); + ~Formatter(); + + // Prints the full IR. + auto Print(llvm::raw_ostream& out) -> void; + // Prints a single code block. Only prints the last several instructions of + // large blocks. + auto PrintPartialTrailingCodeBlock(llvm::ArrayRef block, + int indent, llvm::raw_ostream& out) + -> void; + // Prints a single instruction. + auto PrintInst(SemIR::InstId inst_id, int indent, llvm::raw_ostream& out) + -> void; + + private: + const File& sem_ir_; + // Caches naming between Print calls. + InstNamer inst_namer_; +}; } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/inst_namer.cpp b/toolchain/sem_ir/inst_namer.cpp index 4e6620fee653..470b6f156612 100644 --- a/toolchain/sem_ir/inst_namer.cpp +++ b/toolchain/sem_ir/inst_namer.cpp @@ -152,7 +152,15 @@ auto InstNamer::GetNameFor(ScopeId scope_id, InstId inst_id) const if (!inst_name) { // This should not happen in valid IR. std::string str; - llvm::raw_string_ostream(str) << ""; + llvm::raw_string_ostream str_stream(str); + str_stream << "." << inst_id; + auto loc_id = sem_ir_.insts().GetLocId(inst_id); + // TODO: Consider handling inst_id cases. + if (loc_id.is_node_id()) { + auto token = parse_tree_.node_token(loc_id.node_id()); + str_stream << ".loc" << tokenized_buffer_.GetLineNumber(token) << "_" + << tokenized_buffer_.GetColumnNumber(token); + } return str; } if (inst_scope == scope_id) {