From 3af7eb26721000208aa1f2f753af0c19d9339dd0 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Thu, 26 Oct 2023 11:50:30 -0700 Subject: [PATCH] Refactor YAML handling to use the llvm::yaml API. (#3337) Provides an adapter for the llvm::yaml API because it otherwise needs a bunch of const/non-const definitions, and the traits are difficult to diagnose issues with. The current approach is pretty simple to use, even if it's not super efficient (which, yaml output is more of a debugging thing so I'm not really expecting it to be an issue). Changes the format of yaml output to provide more index information, just as reminders when seeing something like `node+0`. Note this would create more churn in deltas if we were reliant on the output yaml in tests, but we aren't so it should be okay. --- common/ostream.h | 10 ++ toolchain/base/BUILD | 11 ++ toolchain/base/value_store.h | 115 ++++----------- toolchain/base/value_store_test.cpp | 23 +-- toolchain/base/yaml.h | 115 +++++++++++++++ .../testdata/basics/builtin_nodes.carbon | 38 ++--- .../multifile_raw_and_textual_ir.carbon | 72 +++++---- .../testdata/basics/multifile_raw_ir.carbon | 72 +++++---- .../testdata/basics/raw_and_textual_ir.carbon | 139 ++++++++++-------- toolchain/check/testdata/basics/raw_ir.carbon | 139 ++++++++++-------- .../driver/testdata/dump_shared_values.carbon | 46 +++--- toolchain/lex/tokenized_buffer_test.cpp | 2 +- toolchain/sem_ir/BUILD | 2 + toolchain/sem_ir/file.cpp | 46 +++--- toolchain/sem_ir/file.h | 9 +- toolchain/sem_ir/value_stores.h | 28 ++-- toolchain/sem_ir/yaml_test.cpp | 47 +++--- 17 files changed, 523 insertions(+), 391 deletions(-) create mode 100644 toolchain/base/yaml.h diff --git a/common/ostream.h b/common/ostream.h index aa82f7436589..b01d393f2afb 100644 --- a/common/ostream.h +++ b/common/ostream.h @@ -6,6 +6,7 @@ #define CARBON_COMMON_OSTREAM_H_ #include +#include #include "llvm/Support/raw_os_ostream.h" // Libraries should include this header instead of raw_ostream. @@ -50,6 +51,15 @@ class Printable { } }; +// Returns the result of printing the value. +template +inline auto PrintToString(const T& val) -> std::string { + std::string str; + llvm::raw_string_ostream stream(str); + stream << val; + return str; +} + } // namespace Carbon namespace llvm { diff --git a/toolchain/base/BUILD b/toolchain/base/BUILD index 34ed65e62c7f..dbd3a85d4eb1 100644 --- a/toolchain/base/BUILD +++ b/toolchain/base/BUILD @@ -28,6 +28,7 @@ cc_library( hdrs = ["value_store.h"], deps = [ ":index_base", + ":yaml", "//common:check", "//common:ostream", "@llvm-project//llvm:Support", @@ -46,3 +47,13 @@ cc_test( "@com_google_googletest//:gtest", ], ) + +cc_library( + name = "yaml", + hdrs = ["yaml.h"], + deps = [ + "//common:check", + "//common:ostream", + "@llvm-project//llvm:Support", + ], +) diff --git a/toolchain/base/value_store.h b/toolchain/base/value_store.h index 2572af2a953f..56621951db54 100644 --- a/toolchain/base/value_store.h +++ b/toolchain/base/value_store.h @@ -12,10 +12,12 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/YAMLParser.h" #include "toolchain/base/index_base.h" +#include "toolchain/base/yaml.h" namespace Carbon { @@ -86,73 +88,14 @@ namespace Internal { // Used as a parent class for non-printable types. This is just for // std::conditional, not as an API. class ValueStoreNotPrintable {}; - -// Provides YAML printing of a value. -template -inline auto PrintValue(llvm::raw_ostream& out, const ValueT& val) { - out << val; -}; -inline auto PrintValue(llvm::raw_ostream& out, const llvm::APInt& val) { - val.print(out, /*isSigned=*/false); -}; -inline auto PrintValue(llvm::raw_ostream& out, const llvm::StringRef& val) { - out << "\"" << llvm::yaml::escape(val) << "\""; -}; - -struct DefaultPrinter { - template - void operator()(llvm::raw_ostream& out, const ValueT& value) { - PrintValue(out, value); - } -}; - } // namespace Internal -// Provides YAML printing of a list. The first line indent applies even if there -// is no label, in which case it applies to the first element. -template -inline auto PrintValueRange( - llvm::raw_ostream& out, llvm::iterator_range range, - std::optional label, int first_line_indent, - int later_indent, bool trailing_newline, - llvm::function_ref print = - Internal::DefaultPrinter()) { - out.indent(first_line_indent); - if (label) { - out << *label << ":"; - if (range.empty()) { - // Add a space between the `:` and the `[]` printed below. - out << " "; - } else { - out << "\n"; - out.indent(later_indent); - } - } - if (range.empty()) { - out << "[]"; - if (trailing_newline) { - out << "\n"; - } - return; - } - std::string sep_str = "\n"; - sep_str.append(later_indent, ' '); - llvm::ListSeparator sep(sep_str); - for (const auto& val : range) { - out << sep << "- "; - print(out, val); - } - if (trailing_newline) { - out << "\n"; - } -} - // A simple wrapper for accumulating values, providing IDs to later retrieve the // value. This does not do deduplication. template class ValueStore : public std::conditional, ValueT>, - Printable>, + Yaml::Printable>, Internal::ValueStoreNotPrintable> { public: using PrintFn = @@ -189,17 +132,13 @@ class ValueStore auto Reserve(size_t size) -> void { values_.reserve(size); } // These are to support printable structures, and are not guaranteed. - auto Print(llvm::raw_ostream& out) const -> void { - Print(out, std::nullopt, 0, 0); - } - auto Print(llvm::raw_ostream& out, std::optional label, - int first_line_indent, int later_indent, - // This decays so that `const llvm::APInt` printing catches the - // specialization. - PrintFn print = Internal::DefaultPrinter()) const -> void { - PrintValueRange(out, llvm::iterator_range(values_), label, - first_line_indent, later_indent, /*trailing_newline=*/true, - print); + auto OutputYaml() const -> Yaml::OutputMapping { + return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + for (auto i : llvm::seq(values_.size())) { + auto id = IdT(i); + map.Add(PrintToString(id), Yaml::OutputScalar(Get(id))); + } + }); } auto array_ref() const -> llvm::ArrayRef { return values_; } @@ -212,7 +151,7 @@ class ValueStore // Storage for StringRefs. The caller is responsible for ensuring storage is // allocated. template <> -class ValueStore : public Printable> { +class ValueStore : public Yaml::Printable> { public: using PrintFn = llvm::function_ref; @@ -234,15 +173,12 @@ class ValueStore : public Printable> { return values_[id.index]; } - auto Print(llvm::raw_ostream& out) const -> void { - Print(out, std::nullopt, 0, 0); - } - auto Print(llvm::raw_ostream& out, std::optional label, - int first_line_indent, int later_indent, - PrintFn print = Internal::DefaultPrinter()) const -> void { - PrintValueRange(out, llvm::iterator_range(values_), label, - first_line_indent, later_indent, /*trailing_newline=*/true, - print); + auto OutputYaml() const -> Yaml::OutputMapping { + return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + for (auto [i, val] : llvm::enumerate(values_)) { + map.Add(PrintToString(StringId(i)), val); + } + }); } private: @@ -252,7 +188,7 @@ class ValueStore : public Printable> { // Stores that will be used across compiler steps. This is provided mainly so // that they don't need to be passed separately. -class SharedValueStores : public Printable { +class SharedValueStores : public Yaml::Printable { public: auto integers() -> ValueStore& { return integers_; } auto integers() const -> const ValueStore& { return integers_; } @@ -261,12 +197,15 @@ class SharedValueStores : public Printable { auto strings() -> ValueStore& { return strings_; } auto strings() const -> const ValueStore& { return strings_; } - auto Print(llvm::raw_ostream& out) const -> void { - out << "shared_values:\n" - << " - "; - integers_.Print(out, "integers", 0, 6); - reals_.Print(out, "reals", 4, 6); - strings_.Print(out, "strings", 4, 6); + auto OutputYaml() const -> Yaml::OutputMapping { + return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + map.Add("shared_values", + Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + map.Add("integers", integers_.OutputYaml()); + map.Add("reals", reals_.OutputYaml()); + map.Add("strings", strings_.OutputYaml()); + })); + }); } private: diff --git a/toolchain/base/value_store_test.cpp b/toolchain/base/value_store_test.cpp index d248ae7d3273..c0bb41c4011f 100644 --- a/toolchain/base/value_store_test.cpp +++ b/toolchain/base/value_store_test.cpp @@ -78,14 +78,14 @@ TEST(ValueStore, String) { EXPECT_THAT(value_stores.strings().Add(b), Eq(b_id)); } -auto MatchSharedValues(testing::Matcher integers, - testing::Matcher reals, - testing::Matcher strings) -> auto { +auto MatchSharedValues(testing::Matcher integers, + testing::Matcher reals, + testing::Matcher strings) -> auto { return Yaml::IsYaml(Yaml::Sequence(ElementsAre(Yaml::Mapping(ElementsAre(Pair( - "shared_values", Yaml::Sequence(ElementsAre(Yaml::Mapping(ElementsAre( - Pair("integers", Yaml::Sequence(integers)), - Pair("reals", Yaml::Sequence(reals)), - Pair("strings", Yaml::Sequence(strings)))))))))))); + "shared_values", + Yaml::Mapping(ElementsAre(Pair("integers", Yaml::Mapping(integers)), + Pair("reals", Yaml::Mapping(reals)), + Pair("strings", Yaml::Mapping(strings)))))))))); } TEST(ValueStore, PrintEmpty) { @@ -106,10 +106,11 @@ TEST(ValueStore, PrintVals) { TestRawOstream out; value_stores.Print(out); - EXPECT_THAT(Yaml::Value::FromText(out.TakeStr()), - MatchSharedValues(ElementsAre(Yaml::Scalar("8")), - ElementsAre(Yaml::Scalar("8*10^8")), - ElementsAre(Yaml::Scalar("foo'\"baz")))); + EXPECT_THAT( + Yaml::Value::FromText(out.TakeStr()), + MatchSharedValues(ElementsAre(Pair("int0", Yaml::Scalar("8"))), + ElementsAre(Pair("real0", Yaml::Scalar("8*10^8"))), + ElementsAre(Pair("str0", Yaml::Scalar("foo'\"baz"))))); } } // namespace diff --git a/toolchain/base/yaml.h b/toolchain/base/yaml.h new file mode 100644 index 000000000000..86496836a4d9 --- /dev/null +++ b/toolchain/base/yaml.h @@ -0,0 +1,115 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_BASE_YAML_H_ +#define CARBON_TOOLCHAIN_BASE_YAML_H_ + +#include "common/check.h" +#include "common/ostream.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/YAMLTraits.h" + +// This file provides adapters for outputting YAML using llvm::yaml's APIs. It +// only supports output, not input. However, it addresses the mix of const and +// non-const expectations of the llvm::yaml that make it difficult to otherwise +// use the trait-based approach. + +namespace Carbon::Yaml { + +// Helper for printing YAML, to maintain a consistent configuration. +template +inline auto Print(llvm::raw_ostream& out, T yaml) -> void { + llvm::yaml::Output yout(out, /*Ctxt=*/nullptr, /*WrapColumn=*/80); + yout << yaml; +} + +// Similar to the standard Printable, but relies on OutputYaml for printing. +template +class Printable : public Carbon::Printable { + public: + auto Print(llvm::raw_ostream& out) const -> void { + Carbon::Yaml::Print(out, static_cast(this)->OutputYaml()); + } +}; + +// Adapts a function for outputting YAML as a scalar. This currently assumes no +// scalars passed through this should be quoted. +class OutputScalar { + public: + template + explicit OutputScalar(const T& val) + : output_([&](llvm::raw_ostream& out) -> void { out << val; }) {} + + explicit OutputScalar(const llvm::APInt& val) + : output_([&](llvm::raw_ostream& out) -> void { + // Carbon's plain APInt storage is typically unsigned. + val.print(out, /*isSigned=*/false); + }) {} + + explicit OutputScalar(std::function output) + : output_(std::move(output)) {} + + auto Output(llvm::raw_ostream& out) const -> void { output_(out); } + + private: + std::function output_; +}; + +// Adapts a function for outputting YAML as a mapping. +class OutputMapping { + public: + class Map { + public: + explicit Map(llvm::yaml::IO& io) : io_(io) {} + + // Maps a value. This mainly takes responsibility for copying the value, + // letting mapRequired take `&value`. + template + auto Add(llvm::StringRef key, T value) -> void { + io_.mapRequired(key.data(), value); + } + + private: + llvm::yaml::IO& io_; + }; + + explicit OutputMapping(std::function output) + : output_(std::move(output)) {} + + auto Output(llvm::yaml::IO& io) -> void { output_(Map(io)); } + + private: + std::function output_; +}; + +} // namespace Carbon::Yaml + +// Link OutputScalar to the llvm::yaml::IO API. +template <> +struct llvm::yaml::ScalarTraits { + static auto output(const Carbon::Yaml::OutputScalar& value, void* /*ctxt*/, + llvm::raw_ostream& out) -> void { + value.Output(out); + } + static auto input(StringRef /*scalar*/, void* /*ctxt*/, + Carbon::Yaml::OutputScalar& /*value*/) -> StringRef { + CARBON_FATAL() << "Input is unsupported."; + } + static auto mustQuote(StringRef /*value*/) -> QuotingType { + return QuotingType::None; + } +}; +static_assert(llvm::yaml::has_ScalarTraits::value); + +// Link OutputMapping to the llvm::yaml::IO API. +template <> +struct llvm::yaml::MappingTraits { + static auto mapping(IO& io, Carbon::Yaml::OutputMapping& mapping) -> void { + mapping.Output(io); + } +}; +static_assert(llvm::yaml::has_MappingTraits::value); + +#endif // CARBON_TOOLCHAIN_BASE_YAML_H_ diff --git a/toolchain/check/testdata/basics/builtin_nodes.carbon b/toolchain/check/testdata/basics/builtin_nodes.carbon index b6453ecb8c4e..2e12bacb06bc 100644 --- a/toolchain/check/testdata/basics/builtin_nodes.carbon +++ b/toolchain/check/testdata/basics/builtin_nodes.carbon @@ -6,21 +6,23 @@ // // AUTOUPDATE -// CHECK:STDOUT: - filename: builtin_nodes.carbon -// CHECK:STDOUT: sem_ir: -// CHECK:STDOUT: - cross_reference_irs_size: 1 -// CHECK:STDOUT: functions: [] -// CHECK:STDOUT: classes: [] -// CHECK:STDOUT: types: [] -// CHECK:STDOUT: type_blocks: [] -// CHECK:STDOUT: nodes: -// CHECK:STDOUT: - {kind: CrossReference, arg0: ir0, arg1: nodeTypeType, type: typeTypeType} -// CHECK:STDOUT: - {kind: CrossReference, arg0: ir0, arg1: nodeError, type: typeError} -// CHECK:STDOUT: - {kind: CrossReference, arg0: ir0, arg1: nodeBoolType, type: typeTypeType} -// CHECK:STDOUT: - {kind: CrossReference, arg0: ir0, arg1: nodeIntegerType, type: typeTypeType} -// CHECK:STDOUT: - {kind: CrossReference, arg0: ir0, arg1: nodeFloatingPointType, type: typeTypeType} -// CHECK:STDOUT: - {kind: CrossReference, arg0: ir0, arg1: nodeStringType, type: typeTypeType} -// CHECK:STDOUT: - {kind: CrossReference, arg0: ir0, arg1: nodeFunctionType, type: typeTypeType} -// CHECK:STDOUT: - {kind: CrossReference, arg0: ir0, arg1: nodeNamespaceType, type: typeTypeType} -// CHECK:STDOUT: node_blocks: -// CHECK:STDOUT: - [] +// CHECK:STDOUT: --- +// CHECK:STDOUT: filename: builtin_nodes.carbon +// CHECK:STDOUT: sem_ir: +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: {} +// CHECK:STDOUT: classes: {} +// CHECK:STDOUT: types: {} +// CHECK:STDOUT: type_blocks: {} +// CHECK:STDOUT: nodes: +// CHECK:STDOUT: nodeTypeType: {kind: CrossReference, arg0: ir0, arg1: nodeTypeType, type: typeTypeType} +// CHECK:STDOUT: nodeError: {kind: CrossReference, arg0: ir0, arg1: nodeError, type: typeError} +// CHECK:STDOUT: nodeBoolType: {kind: CrossReference, arg0: ir0, arg1: nodeBoolType, type: typeTypeType} +// CHECK:STDOUT: nodeIntegerType: {kind: CrossReference, arg0: ir0, arg1: nodeIntegerType, type: typeTypeType} +// CHECK:STDOUT: nodeFloatingPointType: {kind: CrossReference, arg0: ir0, arg1: nodeFloatingPointType, type: typeTypeType} +// CHECK:STDOUT: nodeStringType: {kind: CrossReference, arg0: ir0, arg1: nodeStringType, type: typeTypeType} +// CHECK:STDOUT: nodeFunctionType: {kind: CrossReference, arg0: ir0, arg1: nodeFunctionType, type: typeTypeType} +// CHECK:STDOUT: nodeNamespaceType: {kind: CrossReference, arg0: ir0, arg1: nodeNamespaceType, type: typeTypeType} +// CHECK:STDOUT: node_blocks: +// CHECK:STDOUT: block0: {} +// CHECK:STDOUT: ... diff --git a/toolchain/check/testdata/basics/multifile_raw_and_textual_ir.carbon b/toolchain/check/testdata/basics/multifile_raw_and_textual_ir.carbon index 3c706688b4e4..97fb51a9ade2 100644 --- a/toolchain/check/testdata/basics/multifile_raw_and_textual_ir.carbon +++ b/toolchain/check/testdata/basics/multifile_raw_and_textual_ir.carbon @@ -14,22 +14,26 @@ fn A() {} // --- b.carbon fn B() {} -// CHECK:STDOUT: - filename: a.carbon -// CHECK:STDOUT: sem_ir: -// CHECK:STDOUT: - cross_reference_irs_size: 1 -// CHECK:STDOUT: functions: -// CHECK:STDOUT: - {name: str0, param_refs: block0, body: [block1]} -// CHECK:STDOUT: classes: [] -// CHECK:STDOUT: types: -// CHECK:STDOUT: - {node: nodeFunctionType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type_blocks: [] -// CHECK:STDOUT: nodes: -// CHECK:STDOUT: - {kind: FunctionDeclaration, arg0: function0, type: type0} -// CHECK:STDOUT: - {kind: Return} -// CHECK:STDOUT: node_blocks: -// CHECK:STDOUT: - [] -// CHECK:STDOUT: - - node+1 -// CHECK:STDOUT: - - node+0 +// CHECK:STDOUT: --- +// CHECK:STDOUT: filename: a.carbon +// CHECK:STDOUT: sem_ir: +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: +// CHECK:STDOUT: function0: {name: str0, param_refs: block0, body: [block1]} +// CHECK:STDOUT: classes: {} +// CHECK:STDOUT: types: +// CHECK:STDOUT: type0: {node: nodeFunctionType, value_rep: {kind: copy, type: type0}} +// CHECK:STDOUT: type_blocks: {} +// CHECK:STDOUT: nodes: +// CHECK:STDOUT: node+0: {kind: FunctionDeclaration, arg0: function0, type: type0} +// CHECK:STDOUT: node+1: {kind: Return} +// CHECK:STDOUT: node_blocks: +// CHECK:STDOUT: block0: {} +// CHECK:STDOUT: block1: +// CHECK:STDOUT: 0: node+1 +// CHECK:STDOUT: block2: +// CHECK:STDOUT: 0: node+0 +// CHECK:STDOUT: ... // CHECK:STDOUT: // CHECK:STDOUT: file "a.carbon" { // CHECK:STDOUT: %A: = fn_decl @A @@ -39,22 +43,26 @@ fn B() {} // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } -// CHECK:STDOUT: - filename: b.carbon -// CHECK:STDOUT: sem_ir: -// CHECK:STDOUT: - cross_reference_irs_size: 1 -// CHECK:STDOUT: functions: -// CHECK:STDOUT: - {name: str1, param_refs: block0, body: [block1]} -// CHECK:STDOUT: classes: [] -// CHECK:STDOUT: types: -// CHECK:STDOUT: - {node: nodeFunctionType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type_blocks: [] -// CHECK:STDOUT: nodes: -// CHECK:STDOUT: - {kind: FunctionDeclaration, arg0: function0, type: type0} -// CHECK:STDOUT: - {kind: Return} -// CHECK:STDOUT: node_blocks: -// CHECK:STDOUT: - [] -// CHECK:STDOUT: - - node+1 -// CHECK:STDOUT: - - node+0 +// CHECK:STDOUT: --- +// CHECK:STDOUT: filename: b.carbon +// CHECK:STDOUT: sem_ir: +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: +// CHECK:STDOUT: function0: {name: str1, param_refs: block0, body: [block1]} +// CHECK:STDOUT: classes: {} +// CHECK:STDOUT: types: +// CHECK:STDOUT: type0: {node: nodeFunctionType, value_rep: {kind: copy, type: type0}} +// CHECK:STDOUT: type_blocks: {} +// CHECK:STDOUT: nodes: +// CHECK:STDOUT: node+0: {kind: FunctionDeclaration, arg0: function0, type: type0} +// CHECK:STDOUT: node+1: {kind: Return} +// CHECK:STDOUT: node_blocks: +// CHECK:STDOUT: block0: {} +// CHECK:STDOUT: block1: +// CHECK:STDOUT: 0: node+1 +// CHECK:STDOUT: block2: +// CHECK:STDOUT: 0: node+0 +// CHECK:STDOUT: ... // CHECK:STDOUT: // CHECK:STDOUT: file "b.carbon" { // CHECK:STDOUT: %B: = fn_decl @B diff --git a/toolchain/check/testdata/basics/multifile_raw_ir.carbon b/toolchain/check/testdata/basics/multifile_raw_ir.carbon index 19770a279ee7..85683bdda0ae 100644 --- a/toolchain/check/testdata/basics/multifile_raw_ir.carbon +++ b/toolchain/check/testdata/basics/multifile_raw_ir.carbon @@ -14,35 +14,43 @@ fn A() {} // --- b.carbon fn B() {} -// CHECK:STDOUT: - filename: a.carbon -// CHECK:STDOUT: sem_ir: -// CHECK:STDOUT: - cross_reference_irs_size: 1 -// CHECK:STDOUT: functions: -// CHECK:STDOUT: - {name: str0, param_refs: block0, body: [block1]} -// CHECK:STDOUT: classes: [] -// CHECK:STDOUT: types: -// CHECK:STDOUT: - {node: nodeFunctionType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type_blocks: [] -// CHECK:STDOUT: nodes: -// CHECK:STDOUT: - {kind: FunctionDeclaration, arg0: function0, type: type0} -// CHECK:STDOUT: - {kind: Return} -// CHECK:STDOUT: node_blocks: -// CHECK:STDOUT: - [] -// CHECK:STDOUT: - - node+1 -// CHECK:STDOUT: - - node+0 -// CHECK:STDOUT: - filename: b.carbon -// CHECK:STDOUT: sem_ir: -// CHECK:STDOUT: - cross_reference_irs_size: 1 -// CHECK:STDOUT: functions: -// CHECK:STDOUT: - {name: str1, param_refs: block0, body: [block1]} -// CHECK:STDOUT: classes: [] -// CHECK:STDOUT: types: -// CHECK:STDOUT: - {node: nodeFunctionType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: type_blocks: [] -// CHECK:STDOUT: nodes: -// CHECK:STDOUT: - {kind: FunctionDeclaration, arg0: function0, type: type0} -// CHECK:STDOUT: - {kind: Return} -// CHECK:STDOUT: node_blocks: -// CHECK:STDOUT: - [] -// CHECK:STDOUT: - - node+1 -// CHECK:STDOUT: - - node+0 +// CHECK:STDOUT: --- +// CHECK:STDOUT: filename: a.carbon +// CHECK:STDOUT: sem_ir: +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: +// CHECK:STDOUT: function0: {name: str0, param_refs: block0, body: [block1]} +// CHECK:STDOUT: classes: {} +// CHECK:STDOUT: types: +// CHECK:STDOUT: type0: {node: nodeFunctionType, value_rep: {kind: copy, type: type0}} +// CHECK:STDOUT: type_blocks: {} +// CHECK:STDOUT: nodes: +// CHECK:STDOUT: node+0: {kind: FunctionDeclaration, arg0: function0, type: type0} +// CHECK:STDOUT: node+1: {kind: Return} +// CHECK:STDOUT: node_blocks: +// CHECK:STDOUT: block0: {} +// CHECK:STDOUT: block1: +// CHECK:STDOUT: 0: node+1 +// CHECK:STDOUT: block2: +// CHECK:STDOUT: 0: node+0 +// CHECK:STDOUT: ... +// CHECK:STDOUT: --- +// CHECK:STDOUT: filename: b.carbon +// CHECK:STDOUT: sem_ir: +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: +// CHECK:STDOUT: function0: {name: str1, param_refs: block0, body: [block1]} +// CHECK:STDOUT: classes: {} +// CHECK:STDOUT: types: +// CHECK:STDOUT: type0: {node: nodeFunctionType, value_rep: {kind: copy, type: type0}} +// CHECK:STDOUT: type_blocks: {} +// CHECK:STDOUT: nodes: +// CHECK:STDOUT: node+0: {kind: FunctionDeclaration, arg0: function0, type: type0} +// CHECK:STDOUT: node+1: {kind: Return} +// CHECK:STDOUT: node_blocks: +// CHECK:STDOUT: block0: {} +// CHECK:STDOUT: block1: +// CHECK:STDOUT: 0: node+1 +// CHECK:STDOUT: block2: +// CHECK:STDOUT: 0: node+0 +// CHECK:STDOUT: ... diff --git a/toolchain/check/testdata/basics/raw_and_textual_ir.carbon b/toolchain/check/testdata/basics/raw_and_textual_ir.carbon index d6bfbfdfa667..e24c3068a32f 100644 --- a/toolchain/check/testdata/basics/raw_and_textual_ir.carbon +++ b/toolchain/check/testdata/basics/raw_and_textual_ir.carbon @@ -12,70 +12,81 @@ fn Foo(n: i32) -> (i32, f64) { return (n + 2, 3.4); } -// CHECK:STDOUT: - filename: raw_and_textual_ir.carbon -// CHECK:STDOUT: sem_ir: -// CHECK:STDOUT: - cross_reference_irs_size: 1 -// CHECK:STDOUT: functions: -// CHECK:STDOUT: - {name: str0, param_refs: block1, return_type: type3, return_slot: node+4, body: [block4]} -// CHECK:STDOUT: classes: [] -// CHECK:STDOUT: types: -// CHECK:STDOUT: - {node: nodeIntegerType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: - {node: node+1, value_rep: {kind: unknown, type: type}} -// CHECK:STDOUT: - {node: nodeFloatingPointType, value_rep: {kind: copy, type: type2}} -// CHECK:STDOUT: - {node: node+3, value_rep: {kind: pointer, type: type4}} -// CHECK:STDOUT: - {node: node+5, value_rep: {kind: copy, type: type4}} -// CHECK:STDOUT: - {node: nodeFunctionType, value_rep: {kind: copy, type: type5}} -// CHECK:STDOUT: type_blocks: -// CHECK:STDOUT: - - typeTypeType -// CHECK:STDOUT: - typeTypeType -// CHECK:STDOUT: - - type0 -// CHECK:STDOUT: - type2 -// CHECK:STDOUT: nodes: -// CHECK:STDOUT: - {kind: Parameter, arg0: str1, type: type0} -// CHECK:STDOUT: - {kind: TupleType, arg0: typeBlock0, type: typeTypeType} -// CHECK:STDOUT: - {kind: TupleLiteral, arg0: block2, type: type1} -// CHECK:STDOUT: - {kind: TupleType, arg0: typeBlock1, type: typeTypeType} -// CHECK:STDOUT: - {kind: VarStorage, arg0: str2, type: type3} -// CHECK:STDOUT: - {kind: PointerType, arg0: type3, type: typeTypeType} -// CHECK:STDOUT: - {kind: FunctionDeclaration, arg0: function0, type: type5} -// CHECK:STDOUT: - {kind: NameReference, arg0: str1, arg1: node+0, type: type0} -// CHECK:STDOUT: - {kind: IntegerLiteral, arg0: int3, type: type0} -// CHECK:STDOUT: - {kind: BinaryOperatorAdd, arg0: node+7, arg1: node+8, type: type0} -// CHECK:STDOUT: - {kind: RealLiteral, arg0: real0, type: type2} -// CHECK:STDOUT: - {kind: TupleLiteral, arg0: block5, type: type3} -// CHECK:STDOUT: - {kind: TupleAccess, arg0: node+4, arg1: member0, type: type0} -// CHECK:STDOUT: - {kind: InitializeFrom, arg0: node+9, arg1: node+12, type: type0} -// CHECK:STDOUT: - {kind: TupleAccess, arg0: node+4, arg1: member1, type: type2} -// CHECK:STDOUT: - {kind: InitializeFrom, arg0: node+10, arg1: node+14, type: type2} -// CHECK:STDOUT: - {kind: TupleInit, arg0: node+11, arg1: block6, type: type3} -// CHECK:STDOUT: - {kind: ReturnExpression, arg0: node+16} -// CHECK:STDOUT: node_blocks: -// CHECK:STDOUT: - [] -// CHECK:STDOUT: - - node+0 -// CHECK:STDOUT: - - nodeIntegerType -// CHECK:STDOUT: - nodeFloatingPointType -// CHECK:STDOUT: - - node+0 -// CHECK:STDOUT: - node+1 -// CHECK:STDOUT: - node+2 -// CHECK:STDOUT: - node+3 -// CHECK:STDOUT: - node+4 -// CHECK:STDOUT: - - node+7 -// CHECK:STDOUT: - node+8 -// CHECK:STDOUT: - node+9 -// CHECK:STDOUT: - node+10 -// CHECK:STDOUT: - node+11 -// CHECK:STDOUT: - node+12 -// CHECK:STDOUT: - node+13 -// CHECK:STDOUT: - node+14 -// CHECK:STDOUT: - node+15 -// CHECK:STDOUT: - node+16 -// CHECK:STDOUT: - node+17 -// CHECK:STDOUT: - - node+9 -// CHECK:STDOUT: - node+10 -// CHECK:STDOUT: - - node+13 -// CHECK:STDOUT: - node+15 -// CHECK:STDOUT: - - node+5 -// CHECK:STDOUT: - node+6 +// CHECK:STDOUT: --- +// CHECK:STDOUT: filename: raw_and_textual_ir.carbon +// CHECK:STDOUT: sem_ir: +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: +// CHECK:STDOUT: function0: {name: str0, param_refs: block1, return_type: type3, return_slot: node+4, body: [block4]} +// CHECK:STDOUT: classes: {} +// CHECK:STDOUT: types: +// CHECK:STDOUT: type0: {node: nodeIntegerType, value_rep: {kind: copy, type: type0}} +// CHECK:STDOUT: type1: {node: node+1, value_rep: {kind: unknown, type: type}} +// CHECK:STDOUT: type2: {node: nodeFloatingPointType, value_rep: {kind: copy, type: type2}} +// CHECK:STDOUT: type3: {node: node+3, value_rep: {kind: pointer, type: type4}} +// CHECK:STDOUT: type4: {node: node+5, value_rep: {kind: copy, type: type4}} +// CHECK:STDOUT: type5: {node: nodeFunctionType, value_rep: {kind: copy, type: type5}} +// CHECK:STDOUT: type_blocks: +// CHECK:STDOUT: typeBlock0: +// CHECK:STDOUT: 0: typeTypeType +// CHECK:STDOUT: 1: typeTypeType +// CHECK:STDOUT: typeBlock1: +// CHECK:STDOUT: 0: type0 +// CHECK:STDOUT: 1: type2 +// CHECK:STDOUT: nodes: +// CHECK:STDOUT: node+0: {kind: Parameter, arg0: str1, type: type0} +// CHECK:STDOUT: node+1: {kind: TupleType, arg0: typeBlock0, type: typeTypeType} +// CHECK:STDOUT: node+2: {kind: TupleLiteral, arg0: block2, type: type1} +// CHECK:STDOUT: node+3: {kind: TupleType, arg0: typeBlock1, type: typeTypeType} +// CHECK:STDOUT: node+4: {kind: VarStorage, arg0: str2, type: type3} +// CHECK:STDOUT: node+5: {kind: PointerType, arg0: type3, type: typeTypeType} +// CHECK:STDOUT: node+6: {kind: FunctionDeclaration, arg0: function0, type: type5} +// CHECK:STDOUT: node+7: {kind: NameReference, arg0: str1, arg1: node+0, type: type0} +// CHECK:STDOUT: node+8: {kind: IntegerLiteral, arg0: int3, type: type0} +// CHECK:STDOUT: node+9: {kind: BinaryOperatorAdd, arg0: node+7, arg1: node+8, type: type0} +// CHECK:STDOUT: node+10: {kind: RealLiteral, arg0: real0, type: type2} +// CHECK:STDOUT: node+11: {kind: TupleLiteral, arg0: block5, type: type3} +// CHECK:STDOUT: node+12: {kind: TupleAccess, arg0: node+4, arg1: member0, type: type0} +// CHECK:STDOUT: node+13: {kind: InitializeFrom, arg0: node+9, arg1: node+12, type: type0} +// CHECK:STDOUT: node+14: {kind: TupleAccess, arg0: node+4, arg1: member1, type: type2} +// CHECK:STDOUT: node+15: {kind: InitializeFrom, arg0: node+10, arg1: node+14, type: type2} +// CHECK:STDOUT: node+16: {kind: TupleInit, arg0: node+11, arg1: block6, type: type3} +// CHECK:STDOUT: node+17: {kind: ReturnExpression, arg0: node+16} +// CHECK:STDOUT: node_blocks: +// CHECK:STDOUT: block0: {} +// CHECK:STDOUT: block1: +// CHECK:STDOUT: 0: node+0 +// CHECK:STDOUT: block2: +// CHECK:STDOUT: 0: nodeIntegerType +// CHECK:STDOUT: 1: nodeFloatingPointType +// CHECK:STDOUT: block3: +// CHECK:STDOUT: 0: node+0 +// CHECK:STDOUT: 1: node+1 +// CHECK:STDOUT: 2: node+2 +// CHECK:STDOUT: 3: node+3 +// CHECK:STDOUT: 4: node+4 +// CHECK:STDOUT: block4: +// CHECK:STDOUT: 0: node+7 +// CHECK:STDOUT: 1: node+8 +// CHECK:STDOUT: 2: node+9 +// CHECK:STDOUT: 3: node+10 +// CHECK:STDOUT: 4: node+11 +// CHECK:STDOUT: 5: node+12 +// CHECK:STDOUT: 6: node+13 +// CHECK:STDOUT: 7: node+14 +// CHECK:STDOUT: 8: node+15 +// CHECK:STDOUT: 9: node+16 +// CHECK:STDOUT: 10: node+17 +// CHECK:STDOUT: block5: +// CHECK:STDOUT: 0: node+9 +// CHECK:STDOUT: 1: node+10 +// CHECK:STDOUT: block6: +// CHECK:STDOUT: 0: node+13 +// CHECK:STDOUT: 1: node+15 +// CHECK:STDOUT: block7: +// CHECK:STDOUT: 0: node+5 +// CHECK:STDOUT: 1: node+6 +// CHECK:STDOUT: ... // CHECK:STDOUT: // CHECK:STDOUT: file "raw_and_textual_ir.carbon" { // CHECK:STDOUT: %.loc11: type = ptr_type (i32, f64) diff --git a/toolchain/check/testdata/basics/raw_ir.carbon b/toolchain/check/testdata/basics/raw_ir.carbon index 99f50b0c6348..5bb0d0a8fdb6 100644 --- a/toolchain/check/testdata/basics/raw_ir.carbon +++ b/toolchain/check/testdata/basics/raw_ir.carbon @@ -12,67 +12,78 @@ fn Foo(n: i32) -> (i32, f64) { return (n + 2, 3.4); } -// CHECK:STDOUT: - filename: raw_ir.carbon -// CHECK:STDOUT: sem_ir: -// CHECK:STDOUT: - cross_reference_irs_size: 1 -// CHECK:STDOUT: functions: -// CHECK:STDOUT: - {name: str0, param_refs: block1, return_type: type3, return_slot: node+4, body: [block4]} -// CHECK:STDOUT: classes: [] -// CHECK:STDOUT: types: -// CHECK:STDOUT: - {node: nodeIntegerType, value_rep: {kind: copy, type: type0}} -// CHECK:STDOUT: - {node: node+1, value_rep: {kind: unknown, type: type}} -// CHECK:STDOUT: - {node: nodeFloatingPointType, value_rep: {kind: copy, type: type2}} -// CHECK:STDOUT: - {node: node+3, value_rep: {kind: pointer, type: type4}} -// CHECK:STDOUT: - {node: node+5, value_rep: {kind: copy, type: type4}} -// CHECK:STDOUT: - {node: nodeFunctionType, value_rep: {kind: copy, type: type5}} -// CHECK:STDOUT: type_blocks: -// CHECK:STDOUT: - - typeTypeType -// CHECK:STDOUT: - typeTypeType -// CHECK:STDOUT: - - type0 -// CHECK:STDOUT: - type2 -// CHECK:STDOUT: nodes: -// CHECK:STDOUT: - {kind: Parameter, arg0: str1, type: type0} -// CHECK:STDOUT: - {kind: TupleType, arg0: typeBlock0, type: typeTypeType} -// CHECK:STDOUT: - {kind: TupleLiteral, arg0: block2, type: type1} -// CHECK:STDOUT: - {kind: TupleType, arg0: typeBlock1, type: typeTypeType} -// CHECK:STDOUT: - {kind: VarStorage, arg0: str2, type: type3} -// CHECK:STDOUT: - {kind: PointerType, arg0: type3, type: typeTypeType} -// CHECK:STDOUT: - {kind: FunctionDeclaration, arg0: function0, type: type5} -// CHECK:STDOUT: - {kind: NameReference, arg0: str1, arg1: node+0, type: type0} -// CHECK:STDOUT: - {kind: IntegerLiteral, arg0: int3, type: type0} -// CHECK:STDOUT: - {kind: BinaryOperatorAdd, arg0: node+7, arg1: node+8, type: type0} -// CHECK:STDOUT: - {kind: RealLiteral, arg0: real0, type: type2} -// CHECK:STDOUT: - {kind: TupleLiteral, arg0: block5, type: type3} -// CHECK:STDOUT: - {kind: TupleAccess, arg0: node+4, arg1: member0, type: type0} -// CHECK:STDOUT: - {kind: InitializeFrom, arg0: node+9, arg1: node+12, type: type0} -// CHECK:STDOUT: - {kind: TupleAccess, arg0: node+4, arg1: member1, type: type2} -// CHECK:STDOUT: - {kind: InitializeFrom, arg0: node+10, arg1: node+14, type: type2} -// CHECK:STDOUT: - {kind: TupleInit, arg0: node+11, arg1: block6, type: type3} -// CHECK:STDOUT: - {kind: ReturnExpression, arg0: node+16} -// CHECK:STDOUT: node_blocks: -// CHECK:STDOUT: - [] -// CHECK:STDOUT: - - node+0 -// CHECK:STDOUT: - - nodeIntegerType -// CHECK:STDOUT: - nodeFloatingPointType -// CHECK:STDOUT: - - node+0 -// CHECK:STDOUT: - node+1 -// CHECK:STDOUT: - node+2 -// CHECK:STDOUT: - node+3 -// CHECK:STDOUT: - node+4 -// CHECK:STDOUT: - - node+7 -// CHECK:STDOUT: - node+8 -// CHECK:STDOUT: - node+9 -// CHECK:STDOUT: - node+10 -// CHECK:STDOUT: - node+11 -// CHECK:STDOUT: - node+12 -// CHECK:STDOUT: - node+13 -// CHECK:STDOUT: - node+14 -// CHECK:STDOUT: - node+15 -// CHECK:STDOUT: - node+16 -// CHECK:STDOUT: - node+17 -// CHECK:STDOUT: - - node+9 -// CHECK:STDOUT: - node+10 -// CHECK:STDOUT: - - node+13 -// CHECK:STDOUT: - node+15 -// CHECK:STDOUT: - - node+5 -// CHECK:STDOUT: - node+6 +// CHECK:STDOUT: --- +// CHECK:STDOUT: filename: raw_ir.carbon +// CHECK:STDOUT: sem_ir: +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: +// CHECK:STDOUT: function0: {name: str0, param_refs: block1, return_type: type3, return_slot: node+4, body: [block4]} +// CHECK:STDOUT: classes: {} +// CHECK:STDOUT: types: +// CHECK:STDOUT: type0: {node: nodeIntegerType, value_rep: {kind: copy, type: type0}} +// CHECK:STDOUT: type1: {node: node+1, value_rep: {kind: unknown, type: type}} +// CHECK:STDOUT: type2: {node: nodeFloatingPointType, value_rep: {kind: copy, type: type2}} +// CHECK:STDOUT: type3: {node: node+3, value_rep: {kind: pointer, type: type4}} +// CHECK:STDOUT: type4: {node: node+5, value_rep: {kind: copy, type: type4}} +// CHECK:STDOUT: type5: {node: nodeFunctionType, value_rep: {kind: copy, type: type5}} +// CHECK:STDOUT: type_blocks: +// CHECK:STDOUT: typeBlock0: +// CHECK:STDOUT: 0: typeTypeType +// CHECK:STDOUT: 1: typeTypeType +// CHECK:STDOUT: typeBlock1: +// CHECK:STDOUT: 0: type0 +// CHECK:STDOUT: 1: type2 +// CHECK:STDOUT: nodes: +// CHECK:STDOUT: node+0: {kind: Parameter, arg0: str1, type: type0} +// CHECK:STDOUT: node+1: {kind: TupleType, arg0: typeBlock0, type: typeTypeType} +// CHECK:STDOUT: node+2: {kind: TupleLiteral, arg0: block2, type: type1} +// CHECK:STDOUT: node+3: {kind: TupleType, arg0: typeBlock1, type: typeTypeType} +// CHECK:STDOUT: node+4: {kind: VarStorage, arg0: str2, type: type3} +// CHECK:STDOUT: node+5: {kind: PointerType, arg0: type3, type: typeTypeType} +// CHECK:STDOUT: node+6: {kind: FunctionDeclaration, arg0: function0, type: type5} +// CHECK:STDOUT: node+7: {kind: NameReference, arg0: str1, arg1: node+0, type: type0} +// CHECK:STDOUT: node+8: {kind: IntegerLiteral, arg0: int3, type: type0} +// CHECK:STDOUT: node+9: {kind: BinaryOperatorAdd, arg0: node+7, arg1: node+8, type: type0} +// CHECK:STDOUT: node+10: {kind: RealLiteral, arg0: real0, type: type2} +// CHECK:STDOUT: node+11: {kind: TupleLiteral, arg0: block5, type: type3} +// CHECK:STDOUT: node+12: {kind: TupleAccess, arg0: node+4, arg1: member0, type: type0} +// CHECK:STDOUT: node+13: {kind: InitializeFrom, arg0: node+9, arg1: node+12, type: type0} +// CHECK:STDOUT: node+14: {kind: TupleAccess, arg0: node+4, arg1: member1, type: type2} +// CHECK:STDOUT: node+15: {kind: InitializeFrom, arg0: node+10, arg1: node+14, type: type2} +// CHECK:STDOUT: node+16: {kind: TupleInit, arg0: node+11, arg1: block6, type: type3} +// CHECK:STDOUT: node+17: {kind: ReturnExpression, arg0: node+16} +// CHECK:STDOUT: node_blocks: +// CHECK:STDOUT: block0: {} +// CHECK:STDOUT: block1: +// CHECK:STDOUT: 0: node+0 +// CHECK:STDOUT: block2: +// CHECK:STDOUT: 0: nodeIntegerType +// CHECK:STDOUT: 1: nodeFloatingPointType +// CHECK:STDOUT: block3: +// CHECK:STDOUT: 0: node+0 +// CHECK:STDOUT: 1: node+1 +// CHECK:STDOUT: 2: node+2 +// CHECK:STDOUT: 3: node+3 +// CHECK:STDOUT: 4: node+4 +// CHECK:STDOUT: block4: +// CHECK:STDOUT: 0: node+7 +// CHECK:STDOUT: 1: node+8 +// CHECK:STDOUT: 2: node+9 +// CHECK:STDOUT: 3: node+10 +// CHECK:STDOUT: 4: node+11 +// CHECK:STDOUT: 5: node+12 +// CHECK:STDOUT: 6: node+13 +// CHECK:STDOUT: 7: node+14 +// CHECK:STDOUT: 8: node+15 +// CHECK:STDOUT: 9: node+16 +// CHECK:STDOUT: 10: node+17 +// CHECK:STDOUT: block5: +// CHECK:STDOUT: 0: node+9 +// CHECK:STDOUT: 1: node+10 +// CHECK:STDOUT: block6: +// CHECK:STDOUT: 0: node+13 +// CHECK:STDOUT: 1: node+15 +// CHECK:STDOUT: block7: +// CHECK:STDOUT: 0: node+5 +// CHECK:STDOUT: 1: node+6 +// CHECK:STDOUT: ... diff --git a/toolchain/driver/testdata/dump_shared_values.carbon b/toolchain/driver/testdata/dump_shared_values.carbon index 03c5d6b3eef9..cfe5382c96e9 100644 --- a/toolchain/driver/testdata/dump_shared_values.carbon +++ b/toolchain/driver/testdata/dump_shared_values.carbon @@ -15,26 +15,28 @@ var real3: f64 = 0.8e9; var str1: String = "abc"; var str2: String = "ab'\"c"; +// CHECK:STDOUT: --- // CHECK:STDOUT: shared_values: -// CHECK:STDOUT: - integers: -// CHECK:STDOUT: - 32 -// CHECK:STDOUT: - 1 -// CHECK:STDOUT: - 32 -// CHECK:STDOUT: - 8 -// CHECK:STDOUT: - 64 -// CHECK:STDOUT: - 64 -// CHECK:STDOUT: - 64 -// CHECK:STDOUT: reals: -// CHECK:STDOUT: - 10*10^-1 -// CHECK:STDOUT: - 8*10^7 -// CHECK:STDOUT: - 8*10^8 -// CHECK:STDOUT: strings: -// CHECK:STDOUT: - "int1" -// CHECK:STDOUT: - "int2" -// CHECK:STDOUT: - "real1" -// CHECK:STDOUT: - "real2" -// CHECK:STDOUT: - "real3" -// CHECK:STDOUT: - "str1" -// CHECK:STDOUT: - "abc" -// CHECK:STDOUT: - "str2" -// CHECK:STDOUT: - "ab'\"c" +// CHECK:STDOUT: integers: +// CHECK:STDOUT: int0: 32 +// CHECK:STDOUT: int1: 1 +// CHECK:STDOUT: int2: 32 +// CHECK:STDOUT: int3: 8 +// CHECK:STDOUT: int4: 64 +// CHECK:STDOUT: int5: 64 +// CHECK:STDOUT: int6: 64 +// CHECK:STDOUT: reals: +// CHECK:STDOUT: real0: 10*10^-1 +// CHECK:STDOUT: real1: 8*10^7 +// CHECK:STDOUT: real2: 8*10^8 +// CHECK:STDOUT: strings: +// CHECK:STDOUT: str0: int1 +// CHECK:STDOUT: str1: int2 +// CHECK:STDOUT: str2: real1 +// CHECK:STDOUT: str3: real2 +// CHECK:STDOUT: str4: real3 +// CHECK:STDOUT: str5: str1 +// CHECK:STDOUT: str6: abc +// CHECK:STDOUT: str7: str2 +// CHECK:STDOUT: str8: 'ab''"c' +// CHECK:STDOUT: ... diff --git a/toolchain/lex/tokenized_buffer_test.cpp b/toolchain/lex/tokenized_buffer_test.cpp index cbec6c8c7290..3e2ce3da5945 100644 --- a/toolchain/lex/tokenized_buffer_test.cpp +++ b/toolchain/lex/tokenized_buffer_test.cpp @@ -1057,7 +1057,7 @@ TEST_F(LexerTest, DiagnosticUnrecognizedChar) { Lex("\b", consumer); } -TEST_F(LexerTest, PrintingAsYaml) { +TEST_F(LexerTest, PrintingOutputYaml) { // Test that we can parse this into YAML and verify line and indent data. auto buffer = Lex("\n ;\n\n\n; ;\n\n\n\n\n\n\n\n\n\n\n"); ASSERT_FALSE(buffer.has_errors()); diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index 074bce5e8d36..14512668f0dc 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -69,6 +69,7 @@ cc_library( ":value_stores", "//common:check", "//toolchain/base:value_store", + "//toolchain/base:yaml", "@llvm-project//llvm:Support", ], ) @@ -102,6 +103,7 @@ cc_library( deps = [ ":node", "//toolchain/base:value_store", + "//toolchain/base:yaml", "@llvm-project//llvm:Support", ], ) diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index 594bde0d4ce4..5e22e067bccd 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -8,6 +8,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "toolchain/base/value_store.h" +#include "toolchain/base/yaml.h" #include "toolchain/sem_ir/builtin_kind.h" #include "toolchain/sem_ir/node.h" #include "toolchain/sem_ir/node_kind.h" @@ -129,27 +130,30 @@ auto File::Verify() const -> ErrorOr { return Success(); } -auto File::Print(llvm::raw_ostream& out, bool include_builtins) const -> void { - out << "- filename: " << filename_ << "\n" - << " sem_ir:\n" - << " - cross_reference_irs_size: " << cross_reference_irs_.size() - << "\n"; - - static constexpr int FirstLineIndent = 4; - static constexpr int LaterIndent = 6; - functions_.Print(out, "functions", FirstLineIndent, LaterIndent); - classes_.Print(out, "classes", FirstLineIndent, LaterIndent); - types_.Print(out, "types", FirstLineIndent, LaterIndent); - type_blocks_.Print(out, "type_blocks", FirstLineIndent, LaterIndent); - - auto nodes = nodes_.array_ref(); - if (!include_builtins) { - nodes = nodes.drop_front(BuiltinKind::ValidCount); - } - PrintValueRange(out, llvm::iterator_range(nodes), "nodes", FirstLineIndent, - LaterIndent, /*trailing_newline=*/true); - - node_blocks_.Print(out, "node_blocks", FirstLineIndent, LaterIndent); +auto File::OutputYaml(bool include_builtins) const -> Yaml::OutputMapping { + return Yaml::OutputMapping([this, + include_builtins](Yaml::OutputMapping::Map map) { + map.Add("filename", filename_); + map.Add("sem_ir", Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + map.Add("cross_reference_irs_size", + Yaml::OutputScalar(cross_reference_irs_.size())); + map.Add("functions", functions_.OutputYaml()); + map.Add("classes", classes_.OutputYaml()); + map.Add("types", types_.OutputYaml()); + map.Add("type_blocks", type_blocks_.OutputYaml()); + map.Add("nodes", + Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + int start = + include_builtins ? 0 : BuiltinKind::ValidCount; + for (int i : llvm::seq(start, nodes_.size())) { + auto id = NodeId(i); + map.Add(PrintToString(id), + Yaml::OutputScalar(nodes_.Get(id))); + } + })); + map.Add("node_blocks", node_blocks_.OutputYaml()); + })); + }); } // Map a node kind representing a type into an integer describing the diff --git a/toolchain/sem_ir/file.h b/toolchain/sem_ir/file.h index e7c1f017a382..79553fefc6a2 100644 --- a/toolchain/sem_ir/file.h +++ b/toolchain/sem_ir/file.h @@ -10,6 +10,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/FormatVariadic.h" #include "toolchain/base/value_store.h" +#include "toolchain/base/yaml.h" #include "toolchain/sem_ir/node.h" #include "toolchain/sem_ir/value_stores.h" @@ -174,11 +175,11 @@ class File : public Printable { // TODO: In the future, the things to print may change, for example by adding // preludes. We may then want the ability to omit other things similar to // builtins. - auto Print(llvm::raw_ostream& out, bool include_builtins) const -> void; - - auto Print(llvm::raw_ostream& out) const -> void { - Print(out, /*include_builtins=*/false); + auto Print(llvm::raw_ostream& out, bool include_builtins = false) const + -> void { + Yaml::Print(out, OutputYaml(include_builtins)); } + auto OutputYaml(bool include_builtins) const -> Yaml::OutputMapping; // Returns array bound value from the bound node. auto GetArrayBoundValue(NodeId bound_id) const -> uint64_t { diff --git a/toolchain/sem_ir/value_stores.h b/toolchain/sem_ir/value_stores.h index e1c8431253e7..d91d277ea884 100644 --- a/toolchain/sem_ir/value_stores.h +++ b/toolchain/sem_ir/value_stores.h @@ -7,6 +7,7 @@ #include "llvm/ADT/DenseMap.h" #include "toolchain/base/value_store.h" +#include "toolchain/base/yaml.h" #include "toolchain/sem_ir/node.h" namespace Carbon::SemIR { @@ -72,7 +73,7 @@ class NameScopeStore { // BlockValueStore is used as-is, but there are also children that expose the // protected members for type-specific functionality. template -class BlockValueStore { +class BlockValueStore : public Yaml::Printable> { public: explicit BlockValueStore(llvm::BumpPtrAllocator& allocator) : allocator_(&allocator) {} @@ -88,18 +89,19 @@ class BlockValueStore { // Returns the requested block. auto Get(IdT id) -> llvm::MutableArrayRef { return values_.Get(id); } - auto Print(llvm::raw_ostream& out) const -> void { - Print(out, std::nullopt, 0, 0); - } - auto Print(llvm::raw_ostream& out, std::optional label, - int first_line_indent, int later_indent) const -> void { - values_.Print(out, label, first_line_indent, later_indent, - [&](llvm::raw_ostream& out, - const llvm::MutableArrayRef& value) { - PrintValueRange(out, llvm::iterator_range(value), - std::nullopt, 0, later_indent + 2, - /*trailing_newline=*/false); - }); + auto OutputYaml() const -> Yaml::OutputMapping { + return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + for (auto block_index : llvm::seq(values_.size())) { + auto block_id = IdT(block_index); + map.Add(PrintToString(block_id), + Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + auto block = Get(block_id); + for (auto i : llvm::seq(block.size())) { + map.Add(llvm::itostr(i), Yaml::OutputScalar(block[i])); + } + })); + } + }); } auto size() const -> int { return values_.size(); } diff --git a/toolchain/sem_ir/yaml_test.cpp b/toolchain/sem_ir/yaml_test.cpp index 0f0e58224673..d225ac282882 100644 --- a/toolchain/sem_ir/yaml_test.cpp +++ b/toolchain/sem_ir/yaml_test.cpp @@ -44,40 +44,45 @@ TEST(SemIRTest, YAML) { auto node_id = Yaml::Scalar(MatchesRegex(R"(node\+\d+)")); auto node_builtin = Yaml::Scalar(MatchesRegex(R"(node\w+)")); auto type_id = Yaml::Scalar(MatchesRegex(R"(type\d+)")); - auto type_builtin = Yaml::Mapping(ElementsAre( - Pair("node", node_builtin), Pair("value_rep", Yaml::Mapping(_)))); + auto type_builtin = Pair( + type_id, Yaml::Mapping(ElementsAre(Pair("node", node_builtin), + Pair("value_rep", Yaml::Mapping(_))))); - auto file = Yaml::Sequence(ElementsAre(Yaml::Mapping(ElementsAre( + auto file = Yaml::Mapping(ElementsAre( Pair("cross_reference_irs_size", "1"), - Pair("functions", Yaml::Sequence(SizeIs(1))), - Pair("classes", Yaml::Sequence(SizeIs(0))), - Pair("types", Yaml::Sequence(Each(type_builtin))), - Pair("type_blocks", Yaml::Sequence(IsEmpty())), + Pair("functions", Yaml::Mapping(SizeIs(1))), + Pair("classes", Yaml::Mapping(SizeIs(0))), + Pair("types", Yaml::Mapping(Each(type_builtin))), + Pair("type_blocks", Yaml::Mapping(IsEmpty())), Pair("nodes", - Yaml::Sequence(AllOf( + Yaml::Mapping(AllOf( + Each(Key(node_id)), // kind is required, other parts are optional. - Each(Yaml::Mapping(Contains(Pair("kind", _)))), + Each(Pair(_, Yaml::Mapping(Contains(Pair("kind", _))))), // A 0-arg node. - Contains(Yaml::Mapping(ElementsAre(Pair("kind", "Return")))), + Contains( + Pair(_, Yaml::Mapping(ElementsAre(Pair("kind", "Return"))))), // A 1-arg node. - Contains(Yaml::Mapping(ElementsAre( - Pair("kind", "IntegerLiteral"), Pair("arg0", integer_id), - Pair("type", type_id)))), + Contains(Pair( + _, Yaml::Mapping(ElementsAre(Pair("kind", "IntegerLiteral"), + Pair("arg0", integer_id), + Pair("type", type_id))))), // A 2-arg node. - Contains(Yaml::Mapping(ElementsAre(Pair("kind", "Assign"), - Pair("arg0", node_id), - Pair("arg1", node_id))))))), + Contains(Pair( + _, Yaml::Mapping(ElementsAre(Pair("kind", "Assign"), + Pair("arg0", node_id), + Pair("arg1", node_id)))))))), // This production has only two node blocks. Pair("node_blocks", - Yaml::Sequence(ElementsAre(Yaml::Sequence(IsEmpty()), - Yaml::Sequence(Each(node_id)), - Yaml::Sequence(Each(node_id))))))))); + Yaml::Mapping(ElementsAre( + Pair("block0", Yaml::Mapping(IsEmpty())), + Pair("block1", Yaml::Mapping(Each(Pair(_, node_id)))), + Pair("block2", Yaml::Mapping(Each(Pair(_, node_id))))))))); auto root = Yaml::Sequence(ElementsAre(Yaml::Mapping( ElementsAre(Pair("filename", "test.carbon"), Pair("sem_ir", file))))); - EXPECT_THAT(Yaml::Value::FromText(print_stream.TakeStr()), - IsYaml(ElementsAre(root))); + EXPECT_THAT(Yaml::Value::FromText(print_stream.TakeStr()), IsYaml(root)); } } // namespace