1438f7fc0SSiva Chandra Reddy //===-- JSON serialization routines ---------------------------------------===//
2438f7fc0SSiva Chandra Reddy //
3438f7fc0SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4438f7fc0SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5438f7fc0SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6438f7fc0SSiva Chandra Reddy //
7438f7fc0SSiva Chandra Reddy //===----------------------------------------------------------------------===//
8438f7fc0SSiva Chandra Reddy 
9438f7fc0SSiva Chandra Reddy #include "JSON.h"
10438f7fc0SSiva Chandra Reddy #include "LibcBenchmark.h"
11438f7fc0SSiva Chandra Reddy #include "llvm/ADT/DenseSet.h"
12438f7fc0SSiva Chandra Reddy #include "llvm/ADT/SmallVector.h"
13438f7fc0SSiva Chandra Reddy #include "llvm/ADT/StringRef.h"
14438f7fc0SSiva Chandra Reddy #include "llvm/ADT/StringSwitch.h"
15438f7fc0SSiva Chandra Reddy #include "llvm/Support/Errc.h"
16438f7fc0SSiva Chandra Reddy #include "llvm/Support/Error.h"
17438f7fc0SSiva Chandra Reddy #include "llvm/Support/ErrorHandling.h"
18438f7fc0SSiva Chandra Reddy #include "llvm/Support/JSON.h"
19438f7fc0SSiva Chandra Reddy #include "llvm/Support/MathExtras.h"
20438f7fc0SSiva Chandra Reddy 
21438f7fc0SSiva Chandra Reddy #include <chrono>
22438f7fc0SSiva Chandra Reddy #include <limits>
23438f7fc0SSiva Chandra Reddy #include <memory>
24438f7fc0SSiva Chandra Reddy #include <string>
25438f7fc0SSiva Chandra Reddy #include <vector>
26438f7fc0SSiva Chandra Reddy 
27438f7fc0SSiva Chandra Reddy namespace llvm {
28438f7fc0SSiva Chandra Reddy namespace libc_benchmarks {
29438f7fc0SSiva Chandra Reddy 
30438f7fc0SSiva Chandra Reddy template <typename T>
intFromJsonTemplate(const json::Value & V,T & Out)31438f7fc0SSiva Chandra Reddy static Error intFromJsonTemplate(const json::Value &V, T &Out) {
32438f7fc0SSiva Chandra Reddy   if (const auto &MaybeInt64 = V.getAsInteger()) {
33438f7fc0SSiva Chandra Reddy     int64_t Value = *MaybeInt64;
34438f7fc0SSiva Chandra Reddy     if (Value < std::numeric_limits<T>::min() ||
35438f7fc0SSiva Chandra Reddy         Value > std::numeric_limits<T>::max())
36438f7fc0SSiva Chandra Reddy       return createStringError(errc::io_error, "Out of bound Integer");
37438f7fc0SSiva Chandra Reddy     Out = Value;
38438f7fc0SSiva Chandra Reddy     return Error::success();
39438f7fc0SSiva Chandra Reddy   }
40438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error, "Can't parse Integer");
41438f7fc0SSiva Chandra Reddy }
42438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,bool & Out)43*deae7e98SGuillaume Chatelet static Error fromJson(const json::Value &V, bool &Out) {
44*deae7e98SGuillaume Chatelet   if (auto B = V.getAsBoolean()) {
45*deae7e98SGuillaume Chatelet     Out = *B;
46*deae7e98SGuillaume Chatelet     return Error::success();
47*deae7e98SGuillaume Chatelet   }
48*deae7e98SGuillaume Chatelet   return createStringError(errc::io_error, "Can't parse Boolean");
49*deae7e98SGuillaume Chatelet }
50*deae7e98SGuillaume Chatelet 
fromJson(const json::Value & V,double & Out)51438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, double &Out) {
52438f7fc0SSiva Chandra Reddy   if (auto S = V.getAsNumber()) {
53438f7fc0SSiva Chandra Reddy     Out = *S;
54438f7fc0SSiva Chandra Reddy     return Error::success();
55438f7fc0SSiva Chandra Reddy   }
56438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error, "Can't parse Double");
57438f7fc0SSiva Chandra Reddy }
58438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,std::string & Out)59438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, std::string &Out) {
60438f7fc0SSiva Chandra Reddy   if (auto S = V.getAsString()) {
61438f7fc0SSiva Chandra Reddy     Out = std::string(*S);
62438f7fc0SSiva Chandra Reddy     return Error::success();
63438f7fc0SSiva Chandra Reddy   }
64438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error, "Can't parse String");
65438f7fc0SSiva Chandra Reddy }
66438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,uint32_t & Out)67438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, uint32_t &Out) {
68438f7fc0SSiva Chandra Reddy   return intFromJsonTemplate(V, Out);
69438f7fc0SSiva Chandra Reddy }
70438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,int & Out)71438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, int &Out) {
72438f7fc0SSiva Chandra Reddy   return intFromJsonTemplate(V, Out);
73438f7fc0SSiva Chandra Reddy }
74438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::Duration & D)75438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::Duration &D) {
76438f7fc0SSiva Chandra Reddy   if (V.kind() != json::Value::Kind::Number)
77438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error, "Can't parse Duration");
78438f7fc0SSiva Chandra Reddy   D = libc_benchmarks::Duration(*V.getAsNumber());
79438f7fc0SSiva Chandra Reddy   return Error::success();
80438f7fc0SSiva Chandra Reddy }
81438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,MaybeAlign & Out)82438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, MaybeAlign &Out) {
83438f7fc0SSiva Chandra Reddy   const auto MaybeInt = V.getAsInteger();
84438f7fc0SSiva Chandra Reddy   if (!MaybeInt)
85438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
86438f7fc0SSiva Chandra Reddy                              "Can't parse Align, not an Integer");
87438f7fc0SSiva Chandra Reddy   const int64_t Value = *MaybeInt;
88438f7fc0SSiva Chandra Reddy   if (!Value) {
89438f7fc0SSiva Chandra Reddy     Out = None;
90438f7fc0SSiva Chandra Reddy     return Error::success();
91438f7fc0SSiva Chandra Reddy   }
92438f7fc0SSiva Chandra Reddy   if (isPowerOf2_64(Value)) {
93438f7fc0SSiva Chandra Reddy     Out = Align(Value);
94438f7fc0SSiva Chandra Reddy     return Error::success();
95438f7fc0SSiva Chandra Reddy   }
96438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error,
97438f7fc0SSiva Chandra Reddy                            "Can't parse Align, not a power of two");
98438f7fc0SSiva Chandra Reddy }
99438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::BenchmarkLog & Out)100438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
101438f7fc0SSiva Chandra Reddy                       libc_benchmarks::BenchmarkLog &Out) {
102438f7fc0SSiva Chandra Reddy   if (V.kind() != json::Value::Kind::String)
103438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
104438f7fc0SSiva Chandra Reddy                              "Can't parse BenchmarkLog, not a String");
105438f7fc0SSiva Chandra Reddy   const auto String = *V.getAsString();
106438f7fc0SSiva Chandra Reddy   auto Parsed =
107438f7fc0SSiva Chandra Reddy       llvm::StringSwitch<Optional<libc_benchmarks::BenchmarkLog>>(String)
108438f7fc0SSiva Chandra Reddy           .Case("None", libc_benchmarks::BenchmarkLog::None)
109438f7fc0SSiva Chandra Reddy           .Case("Last", libc_benchmarks::BenchmarkLog::Last)
110438f7fc0SSiva Chandra Reddy           .Case("Full", libc_benchmarks::BenchmarkLog::Full)
111438f7fc0SSiva Chandra Reddy           .Default(None);
112438f7fc0SSiva Chandra Reddy   if (!Parsed)
113438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
114438f7fc0SSiva Chandra Reddy                              Twine("Can't parse BenchmarkLog, invalid value '")
115438f7fc0SSiva Chandra Reddy                                  .concat(String)
116438f7fc0SSiva Chandra Reddy                                  .concat("'"));
117438f7fc0SSiva Chandra Reddy   Out = *Parsed;
118438f7fc0SSiva Chandra Reddy   return Error::success();
119438f7fc0SSiva Chandra Reddy }
120438f7fc0SSiva Chandra Reddy 
121438f7fc0SSiva Chandra Reddy template <typename C>
vectorFromJsonTemplate(const json::Value & V,C & Out)122438f7fc0SSiva Chandra Reddy Error vectorFromJsonTemplate(const json::Value &V, C &Out) {
123438f7fc0SSiva Chandra Reddy   auto *A = V.getAsArray();
124438f7fc0SSiva Chandra Reddy   if (!A)
125438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error, "Can't parse Array");
126438f7fc0SSiva Chandra Reddy   Out.clear();
127438f7fc0SSiva Chandra Reddy   Out.resize(A->size());
128438f7fc0SSiva Chandra Reddy   for (auto InOutPair : llvm::zip(*A, Out))
129438f7fc0SSiva Chandra Reddy     if (auto E = fromJson(std::get<0>(InOutPair), std::get<1>(InOutPair)))
130438f7fc0SSiva Chandra Reddy       return std::move(E);
131438f7fc0SSiva Chandra Reddy   return Error::success();
132438f7fc0SSiva Chandra Reddy }
133438f7fc0SSiva Chandra Reddy 
134438f7fc0SSiva Chandra Reddy template <typename T>
fromJson(const json::Value & V,std::vector<T> & Out)135438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, std::vector<T> &Out) {
136438f7fc0SSiva Chandra Reddy   return vectorFromJsonTemplate(V, Out);
137438f7fc0SSiva Chandra Reddy }
138438f7fc0SSiva Chandra Reddy 
139438f7fc0SSiva Chandra Reddy // Same as llvm::json::ObjectMapper but adds a finer error reporting mechanism.
140438f7fc0SSiva Chandra Reddy class JsonObjectMapper {
141438f7fc0SSiva Chandra Reddy   const json::Object *O;
142438f7fc0SSiva Chandra Reddy   Error E;
143438f7fc0SSiva Chandra Reddy   SmallDenseSet<StringRef> SeenFields;
144438f7fc0SSiva Chandra Reddy 
145438f7fc0SSiva Chandra Reddy public:
JsonObjectMapper(const json::Value & V)146438f7fc0SSiva Chandra Reddy   explicit JsonObjectMapper(const json::Value &V)
147438f7fc0SSiva Chandra Reddy       : O(V.getAsObject()),
148438f7fc0SSiva Chandra Reddy         E(O ? Error::success()
149438f7fc0SSiva Chandra Reddy             : createStringError(errc::io_error, "Expected JSON Object")) {}
150438f7fc0SSiva Chandra Reddy 
takeError()151438f7fc0SSiva Chandra Reddy   Error takeError() {
152438f7fc0SSiva Chandra Reddy     if (E)
153438f7fc0SSiva Chandra Reddy       return std::move(E);
154438f7fc0SSiva Chandra Reddy     for (const auto &Itr : *O) {
155438f7fc0SSiva Chandra Reddy       const StringRef Key = Itr.getFirst();
156438f7fc0SSiva Chandra Reddy       if (!SeenFields.count(Key))
157438f7fc0SSiva Chandra Reddy         E = createStringError(errc::io_error,
158438f7fc0SSiva Chandra Reddy                               Twine("Unknown field: ").concat(Key));
159438f7fc0SSiva Chandra Reddy     }
160438f7fc0SSiva Chandra Reddy     return std::move(E);
161438f7fc0SSiva Chandra Reddy   }
162438f7fc0SSiva Chandra Reddy 
map(StringRef Key,T & Out)163438f7fc0SSiva Chandra Reddy   template <typename T> void map(StringRef Key, T &Out) {
164438f7fc0SSiva Chandra Reddy     if (E)
165438f7fc0SSiva Chandra Reddy       return;
166438f7fc0SSiva Chandra Reddy     if (const json::Value *Value = O->get(Key)) {
167438f7fc0SSiva Chandra Reddy       SeenFields.insert(Key);
168438f7fc0SSiva Chandra Reddy       E = fromJson(*Value, Out);
169438f7fc0SSiva Chandra Reddy     }
170438f7fc0SSiva Chandra Reddy   }
171438f7fc0SSiva Chandra Reddy };
172438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::BenchmarkOptions & Out)173438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
174438f7fc0SSiva Chandra Reddy                       libc_benchmarks::BenchmarkOptions &Out) {
175438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
176438f7fc0SSiva Chandra Reddy   O.map("MinDuration", Out.MinDuration);
177438f7fc0SSiva Chandra Reddy   O.map("MaxDuration", Out.MaxDuration);
178438f7fc0SSiva Chandra Reddy   O.map("InitialIterations", Out.InitialIterations);
179438f7fc0SSiva Chandra Reddy   O.map("MaxIterations", Out.MaxIterations);
180438f7fc0SSiva Chandra Reddy   O.map("MinSamples", Out.MinSamples);
181438f7fc0SSiva Chandra Reddy   O.map("MaxSamples", Out.MaxSamples);
182438f7fc0SSiva Chandra Reddy   O.map("Epsilon", Out.Epsilon);
183438f7fc0SSiva Chandra Reddy   O.map("ScalingFactor", Out.ScalingFactor);
184438f7fc0SSiva Chandra Reddy   O.map("Log", Out.Log);
185438f7fc0SSiva Chandra Reddy   return O.takeError();
186438f7fc0SSiva Chandra Reddy }
187438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::StudyConfiguration & Out)188438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
189438f7fc0SSiva Chandra Reddy                       libc_benchmarks::StudyConfiguration &Out) {
190438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
191*deae7e98SGuillaume Chatelet   O.map("Function", Out.Function);
192*deae7e98SGuillaume Chatelet   O.map("NumTrials", Out.NumTrials);
193*deae7e98SGuillaume Chatelet   O.map("IsSweepMode", Out.IsSweepMode);
194*deae7e98SGuillaume Chatelet   O.map("SweepModeMaxSize", Out.SweepModeMaxSize);
195*deae7e98SGuillaume Chatelet   O.map("SizeDistributionName", Out.SizeDistributionName);
196*deae7e98SGuillaume Chatelet   O.map("AccessAlignment", Out.AccessAlignment);
197438f7fc0SSiva Chandra Reddy   O.map("MemcmpMismatchAt", Out.MemcmpMismatchAt);
198438f7fc0SSiva Chandra Reddy   return O.takeError();
199438f7fc0SSiva Chandra Reddy }
200438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::CacheInfo & Out)201438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::CacheInfo &Out) {
202438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
203438f7fc0SSiva Chandra Reddy   O.map("Type", Out.Type);
204438f7fc0SSiva Chandra Reddy   O.map("Level", Out.Level);
205438f7fc0SSiva Chandra Reddy   O.map("Size", Out.Size);
206438f7fc0SSiva Chandra Reddy   O.map("NumSharing", Out.NumSharing);
207438f7fc0SSiva Chandra Reddy   return O.takeError();
208438f7fc0SSiva Chandra Reddy }
209438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::HostState & Out)210438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::HostState &Out) {
211438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
212438f7fc0SSiva Chandra Reddy   O.map("CpuName", Out.CpuName);
213438f7fc0SSiva Chandra Reddy   O.map("CpuFrequency", Out.CpuFrequency);
214438f7fc0SSiva Chandra Reddy   O.map("Caches", Out.Caches);
215438f7fc0SSiva Chandra Reddy   return O.takeError();
216438f7fc0SSiva Chandra Reddy }
217438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::Runtime & Out)218*deae7e98SGuillaume Chatelet static Error fromJson(const json::Value &V, libc_benchmarks::Runtime &Out) {
219438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
220*deae7e98SGuillaume Chatelet   O.map("Host", Out.Host);
221*deae7e98SGuillaume Chatelet   O.map("BufferSize", Out.BufferSize);
222*deae7e98SGuillaume Chatelet   O.map("BatchParameterCount", Out.BatchParameterCount);
223*deae7e98SGuillaume Chatelet   O.map("BenchmarkOptions", Out.BenchmarkOptions);
224438f7fc0SSiva Chandra Reddy   return O.takeError();
225438f7fc0SSiva Chandra Reddy }
226438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::Study & Out)227438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::Study &Out) {
228438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
229*deae7e98SGuillaume Chatelet   O.map("StudyName", Out.StudyName);
230*deae7e98SGuillaume Chatelet   O.map("Runtime", Out.Runtime);
231438f7fc0SSiva Chandra Reddy   O.map("Configuration", Out.Configuration);
232*deae7e98SGuillaume Chatelet   O.map("Measurements", Out.Measurements);
233438f7fc0SSiva Chandra Reddy   return O.takeError();
234438f7fc0SSiva Chandra Reddy }
235438f7fc0SSiva Chandra Reddy 
seconds(const Duration & D)236*deae7e98SGuillaume Chatelet static double seconds(const Duration &D) {
237438f7fc0SSiva Chandra Reddy   return std::chrono::duration<double>(D).count();
238438f7fc0SSiva Chandra Reddy }
239438f7fc0SSiva Chandra Reddy 
parseJsonStudy(StringRef Content)240*deae7e98SGuillaume Chatelet Expected<Study> parseJsonStudy(StringRef Content) {
241438f7fc0SSiva Chandra Reddy   Expected<json::Value> EV = json::parse(Content);
242438f7fc0SSiva Chandra Reddy   if (!EV)
243438f7fc0SSiva Chandra Reddy     return EV.takeError();
244438f7fc0SSiva Chandra Reddy   Study S;
245438f7fc0SSiva Chandra Reddy   if (Error E = fromJson(*EV, S))
246438f7fc0SSiva Chandra Reddy     return std::move(E);
247438f7fc0SSiva Chandra Reddy   return S;
248438f7fc0SSiva Chandra Reddy }
249438f7fc0SSiva Chandra Reddy 
serialize(const BenchmarkLog & L)250*deae7e98SGuillaume Chatelet static StringRef serialize(const BenchmarkLog &L) {
251438f7fc0SSiva Chandra Reddy   switch (L) {
252438f7fc0SSiva Chandra Reddy   case BenchmarkLog::None:
253438f7fc0SSiva Chandra Reddy     return "None";
254438f7fc0SSiva Chandra Reddy   case BenchmarkLog::Last:
255438f7fc0SSiva Chandra Reddy     return "Last";
256438f7fc0SSiva Chandra Reddy   case BenchmarkLog::Full:
257438f7fc0SSiva Chandra Reddy     return "Full";
258438f7fc0SSiva Chandra Reddy   }
259438f7fc0SSiva Chandra Reddy   llvm_unreachable("Unhandled BenchmarkLog value");
260438f7fc0SSiva Chandra Reddy }
261438f7fc0SSiva Chandra Reddy 
serialize(const BenchmarkOptions & BO,json::OStream & JOS)262*deae7e98SGuillaume Chatelet static void serialize(const BenchmarkOptions &BO, json::OStream &JOS) {
263*deae7e98SGuillaume Chatelet   JOS.attribute("MinDuration", seconds(BO.MinDuration));
264*deae7e98SGuillaume Chatelet   JOS.attribute("MaxDuration", seconds(BO.MaxDuration));
265438f7fc0SSiva Chandra Reddy   JOS.attribute("InitialIterations", BO.InitialIterations);
266438f7fc0SSiva Chandra Reddy   JOS.attribute("MaxIterations", BO.MaxIterations);
267438f7fc0SSiva Chandra Reddy   JOS.attribute("MinSamples", BO.MinSamples);
268438f7fc0SSiva Chandra Reddy   JOS.attribute("MaxSamples", BO.MaxSamples);
269438f7fc0SSiva Chandra Reddy   JOS.attribute("Epsilon", BO.Epsilon);
270438f7fc0SSiva Chandra Reddy   JOS.attribute("ScalingFactor", BO.ScalingFactor);
271*deae7e98SGuillaume Chatelet   JOS.attribute("Log", serialize(BO.Log));
272438f7fc0SSiva Chandra Reddy }
273438f7fc0SSiva Chandra Reddy 
serialize(const CacheInfo & CI,json::OStream & JOS)274*deae7e98SGuillaume Chatelet static void serialize(const CacheInfo &CI, json::OStream &JOS) {
275438f7fc0SSiva Chandra Reddy   JOS.attribute("Type", CI.Type);
276438f7fc0SSiva Chandra Reddy   JOS.attribute("Level", CI.Level);
277438f7fc0SSiva Chandra Reddy   JOS.attribute("Size", CI.Size);
278438f7fc0SSiva Chandra Reddy   JOS.attribute("NumSharing", CI.NumSharing);
279438f7fc0SSiva Chandra Reddy }
280438f7fc0SSiva Chandra Reddy 
serialize(const StudyConfiguration & SC,json::OStream & JOS)281*deae7e98SGuillaume Chatelet static void serialize(const StudyConfiguration &SC, json::OStream &JOS) {
282*deae7e98SGuillaume Chatelet   JOS.attribute("Function", SC.Function);
283*deae7e98SGuillaume Chatelet   JOS.attribute("NumTrials", SC.NumTrials);
284*deae7e98SGuillaume Chatelet   JOS.attribute("IsSweepMode", SC.IsSweepMode);
285*deae7e98SGuillaume Chatelet   JOS.attribute("SweepModeMaxSize", SC.SweepModeMaxSize);
286*deae7e98SGuillaume Chatelet   JOS.attribute("SizeDistributionName", SC.SizeDistributionName);
287*deae7e98SGuillaume Chatelet   JOS.attribute("AccessAlignment",
288*deae7e98SGuillaume Chatelet                 static_cast<int64_t>(SC.AccessAlignment->value()));
289*deae7e98SGuillaume Chatelet   JOS.attribute("MemcmpMismatchAt", SC.MemcmpMismatchAt);
290*deae7e98SGuillaume Chatelet }
291*deae7e98SGuillaume Chatelet 
serialize(const HostState & HS,json::OStream & JOS)292*deae7e98SGuillaume Chatelet static void serialize(const HostState &HS, json::OStream &JOS) {
293438f7fc0SSiva Chandra Reddy   JOS.attribute("CpuName", HS.CpuName);
294438f7fc0SSiva Chandra Reddy   JOS.attribute("CpuFrequency", HS.CpuFrequency);
295438f7fc0SSiva Chandra Reddy   JOS.attributeArray("Caches", [&]() {
296438f7fc0SSiva Chandra Reddy     for (const auto &CI : HS.Caches)
297*deae7e98SGuillaume Chatelet       JOS.object([&]() { serialize(CI, JOS); });
298438f7fc0SSiva Chandra Reddy   });
299438f7fc0SSiva Chandra Reddy }
300438f7fc0SSiva Chandra Reddy 
serialize(const Runtime & RI,json::OStream & JOS)301*deae7e98SGuillaume Chatelet static void serialize(const Runtime &RI, json::OStream &JOS) {
302*deae7e98SGuillaume Chatelet   JOS.attributeObject("Host", [&]() { serialize(RI.Host, JOS); });
303*deae7e98SGuillaume Chatelet   JOS.attribute("BufferSize", RI.BufferSize);
304*deae7e98SGuillaume Chatelet   JOS.attribute("BatchParameterCount", RI.BatchParameterCount);
305*deae7e98SGuillaume Chatelet   JOS.attributeObject("BenchmarkOptions",
306*deae7e98SGuillaume Chatelet                       [&]() { serialize(RI.BenchmarkOptions, JOS); });
307438f7fc0SSiva Chandra Reddy }
308438f7fc0SSiva Chandra Reddy 
serializeToJson(const Study & S,json::OStream & JOS)309*deae7e98SGuillaume Chatelet void serializeToJson(const Study &S, json::OStream &JOS) {
310438f7fc0SSiva Chandra Reddy   JOS.object([&]() {
311*deae7e98SGuillaume Chatelet     JOS.attribute("StudyName", S.StudyName);
312*deae7e98SGuillaume Chatelet     JOS.attributeObject("Runtime", [&]() { serialize(S.Runtime, JOS); });
313*deae7e98SGuillaume Chatelet     JOS.attributeObject("Configuration",
314*deae7e98SGuillaume Chatelet                         [&]() { serialize(S.Configuration, JOS); });
315*deae7e98SGuillaume Chatelet     if (!S.Measurements.empty()) {
316*deae7e98SGuillaume Chatelet       JOS.attributeArray("Measurements", [&]() {
317*deae7e98SGuillaume Chatelet         for (const auto &M : S.Measurements)
318*deae7e98SGuillaume Chatelet           JOS.value(seconds(M));
319438f7fc0SSiva Chandra Reddy       });
320438f7fc0SSiva Chandra Reddy     }
321438f7fc0SSiva Chandra Reddy   });
322438f7fc0SSiva Chandra Reddy }
323438f7fc0SSiva Chandra Reddy 
324438f7fc0SSiva Chandra Reddy } // namespace libc_benchmarks
325438f7fc0SSiva Chandra Reddy } // namespace llvm
326