[PATCH] D114052: Add JSONScopedPrinter as a subclass to ScopedPrinter with history stack

Jayson Yan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 16 20:54:13 PST 2021


Jaysonyan created this revision.
Jaysonyan added reviewers: leonardchan, phosek, jhenderson.
Herald added subscribers: dexonsmith, rupprecht, mgrang.
Jaysonyan requested review of this revision.
Herald added subscribers: llvm-commits, MaskRay.
Herald added a project: LLVM.

This is an alternative approach to the following diff: D111658: Add JSON output skeleton to llvm-readelf <https://reviews.llvm.org/D111658>

The major difference is that in this change `JSONScoperPrinter` inherits from `ScopedPrinter` rather
than creating a `ScopedPrinterBase` base class which both `JSONScopedPrinter` and `ScopedPrinter`
inherit from.

In comment {D111658#3121940 <https://reviews.llvm.org/D111658#3121940>} I cited 3 reasons for why I didn't think this was possible. I'll go over
how this change address each problem:

**Problem 1:** `ScopedPrinter` has template methods which are not able to be virtual.
**Solution:** Add private internal non-template methods which can be virtual. The
public template method then transforms all template parameters into concrete types
and then used to call the internal non-template method. This enables `JSONScopedPrinter`
to override the functionality of all of `ScopedPrinter`'s methods.

**Problem 2:** `ScopedPrinter` provides a method `startLine()` which returns the underlying
`raw_ostream`. It would be impossible to ensure printing directly to `raw_ostream` results 
in valid JSON.
**Solution:** There is still no easy solution to the problem. Though since this change is to
enable json output for `llvm-readelf`. The planned solution to this problem is to have a 
`JSONELFDumper` class similar to D111658: Add JSON output skeleton to llvm-readelf <https://reviews.llvm.org/D111658> and override
methods which call `startLine()` to use another interface.

**Problem 3:** A common usage pattern inside `llvm-readelf`  (calling `ListScope(W, "attr1")`
and then `DictScope(W, "attr2")`) produces invalid json since you can't have attributes inside
of lists. (The example would product the following json output)

  ListScope(W, "attr1");
  DictScope(W, "attr2");
  
  "attr1" : [
    "attr2" : { ... }
  ]

**Solution:** Add a "history" stack similar to the one inside `json::OStream` conditionally
output an encompassing `{}` if inside the context of a list. The following are code examples
and their respective outputs:

  ListScope(W, "attr1");
  DictScope(W, "attr2");
  W.printString("attr3",  "val");
  
  "attr1" : [
    {
      "attr2" : {
        "attr3" : "val"
      }
    }
  ]



  DictScope(W, "attr1");
  DictScope(W, "attr2");
  W.printString("attr3",  "val");
  
  "attr1" : {
    "attr2" : {
       "attr3" : "val"
    }
  }


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D114052

Files:
  llvm/include/llvm/Support/ScopedPrinter.h
  llvm/tools/llvm-readobj/llvm-readobj.cpp
  llvm/tools/llvm-readobj/llvm-readobj.h

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D114052.387806.patch
Type: text/x-patch
Size: 20548 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211117/3f58b4b5/attachment.bin>


More information about the llvm-commits mailing list