[llvm] 928d172 - [llvm] Add JSONScopedPrinter class

Jayson Yan via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 10 10:58:08 PST 2021


Author: Jayson Yan
Date: 2021-12-10T18:57:33Z
New Revision: 928d17254ba214749dbd58f6d5604c11057a60bc

URL: https://github.com/llvm/llvm-project/commit/928d17254ba214749dbd58f6d5604c11057a60bc
DIFF: https://github.com/llvm/llvm-project/commit/928d17254ba214749dbd58f6d5604c11057a60bc.diff

LOG: [llvm] Add JSONScopedPrinter class

This change adds a JSONScopedPrinter as a subclass to ScopedPrinter.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D114224

Added: 
    

Modified: 
    llvm/include/llvm/Support/ScopedPrinter.h
    llvm/lib/Support/ScopedPrinter.cpp
    llvm/tools/llvm-readobj/ARMEHABIPrinter.h
    llvm/unittests/Support/ScopedPrinterTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h
index 7c4eb2051a70..865337e3cc7f 100644
--- a/llvm/include/llvm/Support/ScopedPrinter.h
+++ b/llvm/include/llvm/Support/ScopedPrinter.h
@@ -16,6 +16,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/Endian.h"
+#include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 
@@ -100,7 +101,20 @@ std::string enumToString(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues) {
 
 class ScopedPrinter {
 public:
-  ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {}
+  enum class ScopedPrinterKind {
+    Base,
+    JSON,
+  };
+
+  ScopedPrinter(raw_ostream &OS,
+                ScopedPrinterKind Kind = ScopedPrinterKind::Base)
+      : OS(OS), IndentLevel(0), Kind(Kind) {}
+
+  ScopedPrinterKind getKind() const { return Kind; }
+
+  static bool classof(const ScopedPrinter *SP) {
+    return SP->getKind() == ScopedPrinterKind::Base;
+  }
 
   virtual ~ScopedPrinter() {}
 
@@ -487,6 +501,7 @@ class ScopedPrinter {
   raw_ostream &OS;
   int IndentLevel;
   StringRef Prefix;
+  ScopedPrinterKind Kind;
 };
 
 template <>
@@ -496,30 +511,329 @@ ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
   startLine() << Label << ": " << hex(Value) << "\n";
 }
 
+struct DelimitedScope;
+
+class JSONScopedPrinter : public ScopedPrinter {
+private:
+  enum class Scope {
+    Array,
+    Object,
+  };
+
+  enum class ScopeKind {
+    NoAttribute,
+    Attribute,
+    NestedAttribute,
+  };
+
+  struct ScopeContext {
+    Scope Context;
+    ScopeKind Kind;
+    ScopeContext(Scope Context, ScopeKind Kind = ScopeKind::NoAttribute)
+        : Context(Context), Kind(Kind) {}
+  };
+
+  SmallVector<ScopeContext, 8> ScopeHistory;
+  json::OStream JOS;
+  std::unique_ptr<DelimitedScope> OuterScope;
+
+public:
+  JSONScopedPrinter(raw_ostream &OS, bool PrettyPrint = false,
+                    std::unique_ptr<DelimitedScope> &&OuterScope =
+                        std::unique_ptr<DelimitedScope>{});
+
+  static bool classof(const ScopedPrinter *SP) {
+    return SP->getKind() == ScopedPrinter::ScopedPrinterKind::JSON;
+  }
+
+  void printNumber(StringRef Label, uint64_t Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, uint32_t Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, uint16_t Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, uint8_t Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, int64_t Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, int32_t Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, int16_t Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, int8_t Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, const APSInt &Value) override {
+    JOS.attributeBegin(Label);
+    printAPSInt(Value);
+    JOS.attributeEnd();
+  }
+
+  void printBoolean(StringRef Label, bool Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printList(StringRef Label, const ArrayRef<bool> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<std::string> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<uint64_t> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<uint32_t> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<uint16_t> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<uint8_t> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<int64_t> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<int32_t> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<int16_t> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<int8_t> List) override {
+    printListImpl(Label, List);
+  }
+
+  void printList(StringRef Label, const ArrayRef<APSInt> List) override {
+    JOS.attributeArray(Label, [&]() {
+      for (const APSInt &Item : List) {
+        printAPSInt(Item);
+      }
+    });
+  }
+
+  void printString(StringRef Value) override { JOS.value(Value); }
+
+  void printString(StringRef Label, StringRef Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void objectBegin() override {
+    scopedBegin({Scope::Object, ScopeKind::NoAttribute});
+  }
+
+  void objectBegin(StringRef Label) override {
+    scopedBegin(Label, Scope::Object);
+  }
+
+  void objectEnd() override { scopedEnd(); }
+
+  void arrayBegin() override {
+    scopedBegin({Scope::Array, ScopeKind::NoAttribute});
+  }
+
+  void arrayBegin(StringRef Label) override {
+    scopedBegin(Label, Scope::Array);
+  }
+
+  void arrayEnd() override { scopedEnd(); }
+
+private:
+  // Output HexNumbers as decimals so that they're easier to parse.
+  uint64_t hexNumberToInt(HexNumber Hex) { return Hex.Value; }
+
+  void printAPSInt(const APSInt &Value) {
+    JOS.rawValueBegin() << Value;
+    JOS.rawValueEnd();
+  }
+
+  void printFlagsImpl(StringRef Label, HexNumber Value,
+                      ArrayRef<FlagEntry> Flags) override {
+    JOS.attributeObject(Label, [&]() {
+      JOS.attribute("RawFlags", hexNumberToInt(Value));
+      JOS.attributeArray("Flags", [&]() {
+        for (const FlagEntry &Flag : Flags) {
+          JOS.objectBegin();
+          JOS.attribute("Name", Flag.Name);
+          JOS.attribute("Value", Flag.Value);
+          JOS.objectEnd();
+        }
+      });
+    });
+  }
+
+  void printFlagsImpl(StringRef Label, HexNumber Value,
+                      ArrayRef<HexNumber> Flags) override {
+    JOS.attributeObject(Label, [&]() {
+      JOS.attribute("RawFlags", hexNumberToInt(Value));
+      JOS.attributeArray("Flags", [&]() {
+        for (const HexNumber &Flag : Flags) {
+          JOS.value(Flag.Value);
+        }
+      });
+    });
+  }
+
+  template <typename T> void printListImpl(StringRef Label, const T &List) {
+    JOS.attributeArray(Label, [&]() {
+      for (const auto &Item : List)
+        JOS.value(Item);
+    });
+  }
+
+  void printHexListImpl(StringRef Label,
+                        const ArrayRef<HexNumber> List) override {
+    JOS.attributeArray(Label, [&]() {
+      for (const HexNumber &Item : List) {
+        JOS.value(hexNumberToInt(Item));
+      }
+    });
+  }
+
+  void printHexImpl(StringRef Label, HexNumber Value) override {
+    JOS.attribute(Label, hexNumberToInt(Value));
+  }
+
+  void printHexImpl(StringRef Label, StringRef Str, HexNumber Value) override {
+    JOS.attributeObject(Label, [&]() {
+      JOS.attribute("Value", Str);
+      JOS.attribute("RawValue", hexNumberToInt(Value));
+    });
+  }
+
+  void printSymbolOffsetImpl(StringRef Label, StringRef Symbol,
+                             HexNumber Value) override {
+    JOS.attributeObject(Label, [&]() {
+      JOS.attribute("SymName", Symbol);
+      JOS.attribute("Offset", hexNumberToInt(Value));
+    });
+  }
+
+  void printNumberImpl(StringRef Label, StringRef Str,
+                       StringRef Value) override {
+    JOS.attributeObject(Label, [&]() {
+      JOS.attribute("Value", Str);
+      JOS.attributeBegin("RawValue");
+      JOS.rawValueBegin() << Value;
+      JOS.rawValueEnd();
+      JOS.attributeEnd();
+    });
+  }
+
+  void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
+                       bool Block, uint32_t StartOffset = 0) override {
+    JOS.attributeObject(Label, [&]() {
+      if (!Str.empty())
+        JOS.attribute("Value", Str);
+      JOS.attribute("Offset", StartOffset);
+      JOS.attributeArray("Bytes", [&]() {
+        for (uint8_t Val : Value)
+          JOS.value(Val);
+      });
+    });
+  }
+
+  void scopedBegin(ScopeContext ScopeCtx) {
+    if (ScopeCtx.Context == Scope::Object)
+      JOS.objectBegin();
+    else if (ScopeCtx.Context == Scope::Array)
+      JOS.arrayBegin();
+    ScopeHistory.push_back(ScopeCtx);
+  }
+
+  void scopedBegin(StringRef Label, Scope Ctx) {
+    ScopeKind Kind = ScopeKind::Attribute;
+    if (ScopeHistory.empty() || ScopeHistory.back().Context != Scope::Object) {
+      JOS.objectBegin();
+      Kind = ScopeKind::NestedAttribute;
+    }
+    JOS.attributeBegin(Label);
+    scopedBegin({Ctx, Kind});
+  }
+
+  void scopedEnd() {
+    ScopeContext ScopeCtx = ScopeHistory.back();
+    if (ScopeCtx.Context == Scope::Object)
+      JOS.objectEnd();
+    else if (ScopeCtx.Context == Scope::Array)
+      JOS.arrayEnd();
+    if (ScopeCtx.Kind == ScopeKind::Attribute ||
+        ScopeCtx.Kind == ScopeKind::NestedAttribute)
+      JOS.attributeEnd();
+    if (ScopeCtx.Kind == ScopeKind::NestedAttribute)
+      JOS.objectEnd();
+    ScopeHistory.pop_back();
+  }
+};
+
 struct DelimitedScope {
-  DelimitedScope(ScopedPrinter &W) : W(W) {}
+  DelimitedScope(ScopedPrinter &W) : W(&W) {}
+  DelimitedScope() : W(nullptr) {}
   virtual ~DelimitedScope(){};
-  ScopedPrinter &W;
+  virtual void setPrinter(ScopedPrinter &W) = 0;
+  ScopedPrinter *W;
 };
 
 struct DictScope : DelimitedScope {
+  explicit DictScope() : DelimitedScope() {}
   explicit DictScope(ScopedPrinter &W) : DelimitedScope(W) { W.objectBegin(); }
 
   DictScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) {
     W.objectBegin(N);
   }
 
-  ~DictScope() { W.objectEnd(); }
+  void setPrinter(ScopedPrinter &W) override {
+    this->W = &W;
+    W.objectBegin();
+  }
+
+  ~DictScope() {
+    if (W)
+      W->objectEnd();
+  }
 };
 
 struct ListScope : DelimitedScope {
+  explicit ListScope() : DelimitedScope() {}
   explicit ListScope(ScopedPrinter &W) : DelimitedScope(W) { W.arrayBegin(); }
 
   ListScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) {
     W.arrayBegin(N);
   }
 
-  ~ListScope() { W.arrayEnd(); }
+  void setPrinter(ScopedPrinter &W) override {
+    this->W = &W;
+    W.arrayBegin();
+  }
+
+  ~ListScope() {
+    if (W)
+      W->arrayEnd();
+  }
 };
 
 } // namespace llvm

diff  --git a/llvm/lib/Support/ScopedPrinter.cpp b/llvm/lib/Support/ScopedPrinter.cpp
index 779c6c45257d..ea90a24eaced 100644
--- a/llvm/lib/Support/ScopedPrinter.cpp
+++ b/llvm/lib/Support/ScopedPrinter.cpp
@@ -43,4 +43,14 @@ void ScopedPrinter::printBinaryImpl(StringRef Label, StringRef Str,
   }
 }
 
+JSONScopedPrinter::JSONScopedPrinter(
+    raw_ostream &OS, bool PrettyPrint,
+    std::unique_ptr<DelimitedScope> &&OuterScope)
+    : ScopedPrinter(OS, ScopedPrinter::ScopedPrinterKind::JSON),
+      JOS(OS, /*Indent=*/PrettyPrint ? 2 : 0),
+      OuterScope(std::move(OuterScope)) {
+  if (this->OuterScope)
+    this->OuterScope->setPrinter(*this);
+}
+
 } // namespace llvm

diff  --git a/llvm/tools/llvm-readobj/ARMEHABIPrinter.h b/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
index 94f1672c6342..d641b172eb91 100644
--- a/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
+++ b/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
@@ -512,7 +512,7 @@ template <typename ET>
 void PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry,
                                       size_t Length, off_t Offset) const {
   ListScope OCC(SW, "Opcodes");
-  OpcodeDecoder(OCC.W).Decode(Entry, Offset, Length);
+  OpcodeDecoder(SW).Decode(Entry, Offset, Length);
 }
 
 template <typename ET>

diff  --git a/llvm/unittests/Support/ScopedPrinterTest.cpp b/llvm/unittests/Support/ScopedPrinterTest.cpp
index 772ef6d9e591..d959720b2329 100644
--- a/llvm/unittests/Support/ScopedPrinterTest.cpp
+++ b/llvm/unittests/Support/ScopedPrinterTest.cpp
@@ -13,13 +13,63 @@
 
 using namespace llvm;
 
+TEST(JSONScopedPrinterTest, PrettyPrintCtor) {
+  auto PrintFunc = [](ScopedPrinter &W) {
+    DictScope D(W);
+    W.printString("Key", "Value");
+  };
+  std::string StreamBuffer;
+  raw_string_ostream OS(StreamBuffer);
+  JSONScopedPrinter PrettyPrintWriter(OS, /*PrettyPrint=*/true);
+  JSONScopedPrinter NoPrettyPrintWriter(OS, /*PrettyPrint=*/false);
+
+  const char *PrettyPrintOut = R"({
+  "Key": "Value"
+})";
+  const char *NoPrettyPrintOut = R"({"Key":"Value"})";
+  PrintFunc(PrettyPrintWriter);
+  EXPECT_EQ(PrettyPrintOut, OS.str());
+  StreamBuffer.clear();
+  PrintFunc(NoPrettyPrintWriter);
+  EXPECT_EQ(NoPrettyPrintOut, OS.str());
+}
+
+TEST(JSONScopedPrinterTest, DelimitedScopeCtor) {
+  std::string StreamBuffer;
+  raw_string_ostream OS(StreamBuffer);
+  {
+    JSONScopedPrinter DictScopeWriter(OS, /*PrettyPrint=*/false,
+                                      std::make_unique<DictScope>());
+    DictScopeWriter.printString("Label", "DictScope");
+  }
+  EXPECT_EQ(R"({"Label":"DictScope"})", OS.str());
+  StreamBuffer.clear();
+  {
+    JSONScopedPrinter ListScopeWriter(OS, /*PrettyPrint=*/false,
+                                      std::make_unique<ListScope>());
+    ListScopeWriter.printString("ListScope");
+  }
+  EXPECT_EQ(R"(["ListScope"])", OS.str());
+  StreamBuffer.clear();
+  {
+    JSONScopedPrinter NoScopeWriter(OS, /*PrettyPrint=*/false);
+    NoScopeWriter.printString("NoScope");
+  }
+  EXPECT_EQ(R"("NoScope")", OS.str());
+}
+
 class ScopedPrinterTest : public ::testing::Test {
 protected:
   std::string StreamBuffer;
   raw_string_ostream OS;
   ScopedPrinter Writer;
+  JSONScopedPrinter JSONWriter;
 
-  ScopedPrinterTest() : OS(StreamBuffer), Writer(OS) {}
+  bool HasPrintedToJSON;
+
+  ScopedPrinterTest()
+      : OS(StreamBuffer), Writer(OS), JSONWriter(OS, /*PrettyPrint=*/true),
+        HasPrintedToJSON(false) {}
 
   using PrintFunc = function_ref<void(ScopedPrinter &)>;
 
@@ -27,9 +77,45 @@ class ScopedPrinterTest : public ::testing::Test {
     Func(Writer);
     Writer.flush();
     EXPECT_EQ(Expected.str(), OS.str());
+    StreamBuffer.clear();
+  }
+
+  void verifyJSONScopedPrinter(StringRef Expected, PrintFunc Func) {
+    {
+      DictScope D(JSONWriter);
+      Func(JSONWriter);
+    }
+    JSONWriter.flush();
+    EXPECT_EQ(Expected.str(), OS.str());
+    StreamBuffer.clear();
+    HasPrintedToJSON = true;
+  }
+
+  void verifyAll(StringRef ExpectedOut, StringRef JSONExpectedOut,
+                 PrintFunc Func) {
+    verifyScopedPrinter(ExpectedOut, Func);
+    verifyJSONScopedPrinter(JSONExpectedOut, Func);
+  }
+
+  void TearDown() {
+    // JSONScopedPrinter fails an assert if nothing's been printed.
+    if (!HasPrintedToJSON)
+      JSONWriter.printString("");
   }
 };
 
+TEST_F(ScopedPrinterTest, GetKind) {
+  EXPECT_EQ(ScopedPrinter::ScopedPrinterKind::Base, Writer.getKind());
+  EXPECT_EQ(ScopedPrinter::ScopedPrinterKind::JSON, JSONWriter.getKind());
+}
+
+TEST_F(ScopedPrinterTest, ClassOf) {
+  EXPECT_TRUE(ScopedPrinter::classof(&Writer));
+  EXPECT_TRUE(JSONScopedPrinter::classof(&JSONWriter));
+  EXPECT_FALSE(ScopedPrinter::classof(&JSONWriter));
+  EXPECT_FALSE(JSONScopedPrinter::classof(&Writer));
+}
+
 TEST_F(ScopedPrinterTest, Indent) {
   auto PrintFunc = [](ScopedPrinter &W) {
     W.printString("|");
@@ -147,7 +233,15 @@ TEST_F(ScopedPrinterTest, PrintEnum) {
   const char *ExpectedOut = R"(Exists: Name2 (0x2)
 DoesNotExist: 0x5
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "Exists": {
+    "Value": "Name2",
+    "RawValue": 2
+  },
+  "DoesNotExist": 5
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintFlag) {
@@ -251,7 +345,169 @@ FirstSecondThirdByteMask [ (0x333)
   ThirdByte3 (0x300)
 ]
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "ZeroFlag": {
+    "RawFlags": 0,
+    "Flags": []
+  },
+  "NoFlag": {
+    "RawFlags": 8,
+    "Flags": []
+  },
+  "Flag1": {
+    "RawFlags": 1,
+    "Flags": [
+      {
+        "Name": "Name1",
+        "Value": 1
+      }
+    ]
+  },
+  "Flag1&3": {
+    "RawFlags": 5,
+    "Flags": [
+      {
+        "Name": "Name1",
+        "Value": 1
+      },
+      {
+        "Name": "Name3",
+        "Value": 4
+      }
+    ]
+  },
+  "ZeroFlagRaw": {
+    "RawFlags": 0,
+    "Flags": []
+  },
+  "NoFlagRaw": {
+    "RawFlags": 8,
+    "Flags": [
+      8
+    ]
+  },
+  "Flag1Raw": {
+    "RawFlags": 1,
+    "Flags": [
+      1
+    ]
+  },
+  "Flag1&3Raw": {
+    "RawFlags": 5,
+    "Flags": [
+      1,
+      4
+    ]
+  },
+  "FlagSorted": {
+    "RawFlags": 7,
+    "Flags": [
+      {
+        "Name": "A",
+        "Value": 4
+      },
+      {
+        "Name": "B",
+        "Value": 2
+      },
+      {
+        "Name": "C",
+        "Value": 1
+      }
+    ]
+  },
+  "NoBitMask": {
+    "RawFlags": 4095,
+    "Flags": [
+      {
+        "Name": "FirstByte1",
+        "Value": 1
+      },
+      {
+        "Name": "FirstByte2",
+        "Value": 2
+      },
+      {
+        "Name": "FirstByte3",
+        "Value": 3
+      },
+      {
+        "Name": "SecondByte1",
+        "Value": 16
+      },
+      {
+        "Name": "SecondByte2",
+        "Value": 32
+      },
+      {
+        "Name": "SecondByte3",
+        "Value": 48
+      },
+      {
+        "Name": "ThirdByte1",
+        "Value": 256
+      },
+      {
+        "Name": "ThirdByte2",
+        "Value": 512
+      },
+      {
+        "Name": "ThirdByte3",
+        "Value": 768
+      }
+    ]
+  },
+  "FirstByteMask": {
+    "RawFlags": 3,
+    "Flags": [
+      {
+        "Name": "FirstByte3",
+        "Value": 3
+      }
+    ]
+  },
+  "SecondByteMask": {
+    "RawFlags": 48,
+    "Flags": [
+      {
+        "Name": "SecondByte3",
+        "Value": 48
+      }
+    ]
+  },
+  "ValueOutsideMask": {
+    "RawFlags": 1,
+    "Flags": [
+      {
+        "Name": "FirstByte1",
+        "Value": 1
+      }
+    ]
+  },
+  "FirstSecondByteMask": {
+    "RawFlags": 255,
+    "Flags": []
+  },
+  "FirstSecondThirdByteMask": {
+    "RawFlags": 819,
+    "Flags": [
+      {
+        "Name": "FirstByte3",
+        "Value": 3
+      },
+      {
+        "Name": "SecondByte3",
+        "Value": 48
+      },
+      {
+        "Name": "ThirdByte3",
+        "Value": 768
+      }
+    ]
+  }
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintNumber) {
@@ -321,7 +577,31 @@ int8_t-min: -128
 apsint: 9999999999999999999999
 label: value (0)
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "uint64_t-max": 18446744073709551615,
+  "uint64_t-min": 0,
+  "uint32_t-max": 4294967295,
+  "uint32_t-min": 0,
+  "uint16_t-max": 65535,
+  "uint16_t-min": 0,
+  "uint8_t-max": 255,
+  "uint8_t-min": 0,
+  "int64_t-max": 9223372036854775807,
+  "int64_t-min": -9223372036854775808,
+  "int32_t-max": 2147483647,
+  "int32_t-min": -2147483648,
+  "int16_t-max": 32767,
+  "int16_t-min": -32768,
+  "int8_t-max": 127,
+  "int8_t-min": -128,
+  "apsint": 9999999999999999999999,
+  "label": {
+    "Value": "value",
+    "RawValue": 0
+  }
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintBoolean) {
@@ -333,7 +613,12 @@ TEST_F(ScopedPrinterTest, PrintBoolean) {
   const char *ExpectedOut = R"(True: Yes
 False: No
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "True": true,
+  "False": false
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintVersion) {
@@ -402,7 +687,56 @@ int16List: [32767, -32768]
 int8List: [127, -128]
 APSIntList: [9999999999999999999999, -9999999999999999999999]
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "EmptyList": [],
+  "StringList": [
+    "foo",
+    "bar",
+    "baz"
+  ],
+  "BoolList": [
+    true,
+    false
+  ],
+  "uint64List": [
+    18446744073709551615,
+    0
+  ],
+  "uint32List": [
+    4294967295,
+    0
+  ],
+  "uint16List": [
+    65535,
+    0
+  ],
+  "uint8List": [
+    255,
+    0
+  ],
+  "int64List": [
+    9223372036854775807,
+    -9223372036854775808
+  ],
+  "int32List": [
+    2147483647,
+    -2147483648
+  ],
+  "int16List": [
+    32767,
+    -32768
+  ],
+  "int8List": [
+    127,
+    -128
+  ],
+  "APSIntList": [
+    9999999999999999999999,
+    -9999999999999999999999
+  ]
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintListPrinter) {
@@ -426,7 +760,15 @@ TEST_F(ScopedPrinterTest, PrintHex) {
   const char *ExpectedOut = R"(HexNumber: 0x10
 HexLabel: Name (0x10)
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "HexNumber": 16,
+  "HexLabel": {
+    "Value": "Name",
+    "RawValue": 16
+  }
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintHexList) {
@@ -436,7 +778,15 @@ TEST_F(ScopedPrinterTest, PrintHexList) {
   };
   const char *ExpectedOut = R"(HexList: [0x1, 0x10, 0x100]
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "HexList": [
+    1,
+    16,
+    256
+  ]
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintSymbolOffset) {
@@ -447,7 +797,18 @@ TEST_F(ScopedPrinterTest, PrintSymbolOffset) {
   const char *ExpectedOut = R"(SymbolOffset: SymbolName+0x10
 NoSymbolOffset: SymbolName+0x0
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "SymbolOffset": {
+    "SymName": "SymbolName",
+    "Offset": 16
+  },
+  "NoSymbolOffset": {
+    "SymName": "SymbolName",
+    "Offset": 0
+  }
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintString) {
@@ -469,7 +830,16 @@ StringList [
   Value
 ]
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "StringRef": "Value",
+  "String": "Value",
+  "CharArray": "Value",
+  "StringList": [
+    "Value"
+  ]
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintBinary) {
@@ -516,7 +886,157 @@ Binary11 (
   0000: FFFF                                 |..|
 )
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "Binary1": {
+    "Value": "FooBar",
+    "Offset": 0,
+    "Bytes": [
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary2": {
+    "Value": "FooBar",
+    "Offset": 0,
+    "Bytes": [
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary3": {
+    "Offset": 0,
+    "Bytes": [
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary4": {
+    "Offset": 0,
+    "Bytes": [
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary5": {
+    "Offset": 0,
+    "Bytes": [
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary6": {
+    "Offset": 0,
+    "Bytes": [
+      77,
+      117,
+      108,
+      116,
+      105,
+      112,
+      108,
+      101,
+      32,
+      76,
+      105,
+      110,
+      101,
+      32,
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary7": {
+    "Offset": 20,
+    "Bytes": [
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary8": {
+    "Offset": 0,
+    "Bytes": [
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary9": {
+    "Offset": 0,
+    "Bytes": [
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary10": {
+    "Offset": 0,
+    "Bytes": [
+      77,
+      117,
+      108,
+      116,
+      105,
+      112,
+      108,
+      101,
+      32,
+      76,
+      105,
+      110,
+      101,
+      32,
+      70,
+      111,
+      111,
+      66,
+      97,
+      114
+    ]
+  },
+  "Binary11": {
+    "Offset": 0,
+    "Bytes": [
+      255,
+      255
+    ]
+  }
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, PrintObject) {
@@ -524,7 +1044,11 @@ TEST_F(ScopedPrinterTest, PrintObject) {
 
   const char *ExpectedOut = R"(Object: Value
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "Object": "Value"
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
 TEST_F(ScopedPrinterTest, StartLine) {
@@ -574,5 +1098,20 @@ List [
   ]
 ]
 )";
-  verifyScopedPrinter(ExpectedOut, PrintFunc);
+
+  const char *JSONExpectedOut = R"({
+  "Object": {
+    "ObjectInObject": {},
+    "ListInObject": []
+  },
+  "List": [
+    {
+      "ObjectInList": {}
+    },
+    {
+      "ListInList": []
+    }
+  ]
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }


        


More information about the llvm-commits mailing list