CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
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/ScopeExit.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/ADT/TypeSwitch.h"
17
18namespace json = llvm::json;
19
20using namespace circt;
21using llvm::make_scope_exit;
22using mlir::UnitAttr;
23
24// NOLINTBEGIN(misc-no-recursion)
25LogicalResult circt::convertAttributeToJSON(llvm::json::OStream &json,
26 Attribute attr) {
27 return TypeSwitch<Attribute, LogicalResult>(attr)
28 .Case<DictionaryAttr>([&](auto attr) {
29 json.objectBegin();
30 auto guard = make_scope_exit([&] { json.objectEnd(); });
31 for (auto subAttr : attr) {
32 json.attributeBegin(subAttr.getName());
33 auto guard = make_scope_exit([&] { json.attributeEnd(); });
34 if (failed(convertAttributeToJSON(json, subAttr.getValue())))
35 return failure();
36 }
37 return success();
38 })
39 .Case<ArrayAttr>([&](auto attr) {
40 json.arrayBegin();
41 auto guard = make_scope_exit([&] { json.arrayEnd(); });
42 for (auto subAttr : attr)
43 if (failed(convertAttributeToJSON(json, subAttr)))
44 return failure();
45 return success();
46 })
47 .Case<BoolAttr, StringAttr>([&](auto attr) {
48 json.value(attr.getValue());
49 return success();
50 })
51 .Case<IntegerAttr>([&](auto attr) -> LogicalResult {
52 // If the integer can be accurately represented by a double, print
53 // it as an integer. Otherwise, convert it to an exact decimal string.
54 const auto &apint = attr.getValue();
55 if (!apint.isSignedIntN(64)) {
56 json.value(nullptr);
57 return failure();
58 }
59 json.value(apint.getSExtValue());
60 return success();
61 })
62 .Case<FloatAttr>([&](auto attr) -> LogicalResult {
63 const auto &apfloat = attr.getValue();
64 json.value(apfloat.convertToDouble());
65 return success();
66 })
67 .Default([&](auto) -> LogicalResult {
68 json.value(nullptr);
69 return failure();
70 });
71}
72// NOLINTEND(misc-no-recursion)
73
74// NOLINTBEGIN(misc-no-recursion)
75Attribute circt::convertJSONToAttribute(MLIRContext *context,
76 json::Value &value, json::Path p) {
77 // String or quoted JSON
78 if (auto a = value.getAsString()) {
79 // Test to see if this might be quoted JSON (a string that is actually
80 // JSON). Sometimes FIRRTL developers will do this to serialize objects
81 // that the Scala FIRRTL Compiler doesn't know about.
82 auto unquotedValue = json::parse(*a);
83 auto err = unquotedValue.takeError();
84 // If this parsed without an error and we didn't just unquote a number, then
85 // it's more JSON and recurse on that.
86 //
87 // We intentionally do not want to unquote a number as, in JSON, the string
88 // "0" is different from the number 0. If we conflate these, then later
89 // expectations about annotation structure may be broken. I.e., an
90 // annotation expecting a string may see a number.
91 if (!err && !unquotedValue.get().getAsNumber())
92 return convertJSONToAttribute(context, unquotedValue.get(), p);
93 // If there was an error, then swallow it and handle this as a string.
94 handleAllErrors(std::move(err), [&](const json::ParseError &a) {});
95 return StringAttr::get(context, *a);
96 }
97
98 // Integer
99 if (auto a = value.getAsInteger())
100 return IntegerAttr::get(IntegerType::get(context, 64), *a);
101
102 // Float
103 if (auto a = value.getAsNumber())
104 return FloatAttr::get(mlir::Float64Type::get(context), *a);
105
106 // Boolean
107 if (auto a = value.getAsBoolean())
108 return BoolAttr::get(context, *a);
109
110 // Null
111 if (auto a = value.getAsNull())
112 return mlir::UnitAttr::get(context);
113
114 // Object
115 if (auto *a = value.getAsObject()) {
116 NamedAttrList metadata;
117 for (auto b : *a)
118 metadata.append(
119 b.first, convertJSONToAttribute(context, b.second, p.field(b.first)));
120 return DictionaryAttr::get(context, metadata);
121 }
122
123 // Array
124 if (auto *a = value.getAsArray()) {
125 SmallVector<Attribute> metadata;
126 for (size_t i = 0, e = (*a).size(); i != e; ++i)
127 metadata.push_back(convertJSONToAttribute(context, (*a)[i], p.index(i)));
128 return ArrayAttr::get(context, metadata);
129 }
130
131 llvm_unreachable("Impossible unhandled JSON type");
132}
133// NOLINTEND(misc-no-recursion)
static StringAttr append(StringAttr base, const Twine &suffix)
Return a attribute with the specified suffix appended.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
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:25