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