Index: llvm/include/llvm/Support/ScopedPrinter.h =================================================================== --- llvm/include/llvm/Support/ScopedPrinter.h +++ 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 @@ -92,9 +93,21 @@ class ScopedPrinter { public: - ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {} + enum ScopedPrinterKind { + Standard, + JSON, + }; - virtual ~ScopedPrinter(){}; + ScopedPrinter(raw_ostream &OS, ScopedPrinterKind Kind = Standard) + : OS(OS), IndentLevel(0), Kind(Kind) {} + + ScopedPrinterKind getKind() const { return Kind; } + + static bool classof(const ScopedPrinter *SP) { + return SP->getKind() == Standard; + } + + virtual ~ScopedPrinter() {} void flush() { OS.flush(); } @@ -439,6 +452,7 @@ raw_ostream &OS; int IndentLevel; StringRef Prefix; + ScopedPrinterKind Kind; }; template <> @@ -448,6 +462,204 @@ startLine() << Label << ": " << hex(Value) << "\n"; } +class JSONScopedPrinter : public ScopedPrinter { + + enum Scope { + Array, + Object, + }; + enum ScopeKind { + Standard, + Attribute, + NestedAttribute, + }; + struct ScopeContext { + Scope Context; + ScopeKind Kind; + ScopeContext(Scope Context, ScopeKind Kind = ScopeKind::Standard) + : Context(Context), Kind(Kind) {} + }; + SmallVector ScopeHistory; + json::OStream JOS; + +public: + JSONScopedPrinter(llvm::raw_ostream &OS) + : ScopedPrinter(OS, ScopedPrinter::ScopedPrinterKind::JSON), JOS(OS, 2) {} + + static bool classof(const ScopedPrinter *SP) { return SP->getKind() == JSON; } + + void printNumber(StringRef Label, uint64_t Value) override { + JOS.attribute(Label, to_string(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 { + SmallString<64> StringValue; + Value.toString(StringValue); + JOS.attribute(Label, StringValue); + } + + void printBoolean(StringRef Label, bool Value) override { + JOS.attribute(Label, Value); + } + + void printString(StringRef Value) override { JOS.value(Value); } + + void printString(StringRef Label, StringRef Value) override { + JOS.attribute(Label, Value); + } + + void objectBegin() override { + JOS.objectBegin(); + ScopeHistory.emplace_back(Scope::Object, ScopeKind::Standard); + } + + void objectBegin(StringRef Label) override { + ScopeContext ScopeCtx{Scope::Object, ScopeKind::Attribute}; + if (ScopeHistory.back().Context == Scope::Array) { + JOS.objectBegin(); + ScopeCtx.Kind = ScopeKind::NestedAttribute; + } + JOS.attributeBegin(Label); + JOS.objectBegin(); + ScopeHistory.emplace_back(ScopeCtx); + } + + void objectEnd() override { + ScopeContext ScopeCtx = ScopeHistory.back(); + if (ScopeCtx.Context == Scope::Object) { + JOS.objectEnd(); + if (ScopeCtx.Kind == ScopeKind::Attribute || + ScopeCtx.Kind == ScopeKind::NestedAttribute) + JOS.attributeEnd(); + if (ScopeCtx.Kind == ScopeKind::NestedAttribute) + JOS.objectEnd(); + } + ScopeHistory.pop_back(); + } + + void arrayBegin() override { + JOS.arrayBegin(); + ScopeHistory.emplace_back(Scope::Array, ScopeKind::Standard); + } + + void arrayBegin(StringRef Label) override { + ScopeContext ScopeCtx{Scope::Array, ScopeKind::Attribute}; + if (ScopeHistory.back().Context == Scope::Array) { + JOS.objectBegin(); + ScopeCtx.Kind = ScopeKind::NestedAttribute; + } + JOS.attributeBegin(Label); + JOS.arrayBegin(); + ScopeHistory.emplace_back(ScopeCtx); + } + + void arrayEnd() override { + ScopeContext ScopeCtx = ScopeHistory.back(); + 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(); + } + + raw_ostream &startLine() override { + raw_ostream &OS = JOS.rawValueBegin(); + JOS.rawValueEnd(); + return OS; + } + + raw_ostream &getOStream() override { + raw_ostream &OS = JOS.rawValueBegin(); + JOS.rawValueEnd(); + return OS; + } + +private: + void printFlagsImpl(StringRef Label, HexNumber Value, + ArrayRef Flags) override { + JOS.attributeArray(Label, [&]() { + for (const auto &Flag : Flags) { + JOS.value(Flag.Name); + } + }); + } + + void printListImpl(StringRef Label, + const ArrayRef List) override { + JOS.attributeArray(Label, [&]() { + for (const auto &Item : List) { + JOS.value(Item); + } + }); + } + + void printHexListImpl(StringRef Label, + const ArrayRef List) override { + JOS.attributeArray(Label, [&]() { + for (const auto &Item : List) { + JOS.value(to_hexString(Item.Value)); + } + }); + } + + void printHexImpl(StringRef Label, HexNumber Value) override { + JOS.attribute(Label, "0x" + to_hexString(Value.Value)); + } + + void printHexImpl(StringRef Label, StringRef Str, HexNumber Value) override { + JOS.attribute(Label, Str); + JOS.attribute(Label.str() + "_raw", "0x" + to_hexString(Value.Value)); + } + + void printSymbolOffsetImpl(StringRef Label, StringRef Symbol, + HexNumber Value) override { + JOS.attribute(Label, Symbol.str() + "+0x" + to_hexString(Value.Value)); + } + + void printNumberImpl(StringRef Label, StringRef Str, + StringRef Value) override { + JOS.attribute(Label, Str); + JOS.attribute(Label.str() + "_raw", Value); + } + + void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef Value, + bool Block, uint32_t StartOffset = 0) override { + // TODO: Implement + } +}; + struct DelimitedScope { DelimitedScope(ScopedPrinter &W) : W(W) {} virtual ~DelimitedScope(){};