xref: /llvm-project/libc/benchmarks/JSON.cpp (revision 660c33e51de20b5a414b029a6dbae8a33aefabd4)
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>
248dcb7f6bSSiva Chandra Reddy #include <optional>
25438f7fc0SSiva Chandra Reddy #include <string>
26438f7fc0SSiva Chandra Reddy #include <vector>
27438f7fc0SSiva Chandra Reddy 
28438f7fc0SSiva Chandra Reddy namespace llvm {
29438f7fc0SSiva Chandra Reddy namespace libc_benchmarks {
30438f7fc0SSiva Chandra Reddy 
31438f7fc0SSiva Chandra Reddy template <typename T>
intFromJsonTemplate(const json::Value & V,T & Out)32438f7fc0SSiva Chandra Reddy static Error intFromJsonTemplate(const json::Value &V, T &Out) {
33438f7fc0SSiva Chandra Reddy   if (const auto &MaybeInt64 = V.getAsInteger()) {
34438f7fc0SSiva Chandra Reddy     int64_t Value = *MaybeInt64;
35438f7fc0SSiva Chandra Reddy     if (Value < std::numeric_limits<T>::min() ||
36438f7fc0SSiva Chandra Reddy         Value > std::numeric_limits<T>::max())
37438f7fc0SSiva Chandra Reddy       return createStringError(errc::io_error, "Out of bound Integer");
38438f7fc0SSiva Chandra Reddy     Out = Value;
39438f7fc0SSiva Chandra Reddy     return Error::success();
40438f7fc0SSiva Chandra Reddy   }
41438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error, "Can't parse Integer");
42438f7fc0SSiva Chandra Reddy }
43438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,bool & Out)44deae7e98SGuillaume Chatelet static Error fromJson(const json::Value &V, bool &Out) {
45deae7e98SGuillaume Chatelet   if (auto B = V.getAsBoolean()) {
46deae7e98SGuillaume Chatelet     Out = *B;
47deae7e98SGuillaume Chatelet     return Error::success();
48deae7e98SGuillaume Chatelet   }
49deae7e98SGuillaume Chatelet   return createStringError(errc::io_error, "Can't parse Boolean");
50deae7e98SGuillaume Chatelet }
51deae7e98SGuillaume Chatelet 
fromJson(const json::Value & V,double & Out)52438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, double &Out) {
53438f7fc0SSiva Chandra Reddy   if (auto S = V.getAsNumber()) {
54438f7fc0SSiva Chandra Reddy     Out = *S;
55438f7fc0SSiva Chandra Reddy     return Error::success();
56438f7fc0SSiva Chandra Reddy   }
57438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error, "Can't parse Double");
58438f7fc0SSiva Chandra Reddy }
59438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,std::string & Out)60438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, std::string &Out) {
61438f7fc0SSiva Chandra Reddy   if (auto S = V.getAsString()) {
62438f7fc0SSiva Chandra Reddy     Out = std::string(*S);
63438f7fc0SSiva Chandra Reddy     return Error::success();
64438f7fc0SSiva Chandra Reddy   }
65438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error, "Can't parse String");
66438f7fc0SSiva Chandra Reddy }
67438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,uint32_t & Out)68438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, uint32_t &Out) {
69438f7fc0SSiva Chandra Reddy   return intFromJsonTemplate(V, Out);
70438f7fc0SSiva Chandra Reddy }
71438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,int & Out)72438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, int &Out) {
73438f7fc0SSiva Chandra Reddy   return intFromJsonTemplate(V, Out);
74438f7fc0SSiva Chandra Reddy }
75438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::Duration & D)76438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::Duration &D) {
77438f7fc0SSiva Chandra Reddy   if (V.kind() != json::Value::Kind::Number)
78438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error, "Can't parse Duration");
79438f7fc0SSiva Chandra Reddy   D = libc_benchmarks::Duration(*V.getAsNumber());
80438f7fc0SSiva Chandra Reddy   return Error::success();
81438f7fc0SSiva Chandra Reddy }
82438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,MaybeAlign & Out)83438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, MaybeAlign &Out) {
84438f7fc0SSiva Chandra Reddy   const auto MaybeInt = V.getAsInteger();
85438f7fc0SSiva Chandra Reddy   if (!MaybeInt)
86438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
87438f7fc0SSiva Chandra Reddy                              "Can't parse Align, not an Integer");
88438f7fc0SSiva Chandra Reddy   const int64_t Value = *MaybeInt;
89438f7fc0SSiva Chandra Reddy   if (!Value) {
908dcb7f6bSSiva Chandra Reddy     Out = std::nullopt;
91438f7fc0SSiva Chandra Reddy     return Error::success();
92438f7fc0SSiva Chandra Reddy   }
93438f7fc0SSiva Chandra Reddy   if (isPowerOf2_64(Value)) {
94438f7fc0SSiva Chandra Reddy     Out = Align(Value);
95438f7fc0SSiva Chandra Reddy     return Error::success();
96438f7fc0SSiva Chandra Reddy   }
97438f7fc0SSiva Chandra Reddy   return createStringError(errc::io_error,
98438f7fc0SSiva Chandra Reddy                            "Can't parse Align, not a power of two");
99438f7fc0SSiva Chandra Reddy }
100438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::BenchmarkLog & Out)101438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
102438f7fc0SSiva Chandra Reddy                       libc_benchmarks::BenchmarkLog &Out) {
103438f7fc0SSiva Chandra Reddy   if (V.kind() != json::Value::Kind::String)
104438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
105438f7fc0SSiva Chandra Reddy                              "Can't parse BenchmarkLog, not a String");
106438f7fc0SSiva Chandra Reddy   const auto String = *V.getAsString();
107438f7fc0SSiva Chandra Reddy   auto Parsed =
108*660c33e5SKazu Hirata       llvm::StringSwitch<std::optional<libc_benchmarks::BenchmarkLog>>(String)
109438f7fc0SSiva Chandra Reddy           .Case("None", libc_benchmarks::BenchmarkLog::None)
110438f7fc0SSiva Chandra Reddy           .Case("Last", libc_benchmarks::BenchmarkLog::Last)
111438f7fc0SSiva Chandra Reddy           .Case("Full", libc_benchmarks::BenchmarkLog::Full)
1128dcb7f6bSSiva Chandra Reddy           .Default(std::nullopt);
113438f7fc0SSiva Chandra Reddy   if (!Parsed)
114438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error,
115438f7fc0SSiva Chandra Reddy                              Twine("Can't parse BenchmarkLog, invalid value '")
116438f7fc0SSiva Chandra Reddy                                  .concat(String)
117438f7fc0SSiva Chandra Reddy                                  .concat("'"));
118438f7fc0SSiva Chandra Reddy   Out = *Parsed;
119438f7fc0SSiva Chandra Reddy   return Error::success();
120438f7fc0SSiva Chandra Reddy }
121438f7fc0SSiva Chandra Reddy 
122438f7fc0SSiva Chandra Reddy template <typename C>
vectorFromJsonTemplate(const json::Value & V,C & Out)123438f7fc0SSiva Chandra Reddy Error vectorFromJsonTemplate(const json::Value &V, C &Out) {
124438f7fc0SSiva Chandra Reddy   auto *A = V.getAsArray();
125438f7fc0SSiva Chandra Reddy   if (!A)
126438f7fc0SSiva Chandra Reddy     return createStringError(errc::io_error, "Can't parse Array");
127438f7fc0SSiva Chandra Reddy   Out.clear();
128438f7fc0SSiva Chandra Reddy   Out.resize(A->size());
129438f7fc0SSiva Chandra Reddy   for (auto InOutPair : llvm::zip(*A, Out))
130438f7fc0SSiva Chandra Reddy     if (auto E = fromJson(std::get<0>(InOutPair), std::get<1>(InOutPair)))
131438f7fc0SSiva Chandra Reddy       return std::move(E);
132438f7fc0SSiva Chandra Reddy   return Error::success();
133438f7fc0SSiva Chandra Reddy }
134438f7fc0SSiva Chandra Reddy 
135438f7fc0SSiva Chandra Reddy template <typename T>
fromJson(const json::Value & V,std::vector<T> & Out)136438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, std::vector<T> &Out) {
137438f7fc0SSiva Chandra Reddy   return vectorFromJsonTemplate(V, Out);
138438f7fc0SSiva Chandra Reddy }
139438f7fc0SSiva Chandra Reddy 
140438f7fc0SSiva Chandra Reddy // Same as llvm::json::ObjectMapper but adds a finer error reporting mechanism.
141438f7fc0SSiva Chandra Reddy class JsonObjectMapper {
142438f7fc0SSiva Chandra Reddy   const json::Object *O;
143438f7fc0SSiva Chandra Reddy   Error E;
144438f7fc0SSiva Chandra Reddy   SmallDenseSet<StringRef> SeenFields;
145438f7fc0SSiva Chandra Reddy 
146438f7fc0SSiva Chandra Reddy public:
JsonObjectMapper(const json::Value & V)147438f7fc0SSiva Chandra Reddy   explicit JsonObjectMapper(const json::Value &V)
148438f7fc0SSiva Chandra Reddy       : O(V.getAsObject()),
149438f7fc0SSiva Chandra Reddy         E(O ? Error::success()
150438f7fc0SSiva Chandra Reddy             : createStringError(errc::io_error, "Expected JSON Object")) {}
151438f7fc0SSiva Chandra Reddy 
takeError()152438f7fc0SSiva Chandra Reddy   Error takeError() {
153438f7fc0SSiva Chandra Reddy     if (E)
154438f7fc0SSiva Chandra Reddy       return std::move(E);
155438f7fc0SSiva Chandra Reddy     for (const auto &Itr : *O) {
156438f7fc0SSiva Chandra Reddy       const StringRef Key = Itr.getFirst();
157438f7fc0SSiva Chandra Reddy       if (!SeenFields.count(Key))
158438f7fc0SSiva Chandra Reddy         E = createStringError(errc::io_error,
159438f7fc0SSiva Chandra Reddy                               Twine("Unknown field: ").concat(Key));
160438f7fc0SSiva Chandra Reddy     }
161438f7fc0SSiva Chandra Reddy     return std::move(E);
162438f7fc0SSiva Chandra Reddy   }
163438f7fc0SSiva Chandra Reddy 
map(StringRef Key,T & Out)164438f7fc0SSiva Chandra Reddy   template <typename T> void map(StringRef Key, T &Out) {
165438f7fc0SSiva Chandra Reddy     if (E)
166438f7fc0SSiva Chandra Reddy       return;
167438f7fc0SSiva Chandra Reddy     if (const json::Value *Value = O->get(Key)) {
168438f7fc0SSiva Chandra Reddy       SeenFields.insert(Key);
169438f7fc0SSiva Chandra Reddy       E = fromJson(*Value, Out);
170438f7fc0SSiva Chandra Reddy     }
171438f7fc0SSiva Chandra Reddy   }
172438f7fc0SSiva Chandra Reddy };
173438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::BenchmarkOptions & Out)174438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
175438f7fc0SSiva Chandra Reddy                       libc_benchmarks::BenchmarkOptions &Out) {
176438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
177438f7fc0SSiva Chandra Reddy   O.map("MinDuration", Out.MinDuration);
178438f7fc0SSiva Chandra Reddy   O.map("MaxDuration", Out.MaxDuration);
179438f7fc0SSiva Chandra Reddy   O.map("InitialIterations", Out.InitialIterations);
180438f7fc0SSiva Chandra Reddy   O.map("MaxIterations", Out.MaxIterations);
181438f7fc0SSiva Chandra Reddy   O.map("MinSamples", Out.MinSamples);
182438f7fc0SSiva Chandra Reddy   O.map("MaxSamples", Out.MaxSamples);
183438f7fc0SSiva Chandra Reddy   O.map("Epsilon", Out.Epsilon);
184438f7fc0SSiva Chandra Reddy   O.map("ScalingFactor", Out.ScalingFactor);
185438f7fc0SSiva Chandra Reddy   O.map("Log", Out.Log);
186438f7fc0SSiva Chandra Reddy   return O.takeError();
187438f7fc0SSiva Chandra Reddy }
188438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::StudyConfiguration & Out)189438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V,
190438f7fc0SSiva Chandra Reddy                       libc_benchmarks::StudyConfiguration &Out) {
191438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
192deae7e98SGuillaume Chatelet   O.map("Function", Out.Function);
193deae7e98SGuillaume Chatelet   O.map("NumTrials", Out.NumTrials);
194deae7e98SGuillaume Chatelet   O.map("IsSweepMode", Out.IsSweepMode);
195deae7e98SGuillaume Chatelet   O.map("SweepModeMaxSize", Out.SweepModeMaxSize);
196deae7e98SGuillaume Chatelet   O.map("SizeDistributionName", Out.SizeDistributionName);
197deae7e98SGuillaume Chatelet   O.map("AccessAlignment", Out.AccessAlignment);
198438f7fc0SSiva Chandra Reddy   O.map("MemcmpMismatchAt", Out.MemcmpMismatchAt);
199438f7fc0SSiva Chandra Reddy   return O.takeError();
200438f7fc0SSiva Chandra Reddy }
201438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::CacheInfo & Out)202438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::CacheInfo &Out) {
203438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
204438f7fc0SSiva Chandra Reddy   O.map("Type", Out.Type);
205438f7fc0SSiva Chandra Reddy   O.map("Level", Out.Level);
206438f7fc0SSiva Chandra Reddy   O.map("Size", Out.Size);
207438f7fc0SSiva Chandra Reddy   O.map("NumSharing", Out.NumSharing);
208438f7fc0SSiva Chandra Reddy   return O.takeError();
209438f7fc0SSiva Chandra Reddy }
210438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::HostState & Out)211438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::HostState &Out) {
212438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
213438f7fc0SSiva Chandra Reddy   O.map("CpuName", Out.CpuName);
214438f7fc0SSiva Chandra Reddy   O.map("CpuFrequency", Out.CpuFrequency);
215438f7fc0SSiva Chandra Reddy   O.map("Caches", Out.Caches);
216438f7fc0SSiva Chandra Reddy   return O.takeError();
217438f7fc0SSiva Chandra Reddy }
218438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::Runtime & Out)219deae7e98SGuillaume Chatelet static Error fromJson(const json::Value &V, libc_benchmarks::Runtime &Out) {
220438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
221deae7e98SGuillaume Chatelet   O.map("Host", Out.Host);
222deae7e98SGuillaume Chatelet   O.map("BufferSize", Out.BufferSize);
223deae7e98SGuillaume Chatelet   O.map("BatchParameterCount", Out.BatchParameterCount);
224deae7e98SGuillaume Chatelet   O.map("BenchmarkOptions", Out.BenchmarkOptions);
225438f7fc0SSiva Chandra Reddy   return O.takeError();
226438f7fc0SSiva Chandra Reddy }
227438f7fc0SSiva Chandra Reddy 
fromJson(const json::Value & V,libc_benchmarks::Study & Out)228438f7fc0SSiva Chandra Reddy static Error fromJson(const json::Value &V, libc_benchmarks::Study &Out) {
229438f7fc0SSiva Chandra Reddy   JsonObjectMapper O(V);
230deae7e98SGuillaume Chatelet   O.map("StudyName", Out.StudyName);
231deae7e98SGuillaume Chatelet   O.map("Runtime", Out.Runtime);
232438f7fc0SSiva Chandra Reddy   O.map("Configuration", Out.Configuration);
233deae7e98SGuillaume Chatelet   O.map("Measurements", Out.Measurements);
234438f7fc0SSiva Chandra Reddy   return O.takeError();
235438f7fc0SSiva Chandra Reddy }
236438f7fc0SSiva Chandra Reddy 
seconds(const Duration & D)237deae7e98SGuillaume Chatelet static double seconds(const Duration &D) {
238438f7fc0SSiva Chandra Reddy   return std::chrono::duration<double>(D).count();
239438f7fc0SSiva Chandra Reddy }
240438f7fc0SSiva Chandra Reddy 
parseJsonStudy(StringRef Content)241deae7e98SGuillaume Chatelet Expected<Study> parseJsonStudy(StringRef Content) {
242438f7fc0SSiva Chandra Reddy   Expected<json::Value> EV = json::parse(Content);
243438f7fc0SSiva Chandra Reddy   if (!EV)
244438f7fc0SSiva Chandra Reddy     return EV.takeError();
245438f7fc0SSiva Chandra Reddy   Study S;
246438f7fc0SSiva Chandra Reddy   if (Error E = fromJson(*EV, S))
247438f7fc0SSiva Chandra Reddy     return std::move(E);
248438f7fc0SSiva Chandra Reddy   return S;
249438f7fc0SSiva Chandra Reddy }
250438f7fc0SSiva Chandra Reddy 
serialize(const BenchmarkLog & L)251deae7e98SGuillaume Chatelet static StringRef serialize(const BenchmarkLog &L) {
252438f7fc0SSiva Chandra Reddy   switch (L) {
253438f7fc0SSiva Chandra Reddy   case BenchmarkLog::None:
254438f7fc0SSiva Chandra Reddy     return "None";
255438f7fc0SSiva Chandra Reddy   case BenchmarkLog::Last:
256438f7fc0SSiva Chandra Reddy     return "Last";
257438f7fc0SSiva Chandra Reddy   case BenchmarkLog::Full:
258438f7fc0SSiva Chandra Reddy     return "Full";
259438f7fc0SSiva Chandra Reddy   }
260438f7fc0SSiva Chandra Reddy   llvm_unreachable("Unhandled BenchmarkLog value");
261438f7fc0SSiva Chandra Reddy }
262438f7fc0SSiva Chandra Reddy 
serialize(const BenchmarkOptions & BO,json::OStream & JOS)263deae7e98SGuillaume Chatelet static void serialize(const BenchmarkOptions &BO, json::OStream &JOS) {
264deae7e98SGuillaume Chatelet   JOS.attribute("MinDuration", seconds(BO.MinDuration));
265deae7e98SGuillaume Chatelet   JOS.attribute("MaxDuration", seconds(BO.MaxDuration));
266438f7fc0SSiva Chandra Reddy   JOS.attribute("InitialIterations", BO.InitialIterations);
267438f7fc0SSiva Chandra Reddy   JOS.attribute("MaxIterations", BO.MaxIterations);
268438f7fc0SSiva Chandra Reddy   JOS.attribute("MinSamples", BO.MinSamples);
269438f7fc0SSiva Chandra Reddy   JOS.attribute("MaxSamples", BO.MaxSamples);
270438f7fc0SSiva Chandra Reddy   JOS.attribute("Epsilon", BO.Epsilon);
271438f7fc0SSiva Chandra Reddy   JOS.attribute("ScalingFactor", BO.ScalingFactor);
272deae7e98SGuillaume Chatelet   JOS.attribute("Log", serialize(BO.Log));
273438f7fc0SSiva Chandra Reddy }
274438f7fc0SSiva Chandra Reddy 
serialize(const CacheInfo & CI,json::OStream & JOS)275deae7e98SGuillaume Chatelet static void serialize(const CacheInfo &CI, json::OStream &JOS) {
276438f7fc0SSiva Chandra Reddy   JOS.attribute("Type", CI.Type);
277438f7fc0SSiva Chandra Reddy   JOS.attribute("Level", CI.Level);
278438f7fc0SSiva Chandra Reddy   JOS.attribute("Size", CI.Size);
279438f7fc0SSiva Chandra Reddy   JOS.attribute("NumSharing", CI.NumSharing);
280438f7fc0SSiva Chandra Reddy }
281438f7fc0SSiva Chandra Reddy 
serialize(const StudyConfiguration & SC,json::OStream & JOS)282deae7e98SGuillaume Chatelet static void serialize(const StudyConfiguration &SC, json::OStream &JOS) {
283deae7e98SGuillaume Chatelet   JOS.attribute("Function", SC.Function);
284deae7e98SGuillaume Chatelet   JOS.attribute("NumTrials", SC.NumTrials);
285deae7e98SGuillaume Chatelet   JOS.attribute("IsSweepMode", SC.IsSweepMode);
286deae7e98SGuillaume Chatelet   JOS.attribute("SweepModeMaxSize", SC.SweepModeMaxSize);
287deae7e98SGuillaume Chatelet   JOS.attribute("SizeDistributionName", SC.SizeDistributionName);
288deae7e98SGuillaume Chatelet   JOS.attribute("AccessAlignment",
289deae7e98SGuillaume Chatelet                 static_cast<int64_t>(SC.AccessAlignment->value()));
290deae7e98SGuillaume Chatelet   JOS.attribute("MemcmpMismatchAt", SC.MemcmpMismatchAt);
291deae7e98SGuillaume Chatelet }
292deae7e98SGuillaume Chatelet 
serialize(const HostState & HS,json::OStream & JOS)293deae7e98SGuillaume Chatelet static void serialize(const HostState &HS, json::OStream &JOS) {
294438f7fc0SSiva Chandra Reddy   JOS.attribute("CpuName", HS.CpuName);
295438f7fc0SSiva Chandra Reddy   JOS.attribute("CpuFrequency", HS.CpuFrequency);
296438f7fc0SSiva Chandra Reddy   JOS.attributeArray("Caches", [&]() {
297438f7fc0SSiva Chandra Reddy     for (const auto &CI : HS.Caches)
298deae7e98SGuillaume Chatelet       JOS.object([&]() { serialize(CI, JOS); });
299438f7fc0SSiva Chandra Reddy   });
300438f7fc0SSiva Chandra Reddy }
301438f7fc0SSiva Chandra Reddy 
serialize(const Runtime & RI,json::OStream & JOS)302deae7e98SGuillaume Chatelet static void serialize(const Runtime &RI, json::OStream &JOS) {
303deae7e98SGuillaume Chatelet   JOS.attributeObject("Host", [&]() { serialize(RI.Host, JOS); });
304deae7e98SGuillaume Chatelet   JOS.attribute("BufferSize", RI.BufferSize);
305deae7e98SGuillaume Chatelet   JOS.attribute("BatchParameterCount", RI.BatchParameterCount);
306deae7e98SGuillaume Chatelet   JOS.attributeObject("BenchmarkOptions",
307deae7e98SGuillaume Chatelet                       [&]() { serialize(RI.BenchmarkOptions, JOS); });
308438f7fc0SSiva Chandra Reddy }
309438f7fc0SSiva Chandra Reddy 
serializeToJson(const Study & S,json::OStream & JOS)310deae7e98SGuillaume Chatelet void serializeToJson(const Study &S, json::OStream &JOS) {
311438f7fc0SSiva Chandra Reddy   JOS.object([&]() {
312deae7e98SGuillaume Chatelet     JOS.attribute("StudyName", S.StudyName);
313deae7e98SGuillaume Chatelet     JOS.attributeObject("Runtime", [&]() { serialize(S.Runtime, JOS); });
314deae7e98SGuillaume Chatelet     JOS.attributeObject("Configuration",
315deae7e98SGuillaume Chatelet                         [&]() { serialize(S.Configuration, JOS); });
316deae7e98SGuillaume Chatelet     if (!S.Measurements.empty()) {
317deae7e98SGuillaume Chatelet       JOS.attributeArray("Measurements", [&]() {
318deae7e98SGuillaume Chatelet         for (const auto &M : S.Measurements)
319deae7e98SGuillaume Chatelet           JOS.value(seconds(M));
320438f7fc0SSiva Chandra Reddy       });
321438f7fc0SSiva Chandra Reddy     }
322438f7fc0SSiva Chandra Reddy   });
323438f7fc0SSiva Chandra Reddy }
324438f7fc0SSiva Chandra Reddy 
325438f7fc0SSiva Chandra Reddy } // namespace libc_benchmarks
326438f7fc0SSiva Chandra Reddy } // namespace llvm
327