1*438f7fc0SSiva Chandra Reddy //===-- JSON serialization routines ---------------------------------------===//
2*438f7fc0SSiva Chandra Reddy //
3*438f7fc0SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*438f7fc0SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5*438f7fc0SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*438f7fc0SSiva Chandra Reddy //
7*438f7fc0SSiva Chandra Reddy //===----------------------------------------------------------------------===//
8*438f7fc0SSiva Chandra Reddy 
9*438f7fc0SSiva Chandra Reddy #include "JSON.h"
10*438f7fc0SSiva Chandra Reddy #include "LibcBenchmark.h"
11*438f7fc0SSiva Chandra Reddy #include "llvm/ADT/DenseSet.h"
12*438f7fc0SSiva Chandra Reddy #include "llvm/ADT/SmallVector.h"
13*438f7fc0SSiva Chandra Reddy #include "llvm/ADT/StringRef.h"
14*438f7fc0SSiva Chandra Reddy #include "llvm/ADT/StringSwitch.h"
15*438f7fc0SSiva Chandra Reddy #include "llvm/Support/Errc.h"
16*438f7fc0SSiva Chandra Reddy #include "llvm/Support/Error.h"
17*438f7fc0SSiva Chandra Reddy #include "llvm/Support/ErrorHandling.h"
18*438f7fc0SSiva Chandra Reddy #include "llvm/Support/JSON.h"
19*438f7fc0SSiva Chandra Reddy #include "llvm/Support/MathExtras.h"
20*438f7fc0SSiva Chandra Reddy 
21*438f7fc0SSiva Chandra Reddy #include <chrono>
22*438f7fc0SSiva Chandra Reddy #include <limits>
23*438f7fc0SSiva Chandra Reddy #include <memory>
24*438f7fc0SSiva Chandra Reddy #include <string>
25*438f7fc0SSiva Chandra Reddy #include <vector>
26*438f7fc0SSiva Chandra Reddy 
27*438f7fc0SSiva Chandra Reddy namespace llvm {
28*438f7fc0SSiva Chandra Reddy namespace libc_benchmarks {
29*438f7fc0SSiva Chandra Reddy 
30*438f7fc0SSiva Chandra Reddy template <typename T>
31*438f7fc0SSiva Chandra Reddy static Error intFromJsonTemplate(const json::Value &V, T &Out) {
32*438f7fc0SSiva Chandra Reddy   if (const auto &MaybeInt64 = V.getAsInteger()) {
33*438f7fc0SSiva Chandra Reddy     int64_t Value = *MaybeInt64;
34*438f7fc0SSiva Chandra Reddy     if (Value < std::numeric_limits<T>::min() ||
35*438f7fc0SSiva Chandra Reddy         Value > std::numeric_limits<T>::max())
36*438f7fc0SSiva Chandra Reddy       return createStringError(errc::io_error, "Out of bound Integer");
37*438f7fc0SSiva Chandra Reddy     Out = Value;
38*438f7fc0SSiva Chandra Reddy     return Error::success();
39*438f7fc0SSiva Chandra Reddy   }
40*438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error, "Can't parse Integer");
41*438f7fc0SSiva Chandra Reddy }
42*438f7fc0SSiva Chandra Reddy 
43*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, double &Out) {
44*438f7fc0SSiva Chandra Reddy   if (auto S = V.getAsNumber()) {
45*438f7fc0SSiva Chandra Reddy     Out = *S;
46*438f7fc0SSiva Chandra Reddy     return Error::success();
47*438f7fc0SSiva Chandra Reddy   }
48*438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error, "Can't parse Double");
49*438f7fc0SSiva Chandra Reddy }
50*438f7fc0SSiva Chandra Reddy 
51*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, std::string &Out) {
52*438f7fc0SSiva Chandra Reddy   if (auto S = V.getAsString()) {
53*438f7fc0SSiva Chandra Reddy     Out = std::string(*S);
54*438f7fc0SSiva Chandra Reddy     return Error::success();
55*438f7fc0SSiva Chandra Reddy   }
56*438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error, "Can't parse String");
57*438f7fc0SSiva Chandra Reddy }
58*438f7fc0SSiva Chandra Reddy 
59*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, uint32_t &Out) {
60*438f7fc0SSiva Chandra Reddy   return intFromJsonTemplate(V, Out);
61*438f7fc0SSiva Chandra Reddy }
62*438f7fc0SSiva Chandra Reddy 
63*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, uint8_t &Out) {
64*438f7fc0SSiva Chandra Reddy   return intFromJsonTemplate(V, Out);
65*438f7fc0SSiva Chandra Reddy }
66*438f7fc0SSiva Chandra Reddy 
67*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, int &Out) {
68*438f7fc0SSiva Chandra Reddy   return intFromJsonTemplate(V, Out);
69*438f7fc0SSiva Chandra Reddy }
70*438f7fc0SSiva Chandra Reddy 
71*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::Duration &D) {
72*438f7fc0SSiva Chandra Reddy   if (V.kind() != json::Value::Kind::Number)
73*438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error, "Can't parse Duration");
74*438f7fc0SSiva Chandra Reddy   D = libc_benchmarks::Duration(*V.getAsNumber());
75*438f7fc0SSiva Chandra Reddy   return Error::success();
76*438f7fc0SSiva Chandra Reddy }
77*438f7fc0SSiva Chandra Reddy 
78*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, MaybeAlign &Out) {
79*438f7fc0SSiva Chandra Reddy   const auto MaybeInt = V.getAsInteger();
80*438f7fc0SSiva Chandra Reddy   if (!MaybeInt)
81*438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
82*438f7fc0SSiva Chandra Reddy                              "Can't parse Align, not an Integer");
83*438f7fc0SSiva Chandra Reddy   const int64_t Value = *MaybeInt;
84*438f7fc0SSiva Chandra Reddy   if (!Value) {
85*438f7fc0SSiva Chandra Reddy     Out = None;
86*438f7fc0SSiva Chandra Reddy     return Error::success();
87*438f7fc0SSiva Chandra Reddy   }
88*438f7fc0SSiva Chandra Reddy   if (isPowerOf2_64(Value)) {
89*438f7fc0SSiva Chandra Reddy     Out = Align(Value);
90*438f7fc0SSiva Chandra Reddy     return Error::success();
91*438f7fc0SSiva Chandra Reddy   }
92*438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error,
93*438f7fc0SSiva Chandra Reddy                            "Can't parse Align, not a power of two");
94*438f7fc0SSiva Chandra Reddy }
95*438f7fc0SSiva Chandra Reddy 
96*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
97*438f7fc0SSiva Chandra Reddy                       libc_benchmarks::BenchmarkLog &Out) {
98*438f7fc0SSiva Chandra Reddy   if (V.kind() != json::Value::Kind::String)
99*438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
100*438f7fc0SSiva Chandra Reddy                              "Can't parse BenchmarkLog, not a String");
101*438f7fc0SSiva Chandra Reddy   const auto String = *V.getAsString();
102*438f7fc0SSiva Chandra Reddy   auto Parsed =
103*438f7fc0SSiva Chandra Reddy       llvm::StringSwitch<Optional<libc_benchmarks::BenchmarkLog>>(String)
104*438f7fc0SSiva Chandra Reddy           .Case("None", libc_benchmarks::BenchmarkLog::None)
105*438f7fc0SSiva Chandra Reddy           .Case("Last", libc_benchmarks::BenchmarkLog::Last)
106*438f7fc0SSiva Chandra Reddy           .Case("Full", libc_benchmarks::BenchmarkLog::Full)
107*438f7fc0SSiva Chandra Reddy           .Default(None);
108*438f7fc0SSiva Chandra Reddy   if (!Parsed)
109*438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
110*438f7fc0SSiva Chandra Reddy                              Twine("Can't parse BenchmarkLog, invalid value '")
111*438f7fc0SSiva Chandra Reddy                                  .concat(String)
112*438f7fc0SSiva Chandra Reddy                                  .concat("'"));
113*438f7fc0SSiva Chandra Reddy   Out = *Parsed;
114*438f7fc0SSiva Chandra Reddy   return Error::success();
115*438f7fc0SSiva Chandra Reddy }
116*438f7fc0SSiva Chandra Reddy 
117*438f7fc0SSiva Chandra Reddy template <typename C>
118*438f7fc0SSiva Chandra Reddy Error vectorFromJsonTemplate(const json::Value &V, C &Out) {
119*438f7fc0SSiva Chandra Reddy   auto *A = V.getAsArray();
120*438f7fc0SSiva Chandra Reddy   if (!A)
121*438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error, "Can't parse Array");
122*438f7fc0SSiva Chandra Reddy   Out.clear();
123*438f7fc0SSiva Chandra Reddy   Out.resize(A->size());
124*438f7fc0SSiva Chandra Reddy   for (auto InOutPair : llvm::zip(*A, Out))
125*438f7fc0SSiva Chandra Reddy     if (auto E = fromJson(std::get<0>(InOutPair), std::get<1>(InOutPair)))
126*438f7fc0SSiva Chandra Reddy       return std::move(E);
127*438f7fc0SSiva Chandra Reddy   return Error::success();
128*438f7fc0SSiva Chandra Reddy }
129*438f7fc0SSiva Chandra Reddy 
130*438f7fc0SSiva Chandra Reddy template <typename T>
131*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, std::vector<T> &Out) {
132*438f7fc0SSiva Chandra Reddy   return vectorFromJsonTemplate(V, Out);
133*438f7fc0SSiva Chandra Reddy }
134*438f7fc0SSiva Chandra Reddy 
135*438f7fc0SSiva Chandra Reddy template <typename T>
136*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, SmallVectorImpl<T> &Out) {
137*438f7fc0SSiva Chandra Reddy   return vectorFromJsonTemplate(V, Out);
138*438f7fc0SSiva Chandra Reddy }
139*438f7fc0SSiva Chandra Reddy 
140*438f7fc0SSiva Chandra Reddy // Same as llvm::json::ObjectMapper but adds a finer error reporting mechanism.
141*438f7fc0SSiva Chandra Reddy class JsonObjectMapper {
142*438f7fc0SSiva Chandra Reddy   const json::Object *O;
143*438f7fc0SSiva Chandra Reddy   Error E;
144*438f7fc0SSiva Chandra Reddy   SmallDenseSet<StringRef> SeenFields;
145*438f7fc0SSiva Chandra Reddy 
146*438f7fc0SSiva Chandra Reddy public:
147*438f7fc0SSiva Chandra Reddy   explicit JsonObjectMapper(const json::Value &V)
148*438f7fc0SSiva Chandra Reddy       : O(V.getAsObject()),
149*438f7fc0SSiva Chandra Reddy         E(O ? Error::success()
150*438f7fc0SSiva Chandra Reddy             : createStringError(errc::io_error, "Expected JSON Object")) {}
151*438f7fc0SSiva Chandra Reddy 
152*438f7fc0SSiva Chandra Reddy   Error takeError() {
153*438f7fc0SSiva Chandra Reddy     if (E)
154*438f7fc0SSiva Chandra Reddy       return std::move(E);
155*438f7fc0SSiva Chandra Reddy     for (const auto &Itr : *O) {
156*438f7fc0SSiva Chandra Reddy       const StringRef Key = Itr.getFirst();
157*438f7fc0SSiva Chandra Reddy       if (!SeenFields.count(Key))
158*438f7fc0SSiva Chandra Reddy         E = createStringError(errc::io_error,
159*438f7fc0SSiva Chandra Reddy                               Twine("Unknown field: ").concat(Key));
160*438f7fc0SSiva Chandra Reddy     }
161*438f7fc0SSiva Chandra Reddy     return std::move(E);
162*438f7fc0SSiva Chandra Reddy   }
163*438f7fc0SSiva Chandra Reddy 
164*438f7fc0SSiva Chandra Reddy   template <typename T> void map(StringRef Key, T &Out) {
165*438f7fc0SSiva Chandra Reddy     if (E)
166*438f7fc0SSiva Chandra Reddy       return;
167*438f7fc0SSiva Chandra Reddy     if (const json::Value *Value = O->get(Key)) {
168*438f7fc0SSiva Chandra Reddy       SeenFields.insert(Key);
169*438f7fc0SSiva Chandra Reddy       E = fromJson(*Value, Out);
170*438f7fc0SSiva Chandra Reddy     }
171*438f7fc0SSiva Chandra Reddy   }
172*438f7fc0SSiva Chandra Reddy };
173*438f7fc0SSiva Chandra Reddy 
174*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
175*438f7fc0SSiva Chandra Reddy                       libc_benchmarks::BenchmarkOptions &Out) {
176*438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
177*438f7fc0SSiva Chandra Reddy   O.map("MinDuration", Out.MinDuration);
178*438f7fc0SSiva Chandra Reddy   O.map("MaxDuration", Out.MaxDuration);
179*438f7fc0SSiva Chandra Reddy   O.map("InitialIterations", Out.InitialIterations);
180*438f7fc0SSiva Chandra Reddy   O.map("MaxIterations", Out.MaxIterations);
181*438f7fc0SSiva Chandra Reddy   O.map("MinSamples", Out.MinSamples);
182*438f7fc0SSiva Chandra Reddy   O.map("MaxSamples", Out.MaxSamples);
183*438f7fc0SSiva Chandra Reddy   O.map("Epsilon", Out.Epsilon);
184*438f7fc0SSiva Chandra Reddy   O.map("ScalingFactor", Out.ScalingFactor);
185*438f7fc0SSiva Chandra Reddy   O.map("Log", Out.Log);
186*438f7fc0SSiva Chandra Reddy   return O.takeError();
187*438f7fc0SSiva Chandra Reddy }
188*438f7fc0SSiva Chandra Reddy 
189*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::SizeRange &Out) {
190*438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
191*438f7fc0SSiva Chandra Reddy   O.map("From", Out.From);
192*438f7fc0SSiva Chandra Reddy   O.map("To", Out.To);
193*438f7fc0SSiva Chandra Reddy   O.map("Step", Out.Step);
194*438f7fc0SSiva Chandra Reddy   return O.takeError();
195*438f7fc0SSiva Chandra Reddy }
196*438f7fc0SSiva Chandra Reddy 
197*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
198*438f7fc0SSiva Chandra Reddy                       libc_benchmarks::StudyConfiguration &Out) {
199*438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
200*438f7fc0SSiva Chandra Reddy   O.map("Runs", Out.Runs);
201*438f7fc0SSiva Chandra Reddy   O.map("BufferSize", Out.BufferSize);
202*438f7fc0SSiva Chandra Reddy   O.map("Size", Out.Size);
203*438f7fc0SSiva Chandra Reddy   O.map("AddressAlignment", Out.AddressAlignment);
204*438f7fc0SSiva Chandra Reddy   O.map("MemsetValue", Out.MemsetValue);
205*438f7fc0SSiva Chandra Reddy   O.map("MemcmpMismatchAt", Out.MemcmpMismatchAt);
206*438f7fc0SSiva Chandra Reddy   return O.takeError();
207*438f7fc0SSiva Chandra Reddy }
208*438f7fc0SSiva Chandra Reddy 
209*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::CacheInfo &Out) {
210*438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
211*438f7fc0SSiva Chandra Reddy   O.map("Type", Out.Type);
212*438f7fc0SSiva Chandra Reddy   O.map("Level", Out.Level);
213*438f7fc0SSiva Chandra Reddy   O.map("Size", Out.Size);
214*438f7fc0SSiva Chandra Reddy   O.map("NumSharing", Out.NumSharing);
215*438f7fc0SSiva Chandra Reddy   return O.takeError();
216*438f7fc0SSiva Chandra Reddy }
217*438f7fc0SSiva Chandra Reddy 
218*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::HostState &Out) {
219*438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
220*438f7fc0SSiva Chandra Reddy   O.map("CpuName", Out.CpuName);
221*438f7fc0SSiva Chandra Reddy   O.map("CpuFrequency", Out.CpuFrequency);
222*438f7fc0SSiva Chandra Reddy   O.map("Caches", Out.Caches);
223*438f7fc0SSiva Chandra Reddy   return O.takeError();
224*438f7fc0SSiva Chandra Reddy }
225*438f7fc0SSiva Chandra Reddy 
226*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
227*438f7fc0SSiva Chandra Reddy                       libc_benchmarks::FunctionMeasurements &Out) {
228*438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
229*438f7fc0SSiva Chandra Reddy   O.map("Name", Out.Name);
230*438f7fc0SSiva Chandra Reddy   std::vector<uint32_t> Sizes;
231*438f7fc0SSiva Chandra Reddy   O.map("Sizes", Sizes);
232*438f7fc0SSiva Chandra Reddy   std::vector<libc_benchmarks::Duration> Runtimes;
233*438f7fc0SSiva Chandra Reddy   O.map("Runtimes", Runtimes);
234*438f7fc0SSiva Chandra Reddy   if (Sizes.size() != Runtimes.size())
235*438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
236*438f7fc0SSiva Chandra Reddy                              "Measurement Size and Runtime mistmatch");
237*438f7fc0SSiva Chandra Reddy   Out.Measurements.resize(Sizes.size());
238*438f7fc0SSiva Chandra Reddy   for (size_t I = 0; I < Sizes.size(); ++I) {
239*438f7fc0SSiva Chandra Reddy     Out.Measurements[I].Size = Sizes[I];
240*438f7fc0SSiva Chandra Reddy     Out.Measurements[I].Runtime = Runtimes[I];
241*438f7fc0SSiva Chandra Reddy   }
242*438f7fc0SSiva Chandra Reddy   return O.takeError();
243*438f7fc0SSiva Chandra Reddy }
244*438f7fc0SSiva Chandra Reddy 
245*438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::Study &Out) {
246*438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
247*438f7fc0SSiva Chandra Reddy   O.map("Host", Out.Host);
248*438f7fc0SSiva Chandra Reddy   O.map("Options", Out.Options);
249*438f7fc0SSiva Chandra Reddy   O.map("Configuration", Out.Configuration);
250*438f7fc0SSiva Chandra Reddy   O.map("Functions", Out.Functions);
251*438f7fc0SSiva Chandra Reddy   return O.takeError();
252*438f7fc0SSiva Chandra Reddy }
253*438f7fc0SSiva Chandra Reddy 
254*438f7fc0SSiva Chandra Reddy static double Seconds(const Duration &D) {
255*438f7fc0SSiva Chandra Reddy   return std::chrono::duration<double>(D).count();
256*438f7fc0SSiva Chandra Reddy }
257*438f7fc0SSiva Chandra Reddy 
258*438f7fc0SSiva Chandra Reddy Expected<Study> ParseJsonStudy(StringRef Content) {
259*438f7fc0SSiva Chandra Reddy   Expected<json::Value> EV = json::parse(Content);
260*438f7fc0SSiva Chandra Reddy   if (!EV)
261*438f7fc0SSiva Chandra Reddy     return EV.takeError();
262*438f7fc0SSiva Chandra Reddy   Study S;
263*438f7fc0SSiva Chandra Reddy   if (Error E = fromJson(*EV, S))
264*438f7fc0SSiva Chandra Reddy     return std::move(E);
265*438f7fc0SSiva Chandra Reddy   return S;
266*438f7fc0SSiva Chandra Reddy }
267*438f7fc0SSiva Chandra Reddy 
268*438f7fc0SSiva Chandra Reddy static StringRef Serialize(const BenchmarkLog &L) {
269*438f7fc0SSiva Chandra Reddy   switch (L) {
270*438f7fc0SSiva Chandra Reddy   case BenchmarkLog::None:
271*438f7fc0SSiva Chandra Reddy     return "None";
272*438f7fc0SSiva Chandra Reddy   case BenchmarkLog::Last:
273*438f7fc0SSiva Chandra Reddy     return "Last";
274*438f7fc0SSiva Chandra Reddy   case BenchmarkLog::Full:
275*438f7fc0SSiva Chandra Reddy     return "Full";
276*438f7fc0SSiva Chandra Reddy   }
277*438f7fc0SSiva Chandra Reddy   llvm_unreachable("Unhandled BenchmarkLog value");
278*438f7fc0SSiva Chandra Reddy }
279*438f7fc0SSiva Chandra Reddy 
280*438f7fc0SSiva Chandra Reddy static void Serialize(const BenchmarkOptions &BO, json::OStream &JOS) {
281*438f7fc0SSiva Chandra Reddy   JOS.object([&]() {
282*438f7fc0SSiva Chandra Reddy     JOS.attribute("MinDuration", Seconds(BO.MinDuration));
283*438f7fc0SSiva Chandra Reddy     JOS.attribute("MaxDuration", Seconds(BO.MaxDuration));
284*438f7fc0SSiva Chandra Reddy     JOS.attribute("InitialIterations", BO.InitialIterations);
285*438f7fc0SSiva Chandra Reddy     JOS.attribute("MaxIterations", BO.MaxIterations);
286*438f7fc0SSiva Chandra Reddy     JOS.attribute("MinSamples", BO.MinSamples);
287*438f7fc0SSiva Chandra Reddy     JOS.attribute("MaxSamples", BO.MaxSamples);
288*438f7fc0SSiva Chandra Reddy     JOS.attribute("Epsilon", BO.Epsilon);
289*438f7fc0SSiva Chandra Reddy     JOS.attribute("ScalingFactor", BO.ScalingFactor);
290*438f7fc0SSiva Chandra Reddy     JOS.attribute("Log", Serialize(BO.Log));
291*438f7fc0SSiva Chandra Reddy   });
292*438f7fc0SSiva Chandra Reddy }
293*438f7fc0SSiva Chandra Reddy 
294*438f7fc0SSiva Chandra Reddy static void Serialize(const CacheInfo &CI, json::OStream &JOS) {
295*438f7fc0SSiva Chandra Reddy   JOS.object([&]() {
296*438f7fc0SSiva Chandra Reddy     JOS.attribute("Type", CI.Type);
297*438f7fc0SSiva Chandra Reddy     JOS.attribute("Level", CI.Level);
298*438f7fc0SSiva Chandra Reddy     JOS.attribute("Size", CI.Size);
299*438f7fc0SSiva Chandra Reddy     JOS.attribute("NumSharing", CI.NumSharing);
300*438f7fc0SSiva Chandra Reddy   });
301*438f7fc0SSiva Chandra Reddy }
302*438f7fc0SSiva Chandra Reddy 
303*438f7fc0SSiva Chandra Reddy static void Serialize(const HostState &HS, json::OStream &JOS) {
304*438f7fc0SSiva Chandra Reddy   JOS.object([&]() {
305*438f7fc0SSiva Chandra Reddy     JOS.attribute("CpuName", HS.CpuName);
306*438f7fc0SSiva Chandra Reddy     JOS.attribute("CpuFrequency", HS.CpuFrequency);
307*438f7fc0SSiva Chandra Reddy     JOS.attributeArray("Caches", [&]() {
308*438f7fc0SSiva Chandra Reddy       for (const auto &CI : HS.Caches)
309*438f7fc0SSiva Chandra Reddy         Serialize(CI, JOS);
310*438f7fc0SSiva Chandra Reddy     });
311*438f7fc0SSiva Chandra Reddy   });
312*438f7fc0SSiva Chandra Reddy }
313*438f7fc0SSiva Chandra Reddy 
314*438f7fc0SSiva Chandra Reddy static void Serialize(const StudyConfiguration &SC, json::OStream &JOS) {
315*438f7fc0SSiva Chandra Reddy   JOS.object([&]() {
316*438f7fc0SSiva Chandra Reddy     JOS.attribute("Runs", SC.Runs);
317*438f7fc0SSiva Chandra Reddy     JOS.attribute("BufferSize", SC.BufferSize);
318*438f7fc0SSiva Chandra Reddy     JOS.attributeObject("Size", [&]() {
319*438f7fc0SSiva Chandra Reddy       JOS.attribute("From", SC.Size.From);
320*438f7fc0SSiva Chandra Reddy       JOS.attribute("To", SC.Size.To);
321*438f7fc0SSiva Chandra Reddy       JOS.attribute("Step", SC.Size.Step);
322*438f7fc0SSiva Chandra Reddy     });
323*438f7fc0SSiva Chandra Reddy     if (SC.AddressAlignment)
324*438f7fc0SSiva Chandra Reddy       JOS.attribute("AddressAlignment",
325*438f7fc0SSiva Chandra Reddy                     static_cast<int64_t>(SC.AddressAlignment->value()));
326*438f7fc0SSiva Chandra Reddy     JOS.attribute("MemsetValue", SC.MemsetValue);
327*438f7fc0SSiva Chandra Reddy     JOS.attribute("MemcmpMismatchAt", SC.MemcmpMismatchAt);
328*438f7fc0SSiva Chandra Reddy   });
329*438f7fc0SSiva Chandra Reddy }
330*438f7fc0SSiva Chandra Reddy 
331*438f7fc0SSiva Chandra Reddy static void Serialize(const FunctionMeasurements &FM, json::OStream &JOS) {
332*438f7fc0SSiva Chandra Reddy   JOS.object([&]() {
333*438f7fc0SSiva Chandra Reddy     JOS.attribute("Name", FM.Name);
334*438f7fc0SSiva Chandra Reddy     JOS.attributeArray("Sizes", [&]() {
335*438f7fc0SSiva Chandra Reddy       for (const auto &M : FM.Measurements)
336*438f7fc0SSiva Chandra Reddy         JOS.value(M.Size);
337*438f7fc0SSiva Chandra Reddy     });
338*438f7fc0SSiva Chandra Reddy     JOS.attributeArray("Runtimes", [&]() {
339*438f7fc0SSiva Chandra Reddy       for (const auto &M : FM.Measurements)
340*438f7fc0SSiva Chandra Reddy         JOS.value(Seconds(M.Runtime));
341*438f7fc0SSiva Chandra Reddy     });
342*438f7fc0SSiva Chandra Reddy   });
343*438f7fc0SSiva Chandra Reddy }
344*438f7fc0SSiva Chandra Reddy 
345*438f7fc0SSiva Chandra Reddy void SerializeToJson(const Study &S, json::OStream &JOS) {
346*438f7fc0SSiva Chandra Reddy   JOS.object([&]() {
347*438f7fc0SSiva Chandra Reddy     JOS.attributeBegin("Host");
348*438f7fc0SSiva Chandra Reddy     Serialize(S.Host, JOS);
349*438f7fc0SSiva Chandra Reddy     JOS.attributeEnd();
350*438f7fc0SSiva Chandra Reddy 
351*438f7fc0SSiva Chandra Reddy     JOS.attributeBegin("Options");
352*438f7fc0SSiva Chandra Reddy     Serialize(S.Options, JOS);
353*438f7fc0SSiva Chandra Reddy     JOS.attributeEnd();
354*438f7fc0SSiva Chandra Reddy 
355*438f7fc0SSiva Chandra Reddy     JOS.attributeBegin("Configuration");
356*438f7fc0SSiva Chandra Reddy     Serialize(S.Configuration, JOS);
357*438f7fc0SSiva Chandra Reddy     JOS.attributeEnd();
358*438f7fc0SSiva Chandra Reddy 
359*438f7fc0SSiva Chandra Reddy     if (!S.Functions.empty()) {
360*438f7fc0SSiva Chandra Reddy       JOS.attributeArray("Functions", [&]() {
361*438f7fc0SSiva Chandra Reddy         for (const auto &FM : S.Functions)
362*438f7fc0SSiva Chandra Reddy           Serialize(FM, JOS);
363*438f7fc0SSiva Chandra Reddy       });
364*438f7fc0SSiva Chandra Reddy     }
365*438f7fc0SSiva Chandra Reddy   });
366*438f7fc0SSiva Chandra Reddy }
367*438f7fc0SSiva Chandra Reddy 
368*438f7fc0SSiva Chandra Reddy } // namespace libc_benchmarks
369*438f7fc0SSiva Chandra Reddy } // namespace llvm
370