CIRCT  19.0.0git
JSON.cpp
Go to the documentation of this file.
1 //===- Json.cpp - Json Utilities --------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "circt/Support/JSON.h"
10 #include "mlir/IR/BuiltinAttributes.h"
11 #include "mlir/IR/BuiltinTypes.h"
12 #include "mlir/IR/Diagnostics.h"
13 #include "mlir/IR/OperationSupport.h"
14 #include "llvm/ADT/StringSwitch.h"
15 #include "llvm/ADT/TypeSwitch.h"
16 
17 namespace json = llvm::json;
18 
19 using namespace circt;
20 using mlir::UnitAttr;
21 
22 // NOLINTBEGIN(misc-no-recursion)
23 LogicalResult circt::convertAttributeToJSON(llvm::json::OStream &json,
24  Attribute attr) {
25  return TypeSwitch<Attribute, LogicalResult>(attr)
26  .Case<DictionaryAttr>([&](auto attr) {
27  json.objectBegin();
28  for (auto subAttr : attr) {
29  json.attributeBegin(subAttr.getName());
30  if (failed(convertAttributeToJSON(json, subAttr.getValue())))
31  return failure();
32  json.attributeEnd();
33  }
34  json.objectEnd();
35  return success();
36  })
37  .Case<ArrayAttr>([&](auto attr) {
38  json.arrayBegin();
39  for (auto subAttr : attr)
40  if (failed(convertAttributeToJSON(json, subAttr)))
41  return failure();
42  json.arrayEnd();
43  return success();
44  })
45  .Case<BoolAttr, StringAttr>([&](auto attr) {
46  json.value(attr.getValue());
47  return success();
48  })
49  .Case<IntegerAttr>([&](auto attr) -> LogicalResult {
50  // If the integer can be accurately represented by a double, print
51  // it as an integer. Otherwise, convert it to an exact decimal string.
52  const auto &apint = attr.getValue();
53  if (!apint.isSignedIntN(64))
54  return failure();
55  json.value(apint.getSExtValue());
56  return success();
57  })
58  .Case<FloatAttr>([&](auto attr) -> LogicalResult {
59  const auto &apfloat = attr.getValue();
60  json.value(apfloat.convertToDouble());
61  return success();
62  })
63  .Default([&](auto) -> LogicalResult { return failure(); });
64 }
65 // NOLINTEND(misc-no-recursion)
66 
67 // NOLINTBEGIN(misc-no-recursion)
68 Attribute circt::convertJSONToAttribute(MLIRContext *context,
69  json::Value &value, json::Path p) {
70  // String or quoted JSON
71  if (auto a = value.getAsString()) {
72  // Test to see if this might be quoted JSON (a string that is actually
73  // JSON). Sometimes FIRRTL developers will do this to serialize objects
74  // that the Scala FIRRTL Compiler doesn't know about.
75  auto unquotedValue = json::parse(*a);
76  auto err = unquotedValue.takeError();
77  // If this parsed without an error and we didn't just unquote a number, then
78  // it's more JSON and recurse on that.
79  //
80  // We intentionally do not want to unquote a number as, in JSON, the string
81  // "0" is different from the number 0. If we conflate these, then later
82  // expectations about annotation structure may be broken. I.e., an
83  // annotation expecting a string may see a number.
84  if (!err && !unquotedValue.get().getAsNumber())
85  return convertJSONToAttribute(context, unquotedValue.get(), p);
86  // If there was an error, then swallow it and handle this as a string.
87  handleAllErrors(std::move(err), [&](const json::ParseError &a) {});
88  return StringAttr::get(context, *a);
89  }
90 
91  // Integer
92  if (auto a = value.getAsInteger())
93  return IntegerAttr::get(IntegerType::get(context, 64), *a);
94 
95  // Float
96  if (auto a = value.getAsNumber())
97  return FloatAttr::get(mlir::FloatType::getF64(context), *a);
98 
99  // Boolean
100  if (auto a = value.getAsBoolean())
101  return BoolAttr::get(context, *a);
102 
103  // Null
104  if (auto a = value.getAsNull())
105  return mlir::UnitAttr::get(context);
106 
107  // Object
108  if (auto *a = value.getAsObject()) {
109  NamedAttrList metadata;
110  for (auto b : *a)
111  metadata.append(
112  b.first, convertJSONToAttribute(context, b.second, p.field(b.first)));
113  return DictionaryAttr::get(context, metadata);
114  }
115 
116  // Array
117  if (auto *a = value.getAsArray()) {
118  SmallVector<Attribute> metadata;
119  for (size_t i = 0, e = (*a).size(); i != e; ++i)
120  metadata.push_back(convertJSONToAttribute(context, (*a)[i], p.index(i)));
121  return ArrayAttr::get(context, metadata);
122  }
123 
124  llvm_unreachable("Impossible unhandled JSON type");
125 }
126 // NOLINTEND(misc-no-recursion)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:54
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Attribute convertJSONToAttribute(MLIRContext *context, llvm::json::Value &value, llvm::json::Path p)
Convert arbitrary JSON to an MLIR Attribute.
LogicalResult convertAttributeToJSON(llvm::json::OStream &json, Attribute attr)
Convert a simple attribute to JSON.
Definition: JSON.cpp:23