[PATCH] D114053: Add JSONScopedPrinter as a subclass to ScopedPrinter with array output

Jayson Yan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 16 20:56:16 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:** Adjust both `ListScope(..., Attr)` and `DictScope(..., Attr)` to always emit an enclosing `[]`
and then output the `Attr` as an element to the array. Then update calls to `printString(...), printNumber(...), etc`
to output enclosing `{}`. This ensures all calls to the `ScopedPrinter` can unconditionally handle being inside
the context of an array and ensure the next call is always in the context of an array. 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"
        }
      ]
  ]

//Note: There is also another approach which handles Problem 3 differently D114052: Add JSONScopedPrinter as a subclass to ScopedPrinter with history stack <https://reviews.llvm.org/D114052>//


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D114053

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: D114053.387815.patch
Type: text/x-patch
Size: 19613 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211117/f476997c/attachment.bin>


More information about the llvm-commits mailing list