1*06c3fb27SDimitry Andric //===- TextStubV5.cpp -----------------------------------------------------===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric // 9*06c3fb27SDimitry Andric // Implements Text Stub JSON mappings. 10*06c3fb27SDimitry Andric // 11*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 12*06c3fb27SDimitry Andric #include "TextStubCommon.h" 13*06c3fb27SDimitry Andric #include "llvm/ADT/StringSwitch.h" 14*06c3fb27SDimitry Andric #include "llvm/Support/JSON.h" 15*06c3fb27SDimitry Andric #include <utility> 16*06c3fb27SDimitry Andric 17*06c3fb27SDimitry Andric // clang-format off 18*06c3fb27SDimitry Andric /* 19*06c3fb27SDimitry Andric 20*06c3fb27SDimitry Andric JSON Format specification. 21*06c3fb27SDimitry Andric 22*06c3fb27SDimitry Andric All library level keys, accept target values and are defaulted if not specified. 23*06c3fb27SDimitry Andric 24*06c3fb27SDimitry Andric { 25*06c3fb27SDimitry Andric "tapi_tbd_version": 5, # Required: TBD version for all documents in file 26*06c3fb27SDimitry Andric "main_library": { # Required: top level library 27*06c3fb27SDimitry Andric "target_info": [ # Required: target information 28*06c3fb27SDimitry Andric { 29*06c3fb27SDimitry Andric "target": "x86_64-macos", 30*06c3fb27SDimitry Andric "min_deployment": "10.14" # Required: minimum OS deployment version 31*06c3fb27SDimitry Andric }, 32*06c3fb27SDimitry Andric { 33*06c3fb27SDimitry Andric "target": "arm64-macos", 34*06c3fb27SDimitry Andric "min_deployment": "10.14" 35*06c3fb27SDimitry Andric }, 36*06c3fb27SDimitry Andric { 37*06c3fb27SDimitry Andric "target": "arm64-maccatalyst", 38*06c3fb27SDimitry Andric "min_deployment": "12.1" 39*06c3fb27SDimitry Andric }], 40*06c3fb27SDimitry Andric "flags":[{"attributes": ["flat_namespace"]}], # Optional: 41*06c3fb27SDimitry Andric "install_names":[{"name":"/S/L/F/Foo.fwk/Foo"}], # Required: library install name 42*06c3fb27SDimitry Andric "current_versions":[{"version": "1.2"}], # Optional: defaults to 1 43*06c3fb27SDimitry Andric "compatibility_versions":[{ "version": "1.1"}], # Optional: defaults to 1 44*06c3fb27SDimitry Andric "rpaths": [ # Optional: 45*06c3fb27SDimitry Andric { 46*06c3fb27SDimitry Andric "targets": ["x86_64-macos"], # Optional: defaults to targets in `target-info` 47*06c3fb27SDimitry Andric "paths": ["@executable_path/.../Frameworks"] 48*06c3fb27SDimitry Andric }], 49*06c3fb27SDimitry Andric "parent_umbrellas": [{"umbrella": "System"}], 50*06c3fb27SDimitry Andric "allowable_clients": [{"clients": ["ClientA"]}], 51*06c3fb27SDimitry Andric "reexported_libraries": [{"names": ["/u/l/l/foo.dylib"]}], 52*06c3fb27SDimitry Andric "exported_symbols": [{ # List of export symbols section 53*06c3fb27SDimitry Andric "targets": ["x86_64-macos", "arm64-macos"], # Optional: defaults to targets in `target-info` 54*06c3fb27SDimitry Andric "text": { # List of Text segment symbols 55*06c3fb27SDimitry Andric "global": [ "_func" ], 56*06c3fb27SDimitry Andric "weak": [], 57*06c3fb27SDimitry Andric "thread_local": [] 58*06c3fb27SDimitry Andric }, 59*06c3fb27SDimitry Andric "data": { ... }, # List of Data segment symbols 60*06c3fb27SDimitry Andric }], 61*06c3fb27SDimitry Andric "reexported_symbols": [{ ... }], # List of reexported symbols section 62*06c3fb27SDimitry Andric "undefined_symbols": [{ ... }] # List of undefined symbols section 63*06c3fb27SDimitry Andric }, 64*06c3fb27SDimitry Andric "libraries": [ # Optional: Array of inlined libraries 65*06c3fb27SDimitry Andric {...}, {...}, {...} 66*06c3fb27SDimitry Andric ] 67*06c3fb27SDimitry Andric } 68*06c3fb27SDimitry Andric */ 69*06c3fb27SDimitry Andric // clang-format on 70*06c3fb27SDimitry Andric 71*06c3fb27SDimitry Andric using namespace llvm; 72*06c3fb27SDimitry Andric using namespace llvm::json; 73*06c3fb27SDimitry Andric using namespace llvm::MachO; 74*06c3fb27SDimitry Andric 75*06c3fb27SDimitry Andric namespace { 76*06c3fb27SDimitry Andric struct JSONSymbol { 77*06c3fb27SDimitry Andric SymbolKind Kind; 78*06c3fb27SDimitry Andric std::string Name; 79*06c3fb27SDimitry Andric SymbolFlags Flags; 80*06c3fb27SDimitry Andric }; 81*06c3fb27SDimitry Andric 82*06c3fb27SDimitry Andric using AttrToTargets = std::map<std::string, TargetList>; 83*06c3fb27SDimitry Andric using TargetsToSymbols = 84*06c3fb27SDimitry Andric SmallVector<std::pair<TargetList, std::vector<JSONSymbol>>>; 85*06c3fb27SDimitry Andric 86*06c3fb27SDimitry Andric enum TBDKey : size_t { 87*06c3fb27SDimitry Andric TBDVersion = 0U, 88*06c3fb27SDimitry Andric MainLibrary, 89*06c3fb27SDimitry Andric Documents, 90*06c3fb27SDimitry Andric TargetInfo, 91*06c3fb27SDimitry Andric Targets, 92*06c3fb27SDimitry Andric Target, 93*06c3fb27SDimitry Andric Deployment, 94*06c3fb27SDimitry Andric Flags, 95*06c3fb27SDimitry Andric Attributes, 96*06c3fb27SDimitry Andric InstallName, 97*06c3fb27SDimitry Andric CurrentVersion, 98*06c3fb27SDimitry Andric CompatibilityVersion, 99*06c3fb27SDimitry Andric Version, 100*06c3fb27SDimitry Andric SwiftABI, 101*06c3fb27SDimitry Andric ABI, 102*06c3fb27SDimitry Andric ParentUmbrella, 103*06c3fb27SDimitry Andric Umbrella, 104*06c3fb27SDimitry Andric AllowableClients, 105*06c3fb27SDimitry Andric Clients, 106*06c3fb27SDimitry Andric ReexportLibs, 107*06c3fb27SDimitry Andric Names, 108*06c3fb27SDimitry Andric Name, 109*06c3fb27SDimitry Andric Exports, 110*06c3fb27SDimitry Andric Reexports, 111*06c3fb27SDimitry Andric Undefineds, 112*06c3fb27SDimitry Andric Data, 113*06c3fb27SDimitry Andric Text, 114*06c3fb27SDimitry Andric Weak, 115*06c3fb27SDimitry Andric ThreadLocal, 116*06c3fb27SDimitry Andric Globals, 117*06c3fb27SDimitry Andric ObjCClass, 118*06c3fb27SDimitry Andric ObjCEHType, 119*06c3fb27SDimitry Andric ObjCIvar, 120*06c3fb27SDimitry Andric RPath, 121*06c3fb27SDimitry Andric Paths, 122*06c3fb27SDimitry Andric }; 123*06c3fb27SDimitry Andric 124*06c3fb27SDimitry Andric std::array<StringRef, 64> Keys = { 125*06c3fb27SDimitry Andric "tapi_tbd_version", 126*06c3fb27SDimitry Andric "main_library", 127*06c3fb27SDimitry Andric "libraries", 128*06c3fb27SDimitry Andric "target_info", 129*06c3fb27SDimitry Andric "targets", 130*06c3fb27SDimitry Andric "target", 131*06c3fb27SDimitry Andric "min_deployment", 132*06c3fb27SDimitry Andric "flags", 133*06c3fb27SDimitry Andric "attributes", 134*06c3fb27SDimitry Andric "install_names", 135*06c3fb27SDimitry Andric "current_versions", 136*06c3fb27SDimitry Andric "compatibility_versions", 137*06c3fb27SDimitry Andric "version", 138*06c3fb27SDimitry Andric "swift_abi", 139*06c3fb27SDimitry Andric "abi", 140*06c3fb27SDimitry Andric "parent_umbrellas", 141*06c3fb27SDimitry Andric "umbrella", 142*06c3fb27SDimitry Andric "allowable_clients", 143*06c3fb27SDimitry Andric "clients", 144*06c3fb27SDimitry Andric "reexported_libraries", 145*06c3fb27SDimitry Andric "names", 146*06c3fb27SDimitry Andric "name", 147*06c3fb27SDimitry Andric "exported_symbols", 148*06c3fb27SDimitry Andric "reexported_symbols", 149*06c3fb27SDimitry Andric "undefined_symbols", 150*06c3fb27SDimitry Andric "data", 151*06c3fb27SDimitry Andric "text", 152*06c3fb27SDimitry Andric "weak", 153*06c3fb27SDimitry Andric "thread_local", 154*06c3fb27SDimitry Andric "global", 155*06c3fb27SDimitry Andric "objc_class", 156*06c3fb27SDimitry Andric "objc_eh_type", 157*06c3fb27SDimitry Andric "objc_ivar", 158*06c3fb27SDimitry Andric "rpaths", 159*06c3fb27SDimitry Andric "paths", 160*06c3fb27SDimitry Andric }; 161*06c3fb27SDimitry Andric 162*06c3fb27SDimitry Andric static llvm::SmallString<128> getParseErrorMsg(TBDKey Key) { 163*06c3fb27SDimitry Andric return {"invalid ", Keys[Key], " section"}; 164*06c3fb27SDimitry Andric } 165*06c3fb27SDimitry Andric 166*06c3fb27SDimitry Andric static llvm::SmallString<128> getSerializeErrorMsg(TBDKey Key) { 167*06c3fb27SDimitry Andric return {"missing ", Keys[Key], " information"}; 168*06c3fb27SDimitry Andric } 169*06c3fb27SDimitry Andric 170*06c3fb27SDimitry Andric class JSONStubError : public llvm::ErrorInfo<llvm::json::ParseError> { 171*06c3fb27SDimitry Andric public: 172*06c3fb27SDimitry Andric JSONStubError(Twine ErrMsg) : Message(ErrMsg.str()) {} 173*06c3fb27SDimitry Andric 174*06c3fb27SDimitry Andric void log(llvm::raw_ostream &OS) const override { OS << Message << "\n"; } 175*06c3fb27SDimitry Andric std::error_code convertToErrorCode() const override { 176*06c3fb27SDimitry Andric return llvm::inconvertibleErrorCode(); 177*06c3fb27SDimitry Andric } 178*06c3fb27SDimitry Andric 179*06c3fb27SDimitry Andric private: 180*06c3fb27SDimitry Andric std::string Message; 181*06c3fb27SDimitry Andric }; 182*06c3fb27SDimitry Andric 183*06c3fb27SDimitry Andric template <typename JsonT, typename StubT = JsonT> 184*06c3fb27SDimitry Andric Expected<StubT> getRequiredValue( 185*06c3fb27SDimitry Andric TBDKey Key, const Object *Obj, 186*06c3fb27SDimitry Andric std::function<std::optional<JsonT>(const Object *, StringRef)> GetValue, 187*06c3fb27SDimitry Andric std::function<std::optional<StubT>(JsonT)> Validate = nullptr) { 188*06c3fb27SDimitry Andric std::optional<JsonT> Val = GetValue(Obj, Keys[Key]); 189*06c3fb27SDimitry Andric if (!Val) 190*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key)); 191*06c3fb27SDimitry Andric 192*06c3fb27SDimitry Andric if (Validate == nullptr) 193*06c3fb27SDimitry Andric return static_cast<StubT>(*Val); 194*06c3fb27SDimitry Andric 195*06c3fb27SDimitry Andric std::optional<StubT> Result = Validate(*Val); 196*06c3fb27SDimitry Andric if (!Result.has_value()) 197*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key)); 198*06c3fb27SDimitry Andric return Result.value(); 199*06c3fb27SDimitry Andric } 200*06c3fb27SDimitry Andric 201*06c3fb27SDimitry Andric template <typename JsonT, typename StubT = JsonT> 202*06c3fb27SDimitry Andric Expected<StubT> getRequiredValue( 203*06c3fb27SDimitry Andric TBDKey Key, const Object *Obj, 204*06c3fb27SDimitry Andric std::function<std::optional<JsonT>(const Object *, StringRef)> GetValue, 205*06c3fb27SDimitry Andric StubT DefaultValue, std::function<std::optional<StubT>(JsonT)> Validate) { 206*06c3fb27SDimitry Andric std::optional<JsonT> Val = GetValue(Obj, Keys[Key]); 207*06c3fb27SDimitry Andric if (!Val) 208*06c3fb27SDimitry Andric return DefaultValue; 209*06c3fb27SDimitry Andric 210*06c3fb27SDimitry Andric std::optional<StubT> Result; 211*06c3fb27SDimitry Andric Result = Validate(*Val); 212*06c3fb27SDimitry Andric if (!Result.has_value()) 213*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key)); 214*06c3fb27SDimitry Andric return Result.value(); 215*06c3fb27SDimitry Andric } 216*06c3fb27SDimitry Andric 217*06c3fb27SDimitry Andric Error collectFromArray(TBDKey Key, const Object *Obj, 218*06c3fb27SDimitry Andric std::function<void(StringRef)> Append, 219*06c3fb27SDimitry Andric bool IsRequired = false) { 220*06c3fb27SDimitry Andric const auto *Values = Obj->getArray(Keys[Key]); 221*06c3fb27SDimitry Andric if (!Values) { 222*06c3fb27SDimitry Andric if (IsRequired) 223*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key)); 224*06c3fb27SDimitry Andric return Error::success(); 225*06c3fb27SDimitry Andric } 226*06c3fb27SDimitry Andric 227*06c3fb27SDimitry Andric for (const Value &Val : *Values) { 228*06c3fb27SDimitry Andric auto ValStr = Val.getAsString(); 229*06c3fb27SDimitry Andric if (!ValStr.has_value()) 230*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key)); 231*06c3fb27SDimitry Andric Append(ValStr.value()); 232*06c3fb27SDimitry Andric } 233*06c3fb27SDimitry Andric 234*06c3fb27SDimitry Andric return Error::success(); 235*06c3fb27SDimitry Andric } 236*06c3fb27SDimitry Andric 237*06c3fb27SDimitry Andric namespace StubParser { 238*06c3fb27SDimitry Andric 239*06c3fb27SDimitry Andric Expected<FileType> getVersion(const Object *File) { 240*06c3fb27SDimitry Andric auto VersionOrErr = getRequiredValue<int64_t, FileType>( 241*06c3fb27SDimitry Andric TBDKey::TBDVersion, File, &Object::getInteger, 242*06c3fb27SDimitry Andric [](int64_t Val) -> std::optional<FileType> { 243*06c3fb27SDimitry Andric unsigned Result = Val; 244*06c3fb27SDimitry Andric if (Result != 5) 245*06c3fb27SDimitry Andric return std::nullopt; 246*06c3fb27SDimitry Andric return FileType::TBD_V5; 247*06c3fb27SDimitry Andric }); 248*06c3fb27SDimitry Andric 249*06c3fb27SDimitry Andric if (!VersionOrErr) 250*06c3fb27SDimitry Andric return VersionOrErr.takeError(); 251*06c3fb27SDimitry Andric return *VersionOrErr; 252*06c3fb27SDimitry Andric } 253*06c3fb27SDimitry Andric 254*06c3fb27SDimitry Andric Expected<TargetList> getTargets(const Object *Section) { 255*06c3fb27SDimitry Andric const auto *Targets = Section->getArray(Keys[TBDKey::Targets]); 256*06c3fb27SDimitry Andric if (!Targets) 257*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets)); 258*06c3fb27SDimitry Andric 259*06c3fb27SDimitry Andric TargetList IFTargets; 260*06c3fb27SDimitry Andric for (const Value &JSONTarget : *Targets) { 261*06c3fb27SDimitry Andric auto TargetStr = JSONTarget.getAsString(); 262*06c3fb27SDimitry Andric if (!TargetStr.has_value()) 263*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target)); 264*06c3fb27SDimitry Andric auto TargetOrErr = Target::create(TargetStr.value()); 265*06c3fb27SDimitry Andric if (!TargetOrErr) 266*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target)); 267*06c3fb27SDimitry Andric IFTargets.push_back(*TargetOrErr); 268*06c3fb27SDimitry Andric } 269*06c3fb27SDimitry Andric return std::move(IFTargets); 270*06c3fb27SDimitry Andric } 271*06c3fb27SDimitry Andric 272*06c3fb27SDimitry Andric Expected<TargetList> getTargetsSection(const Object *Section) { 273*06c3fb27SDimitry Andric const Array *Targets = Section->getArray(Keys[TBDKey::TargetInfo]); 274*06c3fb27SDimitry Andric if (!Targets) 275*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets)); 276*06c3fb27SDimitry Andric 277*06c3fb27SDimitry Andric TargetList IFTargets; 278*06c3fb27SDimitry Andric for (const Value &JSONTarget : *Targets) { 279*06c3fb27SDimitry Andric const auto *Obj = JSONTarget.getAsObject(); 280*06c3fb27SDimitry Andric if (!Obj) 281*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target)); 282*06c3fb27SDimitry Andric auto TargetStr = 283*06c3fb27SDimitry Andric getRequiredValue<StringRef>(TBDKey::Target, Obj, &Object::getString); 284*06c3fb27SDimitry Andric if (!TargetStr) 285*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target)); 286*06c3fb27SDimitry Andric auto VersionStr = getRequiredValue<StringRef>(TBDKey::Deployment, Obj, 287*06c3fb27SDimitry Andric &Object::getString); 288*06c3fb27SDimitry Andric if (!VersionStr) 289*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Deployment)); 290*06c3fb27SDimitry Andric VersionTuple Version; 291*06c3fb27SDimitry Andric if (Version.tryParse(*VersionStr)) 292*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Deployment)); 293*06c3fb27SDimitry Andric auto TargetOrErr = Target::create(*TargetStr); 294*06c3fb27SDimitry Andric if (!TargetOrErr) 295*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target)); 296*06c3fb27SDimitry Andric TargetOrErr->MinDeployment = Version; 297*06c3fb27SDimitry Andric // Convert to LLVM::Triple to accurately compute minOS + platform + arch 298*06c3fb27SDimitry Andric // pairing. 299*06c3fb27SDimitry Andric IFTargets.push_back( 300*06c3fb27SDimitry Andric MachO::Target(Triple(getTargetTripleName(*TargetOrErr)))); 301*06c3fb27SDimitry Andric } 302*06c3fb27SDimitry Andric return std::move(IFTargets); 303*06c3fb27SDimitry Andric } 304*06c3fb27SDimitry Andric 305*06c3fb27SDimitry Andric Error collectSymbolsFromSegment(const Object *Segment, TargetsToSymbols &Result, 306*06c3fb27SDimitry Andric SymbolFlags SectionFlag) { 307*06c3fb27SDimitry Andric auto Err = collectFromArray( 308*06c3fb27SDimitry Andric TBDKey::Globals, Segment, [&Result, &SectionFlag](StringRef Name) { 309*06c3fb27SDimitry Andric JSONSymbol Sym = {SymbolKind::GlobalSymbol, Name.str(), SectionFlag}; 310*06c3fb27SDimitry Andric Result.back().second.emplace_back(Sym); 311*06c3fb27SDimitry Andric }); 312*06c3fb27SDimitry Andric if (Err) 313*06c3fb27SDimitry Andric return Err; 314*06c3fb27SDimitry Andric 315*06c3fb27SDimitry Andric Err = collectFromArray( 316*06c3fb27SDimitry Andric TBDKey::ObjCClass, Segment, [&Result, &SectionFlag](StringRef Name) { 317*06c3fb27SDimitry Andric JSONSymbol Sym = {SymbolKind::ObjectiveCClass, Name.str(), SectionFlag}; 318*06c3fb27SDimitry Andric Result.back().second.emplace_back(Sym); 319*06c3fb27SDimitry Andric }); 320*06c3fb27SDimitry Andric if (Err) 321*06c3fb27SDimitry Andric return Err; 322*06c3fb27SDimitry Andric 323*06c3fb27SDimitry Andric Err = collectFromArray(TBDKey::ObjCEHType, Segment, 324*06c3fb27SDimitry Andric [&Result, &SectionFlag](StringRef Name) { 325*06c3fb27SDimitry Andric JSONSymbol Sym = {SymbolKind::ObjectiveCClassEHType, 326*06c3fb27SDimitry Andric Name.str(), SectionFlag}; 327*06c3fb27SDimitry Andric Result.back().second.emplace_back(Sym); 328*06c3fb27SDimitry Andric }); 329*06c3fb27SDimitry Andric if (Err) 330*06c3fb27SDimitry Andric return Err; 331*06c3fb27SDimitry Andric 332*06c3fb27SDimitry Andric Err = collectFromArray( 333*06c3fb27SDimitry Andric TBDKey::ObjCIvar, Segment, [&Result, &SectionFlag](StringRef Name) { 334*06c3fb27SDimitry Andric JSONSymbol Sym = {SymbolKind::ObjectiveCInstanceVariable, Name.str(), 335*06c3fb27SDimitry Andric SectionFlag}; 336*06c3fb27SDimitry Andric Result.back().second.emplace_back(Sym); 337*06c3fb27SDimitry Andric }); 338*06c3fb27SDimitry Andric if (Err) 339*06c3fb27SDimitry Andric return Err; 340*06c3fb27SDimitry Andric 341*06c3fb27SDimitry Andric SymbolFlags WeakFlag = 342*06c3fb27SDimitry Andric SectionFlag | 343*06c3fb27SDimitry Andric (((SectionFlag & SymbolFlags::Undefined) == SymbolFlags::Undefined) 344*06c3fb27SDimitry Andric ? SymbolFlags::WeakReferenced 345*06c3fb27SDimitry Andric : SymbolFlags::WeakDefined); 346*06c3fb27SDimitry Andric Err = collectFromArray( 347*06c3fb27SDimitry Andric TBDKey::Weak, Segment, [&Result, WeakFlag](StringRef Name) { 348*06c3fb27SDimitry Andric JSONSymbol Sym = {SymbolKind::GlobalSymbol, Name.str(), WeakFlag}; 349*06c3fb27SDimitry Andric Result.back().second.emplace_back(Sym); 350*06c3fb27SDimitry Andric }); 351*06c3fb27SDimitry Andric if (Err) 352*06c3fb27SDimitry Andric return Err; 353*06c3fb27SDimitry Andric 354*06c3fb27SDimitry Andric Err = collectFromArray( 355*06c3fb27SDimitry Andric TBDKey::ThreadLocal, Segment, [&Result, SectionFlag](StringRef Name) { 356*06c3fb27SDimitry Andric JSONSymbol Sym = {SymbolKind::GlobalSymbol, Name.str(), 357*06c3fb27SDimitry Andric SymbolFlags::ThreadLocalValue | SectionFlag}; 358*06c3fb27SDimitry Andric Result.back().second.emplace_back(Sym); 359*06c3fb27SDimitry Andric }); 360*06c3fb27SDimitry Andric if (Err) 361*06c3fb27SDimitry Andric return Err; 362*06c3fb27SDimitry Andric 363*06c3fb27SDimitry Andric return Error::success(); 364*06c3fb27SDimitry Andric } 365*06c3fb27SDimitry Andric 366*06c3fb27SDimitry Andric Expected<StringRef> getNameSection(const Object *File) { 367*06c3fb27SDimitry Andric const Array *Section = File->getArray(Keys[TBDKey::InstallName]); 368*06c3fb27SDimitry Andric if (!Section) 369*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName)); 370*06c3fb27SDimitry Andric 371*06c3fb27SDimitry Andric assert(!Section->empty() && "unexpected missing install name"); 372*06c3fb27SDimitry Andric // TODO: Just take first for now. 373*06c3fb27SDimitry Andric const auto *Obj = Section->front().getAsObject(); 374*06c3fb27SDimitry Andric if (!Obj) 375*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName)); 376*06c3fb27SDimitry Andric 377*06c3fb27SDimitry Andric return getRequiredValue<StringRef>(TBDKey::Name, Obj, &Object::getString); 378*06c3fb27SDimitry Andric } 379*06c3fb27SDimitry Andric 380*06c3fb27SDimitry Andric Expected<TargetsToSymbols> getSymbolSection(const Object *File, TBDKey Key, 381*06c3fb27SDimitry Andric TargetList &Targets) { 382*06c3fb27SDimitry Andric 383*06c3fb27SDimitry Andric const Array *Section = File->getArray(Keys[Key]); 384*06c3fb27SDimitry Andric if (!Section) 385*06c3fb27SDimitry Andric return TargetsToSymbols(); 386*06c3fb27SDimitry Andric 387*06c3fb27SDimitry Andric SymbolFlags SectionFlag; 388*06c3fb27SDimitry Andric switch (Key) { 389*06c3fb27SDimitry Andric case TBDKey::Reexports: 390*06c3fb27SDimitry Andric SectionFlag = SymbolFlags::Rexported; 391*06c3fb27SDimitry Andric break; 392*06c3fb27SDimitry Andric case TBDKey::Undefineds: 393*06c3fb27SDimitry Andric SectionFlag = SymbolFlags::Undefined; 394*06c3fb27SDimitry Andric break; 395*06c3fb27SDimitry Andric default: 396*06c3fb27SDimitry Andric SectionFlag = SymbolFlags::None; 397*06c3fb27SDimitry Andric break; 398*06c3fb27SDimitry Andric }; 399*06c3fb27SDimitry Andric 400*06c3fb27SDimitry Andric TargetsToSymbols Result; 401*06c3fb27SDimitry Andric TargetList MappedTargets; 402*06c3fb27SDimitry Andric for (auto Val : *Section) { 403*06c3fb27SDimitry Andric auto *Obj = Val.getAsObject(); 404*06c3fb27SDimitry Andric if (!Obj) 405*06c3fb27SDimitry Andric continue; 406*06c3fb27SDimitry Andric 407*06c3fb27SDimitry Andric auto TargetsOrErr = getTargets(Obj); 408*06c3fb27SDimitry Andric if (!TargetsOrErr) { 409*06c3fb27SDimitry Andric MappedTargets = Targets; 410*06c3fb27SDimitry Andric consumeError(TargetsOrErr.takeError()); 411*06c3fb27SDimitry Andric } else { 412*06c3fb27SDimitry Andric MappedTargets = *TargetsOrErr; 413*06c3fb27SDimitry Andric } 414*06c3fb27SDimitry Andric Result.emplace_back( 415*06c3fb27SDimitry Andric std::make_pair(std::move(MappedTargets), std::vector<JSONSymbol>())); 416*06c3fb27SDimitry Andric 417*06c3fb27SDimitry Andric auto *DataSection = Obj->getObject(Keys[TBDKey::Data]); 418*06c3fb27SDimitry Andric auto *TextSection = Obj->getObject(Keys[TBDKey::Text]); 419*06c3fb27SDimitry Andric // There should be at least one valid section. 420*06c3fb27SDimitry Andric if (!DataSection && !TextSection) 421*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key)); 422*06c3fb27SDimitry Andric 423*06c3fb27SDimitry Andric if (DataSection) { 424*06c3fb27SDimitry Andric auto Err = collectSymbolsFromSegment(DataSection, Result, 425*06c3fb27SDimitry Andric SectionFlag | SymbolFlags::Data); 426*06c3fb27SDimitry Andric if (Err) 427*06c3fb27SDimitry Andric return std::move(Err); 428*06c3fb27SDimitry Andric } 429*06c3fb27SDimitry Andric if (TextSection) { 430*06c3fb27SDimitry Andric auto Err = collectSymbolsFromSegment(TextSection, Result, 431*06c3fb27SDimitry Andric SectionFlag | SymbolFlags::Text); 432*06c3fb27SDimitry Andric if (Err) 433*06c3fb27SDimitry Andric return std::move(Err); 434*06c3fb27SDimitry Andric } 435*06c3fb27SDimitry Andric } 436*06c3fb27SDimitry Andric 437*06c3fb27SDimitry Andric return std::move(Result); 438*06c3fb27SDimitry Andric } 439*06c3fb27SDimitry Andric 440*06c3fb27SDimitry Andric Expected<AttrToTargets> getLibSection(const Object *File, TBDKey Key, 441*06c3fb27SDimitry Andric TBDKey SubKey, 442*06c3fb27SDimitry Andric const TargetList &Targets) { 443*06c3fb27SDimitry Andric auto *Section = File->getArray(Keys[Key]); 444*06c3fb27SDimitry Andric if (!Section) 445*06c3fb27SDimitry Andric return AttrToTargets(); 446*06c3fb27SDimitry Andric 447*06c3fb27SDimitry Andric AttrToTargets Result; 448*06c3fb27SDimitry Andric TargetList MappedTargets; 449*06c3fb27SDimitry Andric for (auto Val : *Section) { 450*06c3fb27SDimitry Andric auto *Obj = Val.getAsObject(); 451*06c3fb27SDimitry Andric if (!Obj) 452*06c3fb27SDimitry Andric continue; 453*06c3fb27SDimitry Andric 454*06c3fb27SDimitry Andric auto TargetsOrErr = getTargets(Obj); 455*06c3fb27SDimitry Andric if (!TargetsOrErr) { 456*06c3fb27SDimitry Andric MappedTargets = Targets; 457*06c3fb27SDimitry Andric consumeError(TargetsOrErr.takeError()); 458*06c3fb27SDimitry Andric } else { 459*06c3fb27SDimitry Andric MappedTargets = *TargetsOrErr; 460*06c3fb27SDimitry Andric } 461*06c3fb27SDimitry Andric auto Err = 462*06c3fb27SDimitry Andric collectFromArray(SubKey, Obj, [&Result, &MappedTargets](StringRef Key) { 463*06c3fb27SDimitry Andric Result[Key.str()] = MappedTargets; 464*06c3fb27SDimitry Andric }); 465*06c3fb27SDimitry Andric if (Err) 466*06c3fb27SDimitry Andric return std::move(Err); 467*06c3fb27SDimitry Andric } 468*06c3fb27SDimitry Andric 469*06c3fb27SDimitry Andric return std::move(Result); 470*06c3fb27SDimitry Andric } 471*06c3fb27SDimitry Andric 472*06c3fb27SDimitry Andric Expected<AttrToTargets> getUmbrellaSection(const Object *File, 473*06c3fb27SDimitry Andric const TargetList &Targets) { 474*06c3fb27SDimitry Andric const auto *Umbrella = File->getArray(Keys[TBDKey::ParentUmbrella]); 475*06c3fb27SDimitry Andric if (!Umbrella) 476*06c3fb27SDimitry Andric return AttrToTargets(); 477*06c3fb27SDimitry Andric 478*06c3fb27SDimitry Andric AttrToTargets Result; 479*06c3fb27SDimitry Andric TargetList MappedTargets; 480*06c3fb27SDimitry Andric for (auto Val : *Umbrella) { 481*06c3fb27SDimitry Andric auto *Obj = Val.getAsObject(); 482*06c3fb27SDimitry Andric if (!Obj) 483*06c3fb27SDimitry Andric return make_error<JSONStubError>( 484*06c3fb27SDimitry Andric getParseErrorMsg(TBDKey::ParentUmbrella)); 485*06c3fb27SDimitry Andric 486*06c3fb27SDimitry Andric // Get Targets section. 487*06c3fb27SDimitry Andric auto TargetsOrErr = getTargets(Obj); 488*06c3fb27SDimitry Andric if (!TargetsOrErr) { 489*06c3fb27SDimitry Andric MappedTargets = Targets; 490*06c3fb27SDimitry Andric consumeError(TargetsOrErr.takeError()); 491*06c3fb27SDimitry Andric } else { 492*06c3fb27SDimitry Andric MappedTargets = *TargetsOrErr; 493*06c3fb27SDimitry Andric } 494*06c3fb27SDimitry Andric 495*06c3fb27SDimitry Andric auto UmbrellaOrErr = 496*06c3fb27SDimitry Andric getRequiredValue<StringRef>(TBDKey::Umbrella, Obj, &Object::getString); 497*06c3fb27SDimitry Andric if (!UmbrellaOrErr) 498*06c3fb27SDimitry Andric return UmbrellaOrErr.takeError(); 499*06c3fb27SDimitry Andric Result[UmbrellaOrErr->str()] = Targets; 500*06c3fb27SDimitry Andric } 501*06c3fb27SDimitry Andric return std::move(Result); 502*06c3fb27SDimitry Andric } 503*06c3fb27SDimitry Andric 504*06c3fb27SDimitry Andric Expected<uint8_t> getSwiftVersion(const Object *File) { 505*06c3fb27SDimitry Andric const Array *Versions = File->getArray(Keys[TBDKey::SwiftABI]); 506*06c3fb27SDimitry Andric if (!Versions) 507*06c3fb27SDimitry Andric return 0; 508*06c3fb27SDimitry Andric 509*06c3fb27SDimitry Andric for (const auto &Val : *Versions) { 510*06c3fb27SDimitry Andric const auto *Obj = Val.getAsObject(); 511*06c3fb27SDimitry Andric if (!Obj) 512*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::SwiftABI)); 513*06c3fb27SDimitry Andric 514*06c3fb27SDimitry Andric // TODO: Take first for now. 515*06c3fb27SDimitry Andric return getRequiredValue<int64_t, uint8_t>(TBDKey::ABI, Obj, 516*06c3fb27SDimitry Andric &Object::getInteger); 517*06c3fb27SDimitry Andric } 518*06c3fb27SDimitry Andric 519*06c3fb27SDimitry Andric return 0; 520*06c3fb27SDimitry Andric } 521*06c3fb27SDimitry Andric 522*06c3fb27SDimitry Andric Expected<PackedVersion> getPackedVersion(const Object *File, TBDKey Key) { 523*06c3fb27SDimitry Andric const Array *Versions = File->getArray(Keys[Key]); 524*06c3fb27SDimitry Andric if (!Versions) 525*06c3fb27SDimitry Andric return PackedVersion(1, 0, 0); 526*06c3fb27SDimitry Andric 527*06c3fb27SDimitry Andric for (const auto &Val : *Versions) { 528*06c3fb27SDimitry Andric const auto *Obj = Val.getAsObject(); 529*06c3fb27SDimitry Andric if (!Obj) 530*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key)); 531*06c3fb27SDimitry Andric 532*06c3fb27SDimitry Andric auto ValidatePV = [](StringRef Version) -> std::optional<PackedVersion> { 533*06c3fb27SDimitry Andric PackedVersion PV; 534*06c3fb27SDimitry Andric auto [success, truncated] = PV.parse64(Version); 535*06c3fb27SDimitry Andric if (!success || truncated) 536*06c3fb27SDimitry Andric return std::nullopt; 537*06c3fb27SDimitry Andric return PV; 538*06c3fb27SDimitry Andric }; 539*06c3fb27SDimitry Andric // TODO: Take first for now. 540*06c3fb27SDimitry Andric return getRequiredValue<StringRef, PackedVersion>( 541*06c3fb27SDimitry Andric TBDKey::Version, Obj, &Object::getString, PackedVersion(1, 0, 0), 542*06c3fb27SDimitry Andric ValidatePV); 543*06c3fb27SDimitry Andric } 544*06c3fb27SDimitry Andric 545*06c3fb27SDimitry Andric return PackedVersion(1, 0, 0); 546*06c3fb27SDimitry Andric } 547*06c3fb27SDimitry Andric 548*06c3fb27SDimitry Andric Expected<TBDFlags> getFlags(const Object *File) { 549*06c3fb27SDimitry Andric TBDFlags Flags = TBDFlags::None; 550*06c3fb27SDimitry Andric const Array *Section = File->getArray(Keys[TBDKey::Flags]); 551*06c3fb27SDimitry Andric if (!Section) 552*06c3fb27SDimitry Andric return Flags; 553*06c3fb27SDimitry Andric 554*06c3fb27SDimitry Andric for (auto &Val : *Section) { 555*06c3fb27SDimitry Andric // TODO: Just take first for now. 556*06c3fb27SDimitry Andric const auto *Obj = Val.getAsObject(); 557*06c3fb27SDimitry Andric if (!Obj) 558*06c3fb27SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Flags)); 559*06c3fb27SDimitry Andric 560*06c3fb27SDimitry Andric auto FlagsOrErr = 561*06c3fb27SDimitry Andric collectFromArray(TBDKey::Attributes, Obj, [&Flags](StringRef Flag) { 562*06c3fb27SDimitry Andric TBDFlags TBDFlag = 563*06c3fb27SDimitry Andric StringSwitch<TBDFlags>(Flag) 564*06c3fb27SDimitry Andric .Case("flat_namespace", TBDFlags::FlatNamespace) 565*06c3fb27SDimitry Andric .Case("not_app_extension_safe", 566*06c3fb27SDimitry Andric TBDFlags::NotApplicationExtensionSafe) 567*06c3fb27SDimitry Andric .Default(TBDFlags::None); 568*06c3fb27SDimitry Andric Flags |= TBDFlag; 569*06c3fb27SDimitry Andric }); 570*06c3fb27SDimitry Andric 571*06c3fb27SDimitry Andric if (FlagsOrErr) 572*06c3fb27SDimitry Andric return std::move(FlagsOrErr); 573*06c3fb27SDimitry Andric 574*06c3fb27SDimitry Andric return Flags; 575*06c3fb27SDimitry Andric } 576*06c3fb27SDimitry Andric 577*06c3fb27SDimitry Andric return Flags; 578*06c3fb27SDimitry Andric } 579*06c3fb27SDimitry Andric 580*06c3fb27SDimitry Andric using IFPtr = std::unique_ptr<InterfaceFile>; 581*06c3fb27SDimitry Andric Expected<IFPtr> parseToInterfaceFile(const Object *File) { 582*06c3fb27SDimitry Andric auto TargetsOrErr = getTargetsSection(File); 583*06c3fb27SDimitry Andric if (!TargetsOrErr) 584*06c3fb27SDimitry Andric return TargetsOrErr.takeError(); 585*06c3fb27SDimitry Andric TargetList Targets = *TargetsOrErr; 586*06c3fb27SDimitry Andric 587*06c3fb27SDimitry Andric auto NameOrErr = getNameSection(File); 588*06c3fb27SDimitry Andric if (!NameOrErr) 589*06c3fb27SDimitry Andric return NameOrErr.takeError(); 590*06c3fb27SDimitry Andric StringRef Name = *NameOrErr; 591*06c3fb27SDimitry Andric 592*06c3fb27SDimitry Andric auto CurrVersionOrErr = getPackedVersion(File, TBDKey::CurrentVersion); 593*06c3fb27SDimitry Andric if (!CurrVersionOrErr) 594*06c3fb27SDimitry Andric return CurrVersionOrErr.takeError(); 595*06c3fb27SDimitry Andric PackedVersion CurrVersion = *CurrVersionOrErr; 596*06c3fb27SDimitry Andric 597*06c3fb27SDimitry Andric auto CompVersionOrErr = getPackedVersion(File, TBDKey::CompatibilityVersion); 598*06c3fb27SDimitry Andric if (!CompVersionOrErr) 599*06c3fb27SDimitry Andric return CompVersionOrErr.takeError(); 600*06c3fb27SDimitry Andric PackedVersion CompVersion = *CompVersionOrErr; 601*06c3fb27SDimitry Andric 602*06c3fb27SDimitry Andric auto SwiftABIOrErr = getSwiftVersion(File); 603*06c3fb27SDimitry Andric if (!SwiftABIOrErr) 604*06c3fb27SDimitry Andric return SwiftABIOrErr.takeError(); 605*06c3fb27SDimitry Andric uint8_t SwiftABI = *SwiftABIOrErr; 606*06c3fb27SDimitry Andric 607*06c3fb27SDimitry Andric auto FlagsOrErr = getFlags(File); 608*06c3fb27SDimitry Andric if (!FlagsOrErr) 609*06c3fb27SDimitry Andric return FlagsOrErr.takeError(); 610*06c3fb27SDimitry Andric TBDFlags Flags = *FlagsOrErr; 611*06c3fb27SDimitry Andric 612*06c3fb27SDimitry Andric auto UmbrellasOrErr = getUmbrellaSection(File, Targets); 613*06c3fb27SDimitry Andric if (!UmbrellasOrErr) 614*06c3fb27SDimitry Andric return UmbrellasOrErr.takeError(); 615*06c3fb27SDimitry Andric AttrToTargets Umbrellas = *UmbrellasOrErr; 616*06c3fb27SDimitry Andric 617*06c3fb27SDimitry Andric auto ClientsOrErr = 618*06c3fb27SDimitry Andric getLibSection(File, TBDKey::AllowableClients, TBDKey::Clients, Targets); 619*06c3fb27SDimitry Andric if (!ClientsOrErr) 620*06c3fb27SDimitry Andric return ClientsOrErr.takeError(); 621*06c3fb27SDimitry Andric AttrToTargets Clients = *ClientsOrErr; 622*06c3fb27SDimitry Andric 623*06c3fb27SDimitry Andric auto RLOrErr = 624*06c3fb27SDimitry Andric getLibSection(File, TBDKey::ReexportLibs, TBDKey::Names, Targets); 625*06c3fb27SDimitry Andric if (!RLOrErr) 626*06c3fb27SDimitry Andric return RLOrErr.takeError(); 627*06c3fb27SDimitry Andric AttrToTargets ReexportLibs = std::move(*RLOrErr); 628*06c3fb27SDimitry Andric 629*06c3fb27SDimitry Andric auto RPathsOrErr = getLibSection(File, TBDKey::RPath, TBDKey::Paths, Targets); 630*06c3fb27SDimitry Andric if (!RPathsOrErr) 631*06c3fb27SDimitry Andric return RPathsOrErr.takeError(); 632*06c3fb27SDimitry Andric AttrToTargets RPaths = std::move(*RPathsOrErr); 633*06c3fb27SDimitry Andric 634*06c3fb27SDimitry Andric auto ExportsOrErr = getSymbolSection(File, TBDKey::Exports, Targets); 635*06c3fb27SDimitry Andric if (!ExportsOrErr) 636*06c3fb27SDimitry Andric return ExportsOrErr.takeError(); 637*06c3fb27SDimitry Andric TargetsToSymbols Exports = std::move(*ExportsOrErr); 638*06c3fb27SDimitry Andric 639*06c3fb27SDimitry Andric auto ReexportsOrErr = getSymbolSection(File, TBDKey::Reexports, Targets); 640*06c3fb27SDimitry Andric if (!ReexportsOrErr) 641*06c3fb27SDimitry Andric return ReexportsOrErr.takeError(); 642*06c3fb27SDimitry Andric TargetsToSymbols Reexports = std::move(*ReexportsOrErr); 643*06c3fb27SDimitry Andric 644*06c3fb27SDimitry Andric auto UndefinedsOrErr = getSymbolSection(File, TBDKey::Undefineds, Targets); 645*06c3fb27SDimitry Andric if (!UndefinedsOrErr) 646*06c3fb27SDimitry Andric return UndefinedsOrErr.takeError(); 647*06c3fb27SDimitry Andric TargetsToSymbols Undefineds = std::move(*UndefinedsOrErr); 648*06c3fb27SDimitry Andric 649*06c3fb27SDimitry Andric IFPtr F(new InterfaceFile); 650*06c3fb27SDimitry Andric F->setInstallName(Name); 651*06c3fb27SDimitry Andric F->setCurrentVersion(CurrVersion); 652*06c3fb27SDimitry Andric F->setCompatibilityVersion(CompVersion); 653*06c3fb27SDimitry Andric F->setSwiftABIVersion(SwiftABI); 654*06c3fb27SDimitry Andric F->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace)); 655*06c3fb27SDimitry Andric F->setApplicationExtensionSafe( 656*06c3fb27SDimitry Andric !(Flags & TBDFlags::NotApplicationExtensionSafe)); 657*06c3fb27SDimitry Andric for (auto &T : Targets) 658*06c3fb27SDimitry Andric F->addTarget(T); 659*06c3fb27SDimitry Andric for (auto &[Lib, Targets] : Clients) 660*06c3fb27SDimitry Andric for (auto Target : Targets) 661*06c3fb27SDimitry Andric F->addAllowableClient(Lib, Target); 662*06c3fb27SDimitry Andric for (auto &[Lib, Targets] : ReexportLibs) 663*06c3fb27SDimitry Andric for (auto Target : Targets) 664*06c3fb27SDimitry Andric F->addReexportedLibrary(Lib, Target); 665*06c3fb27SDimitry Andric for (auto &[Lib, Targets] : Umbrellas) 666*06c3fb27SDimitry Andric for (auto Target : Targets) 667*06c3fb27SDimitry Andric F->addParentUmbrella(Target, Lib); 668*06c3fb27SDimitry Andric for (auto &[Path, Targets] : RPaths) 669*06c3fb27SDimitry Andric for (auto Target : Targets) 670*06c3fb27SDimitry Andric F->addRPath(Target, Path); 671*06c3fb27SDimitry Andric for (auto &[Targets, Symbols] : Exports) 672*06c3fb27SDimitry Andric for (auto &Sym : Symbols) 673*06c3fb27SDimitry Andric F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags); 674*06c3fb27SDimitry Andric for (auto &[Targets, Symbols] : Reexports) 675*06c3fb27SDimitry Andric for (auto &Sym : Symbols) 676*06c3fb27SDimitry Andric F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags); 677*06c3fb27SDimitry Andric for (auto &[Targets, Symbols] : Undefineds) 678*06c3fb27SDimitry Andric for (auto &Sym : Symbols) 679*06c3fb27SDimitry Andric F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags); 680*06c3fb27SDimitry Andric 681*06c3fb27SDimitry Andric return std::move(F); 682*06c3fb27SDimitry Andric } 683*06c3fb27SDimitry Andric 684*06c3fb27SDimitry Andric Expected<std::vector<IFPtr>> getInlinedLibs(const Object *File) { 685*06c3fb27SDimitry Andric std::vector<IFPtr> IFs; 686*06c3fb27SDimitry Andric const Array *Files = File->getArray(Keys[TBDKey::Documents]); 687*06c3fb27SDimitry Andric if (!Files) 688*06c3fb27SDimitry Andric return std::move(IFs); 689*06c3fb27SDimitry Andric 690*06c3fb27SDimitry Andric for (auto Lib : *Files) { 691*06c3fb27SDimitry Andric auto IFOrErr = parseToInterfaceFile(Lib.getAsObject()); 692*06c3fb27SDimitry Andric if (!IFOrErr) 693*06c3fb27SDimitry Andric return IFOrErr.takeError(); 694*06c3fb27SDimitry Andric auto IF = std::move(*IFOrErr); 695*06c3fb27SDimitry Andric IFs.emplace_back(std::move(IF)); 696*06c3fb27SDimitry Andric } 697*06c3fb27SDimitry Andric return std::move(IFs); 698*06c3fb27SDimitry Andric } 699*06c3fb27SDimitry Andric 700*06c3fb27SDimitry Andric } // namespace StubParser 701*06c3fb27SDimitry Andric } // namespace 702*06c3fb27SDimitry Andric 703*06c3fb27SDimitry Andric Expected<std::unique_ptr<InterfaceFile>> 704*06c3fb27SDimitry Andric MachO::getInterfaceFileFromJSON(StringRef JSON) { 705*06c3fb27SDimitry Andric auto ValOrErr = parse(JSON); 706*06c3fb27SDimitry Andric if (!ValOrErr) 707*06c3fb27SDimitry Andric return ValOrErr.takeError(); 708*06c3fb27SDimitry Andric 709*06c3fb27SDimitry Andric auto *Root = ValOrErr->getAsObject(); 710*06c3fb27SDimitry Andric auto VersionOrErr = StubParser::getVersion(Root); 711*06c3fb27SDimitry Andric if (!VersionOrErr) 712*06c3fb27SDimitry Andric return VersionOrErr.takeError(); 713*06c3fb27SDimitry Andric FileType Version = *VersionOrErr; 714*06c3fb27SDimitry Andric 715*06c3fb27SDimitry Andric Object *MainLib = Root->getObject(Keys[TBDKey::MainLibrary]); 716*06c3fb27SDimitry Andric auto IFOrErr = StubParser::parseToInterfaceFile(MainLib); 717*06c3fb27SDimitry Andric if (!IFOrErr) 718*06c3fb27SDimitry Andric return IFOrErr.takeError(); 719*06c3fb27SDimitry Andric (*IFOrErr)->setFileType(Version); 720*06c3fb27SDimitry Andric std::unique_ptr<InterfaceFile> IF(std::move(*IFOrErr)); 721*06c3fb27SDimitry Andric 722*06c3fb27SDimitry Andric auto IFsOrErr = StubParser::getInlinedLibs(Root); 723*06c3fb27SDimitry Andric if (!IFsOrErr) 724*06c3fb27SDimitry Andric return IFsOrErr.takeError(); 725*06c3fb27SDimitry Andric for (auto &File : *IFsOrErr) { 726*06c3fb27SDimitry Andric File->setFileType(Version); 727*06c3fb27SDimitry Andric IF->addDocument(std::shared_ptr<InterfaceFile>(std::move(File))); 728*06c3fb27SDimitry Andric } 729*06c3fb27SDimitry Andric return std::move(IF); 730*06c3fb27SDimitry Andric } 731*06c3fb27SDimitry Andric 732*06c3fb27SDimitry Andric namespace { 733*06c3fb27SDimitry Andric 734*06c3fb27SDimitry Andric template <typename ContainerT = Array> 735*06c3fb27SDimitry Andric bool insertNonEmptyValues(Object &Obj, TBDKey Key, ContainerT &&Contents) { 736*06c3fb27SDimitry Andric if (Contents.empty()) 737*06c3fb27SDimitry Andric return false; 738*06c3fb27SDimitry Andric Obj[Keys[Key]] = std::move(Contents); 739*06c3fb27SDimitry Andric return true; 740*06c3fb27SDimitry Andric } 741*06c3fb27SDimitry Andric 742*06c3fb27SDimitry Andric std::string getFormattedStr(const MachO::Target &Targ) { 743*06c3fb27SDimitry Andric std::string PlatformStr = Targ.Platform == PLATFORM_MACCATALYST 744*06c3fb27SDimitry Andric ? "maccatalyst" 745*06c3fb27SDimitry Andric : getOSAndEnvironmentName(Targ.Platform); 746*06c3fb27SDimitry Andric return (getArchitectureName(Targ.Arch) + "-" + PlatformStr).str(); 747*06c3fb27SDimitry Andric } 748*06c3fb27SDimitry Andric 749*06c3fb27SDimitry Andric template <typename AggregateT> 750*06c3fb27SDimitry Andric std::vector<std::string> serializeTargets(const AggregateT Targets, 751*06c3fb27SDimitry Andric const TargetList &ActiveTargets) { 752*06c3fb27SDimitry Andric std::vector<std::string> TargetsStr; 753*06c3fb27SDimitry Andric if (Targets.size() == ActiveTargets.size()) 754*06c3fb27SDimitry Andric return TargetsStr; 755*06c3fb27SDimitry Andric 756*06c3fb27SDimitry Andric llvm::for_each(Targets, [&TargetsStr](const MachO::Target &Target) { 757*06c3fb27SDimitry Andric TargetsStr.emplace_back(getFormattedStr(Target)); 758*06c3fb27SDimitry Andric }); 759*06c3fb27SDimitry Andric return TargetsStr; 760*06c3fb27SDimitry Andric } 761*06c3fb27SDimitry Andric 762*06c3fb27SDimitry Andric Array serializeTargetInfo(const TargetList &ActiveTargets) { 763*06c3fb27SDimitry Andric Array Targets; 764*06c3fb27SDimitry Andric for (const auto Targ : ActiveTargets) { 765*06c3fb27SDimitry Andric Object TargetInfo; 766*06c3fb27SDimitry Andric TargetInfo[Keys[TBDKey::Deployment]] = Targ.MinDeployment.getAsString(); 767*06c3fb27SDimitry Andric TargetInfo[Keys[TBDKey::Target]] = getFormattedStr(Targ); 768*06c3fb27SDimitry Andric Targets.emplace_back(std::move(TargetInfo)); 769*06c3fb27SDimitry Andric } 770*06c3fb27SDimitry Andric return Targets; 771*06c3fb27SDimitry Andric } 772*06c3fb27SDimitry Andric 773*06c3fb27SDimitry Andric template <typename ValueT, typename EntryT = ValueT> 774*06c3fb27SDimitry Andric Array serializeScalar(TBDKey Key, ValueT Value, ValueT Default = ValueT()) { 775*06c3fb27SDimitry Andric if (Value == Default) 776*06c3fb27SDimitry Andric return {}; 777*06c3fb27SDimitry Andric Array Container; 778*06c3fb27SDimitry Andric Object ScalarObj({Object::KV({Keys[Key], EntryT(Value)})}); 779*06c3fb27SDimitry Andric 780*06c3fb27SDimitry Andric Container.emplace_back(std::move(ScalarObj)); 781*06c3fb27SDimitry Andric return Container; 782*06c3fb27SDimitry Andric } 783*06c3fb27SDimitry Andric 784*06c3fb27SDimitry Andric using TargetsToValuesMap = 785*06c3fb27SDimitry Andric std::map<std::vector<std::string>, std::vector<std::string>>; 786*06c3fb27SDimitry Andric 787*06c3fb27SDimitry Andric template <typename AggregateT = TargetsToValuesMap> 788*06c3fb27SDimitry Andric Array serializeAttrToTargets(AggregateT &Entries, TBDKey Key) { 789*06c3fb27SDimitry Andric Array Container; 790*06c3fb27SDimitry Andric for (const auto &[Targets, Values] : Entries) { 791*06c3fb27SDimitry Andric Object Obj; 792*06c3fb27SDimitry Andric insertNonEmptyValues(Obj, TBDKey::Targets, std::move(Targets)); 793*06c3fb27SDimitry Andric Obj[Keys[Key]] = Values; 794*06c3fb27SDimitry Andric Container.emplace_back(std::move(Obj)); 795*06c3fb27SDimitry Andric } 796*06c3fb27SDimitry Andric return Container; 797*06c3fb27SDimitry Andric } 798*06c3fb27SDimitry Andric 799*06c3fb27SDimitry Andric template <typename ValueT = std::string, 800*06c3fb27SDimitry Andric typename AggregateT = std::vector<std::pair<MachO::Target, ValueT>>> 801*06c3fb27SDimitry Andric Array serializeField(TBDKey Key, const AggregateT &Values, 802*06c3fb27SDimitry Andric const TargetList &ActiveTargets, bool IsArray = true) { 803*06c3fb27SDimitry Andric std::map<ValueT, std::set<MachO::Target>> Entries; 804*06c3fb27SDimitry Andric for (const auto &[Target, Val] : Values) 805*06c3fb27SDimitry Andric Entries[Val].insert(Target); 806*06c3fb27SDimitry Andric 807*06c3fb27SDimitry Andric if (!IsArray) { 808*06c3fb27SDimitry Andric std::map<std::vector<std::string>, std::string> FinalEntries; 809*06c3fb27SDimitry Andric for (const auto &[Val, Targets] : Entries) 810*06c3fb27SDimitry Andric FinalEntries[serializeTargets(Targets, ActiveTargets)] = Val; 811*06c3fb27SDimitry Andric return serializeAttrToTargets(FinalEntries, Key); 812*06c3fb27SDimitry Andric } 813*06c3fb27SDimitry Andric 814*06c3fb27SDimitry Andric TargetsToValuesMap FinalEntries; 815*06c3fb27SDimitry Andric for (const auto &[Val, Targets] : Entries) 816*06c3fb27SDimitry Andric FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(Val); 817*06c3fb27SDimitry Andric return serializeAttrToTargets(FinalEntries, Key); 818*06c3fb27SDimitry Andric } 819*06c3fb27SDimitry Andric 820*06c3fb27SDimitry Andric Array serializeField(TBDKey Key, const std::vector<InterfaceFileRef> &Values, 821*06c3fb27SDimitry Andric const TargetList &ActiveTargets) { 822*06c3fb27SDimitry Andric TargetsToValuesMap FinalEntries; 823*06c3fb27SDimitry Andric for (const auto &Ref : Values) { 824*06c3fb27SDimitry Andric TargetList Targets{Ref.targets().begin(), Ref.targets().end()}; 825*06c3fb27SDimitry Andric FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back( 826*06c3fb27SDimitry Andric Ref.getInstallName()); 827*06c3fb27SDimitry Andric } 828*06c3fb27SDimitry Andric return serializeAttrToTargets(FinalEntries, Key); 829*06c3fb27SDimitry Andric } 830*06c3fb27SDimitry Andric 831*06c3fb27SDimitry Andric struct SymbolFields { 832*06c3fb27SDimitry Andric struct SymbolTypes { 833*06c3fb27SDimitry Andric std::vector<StringRef> Weaks; 834*06c3fb27SDimitry Andric std::vector<StringRef> Globals; 835*06c3fb27SDimitry Andric std::vector<StringRef> TLV; 836*06c3fb27SDimitry Andric std::vector<StringRef> ObjCClasses; 837*06c3fb27SDimitry Andric std::vector<StringRef> IVars; 838*06c3fb27SDimitry Andric std::vector<StringRef> EHTypes; 839*06c3fb27SDimitry Andric 840*06c3fb27SDimitry Andric bool empty() const { 841*06c3fb27SDimitry Andric return Weaks.empty() && Globals.empty() && TLV.empty() && 842*06c3fb27SDimitry Andric ObjCClasses.empty() && IVars.empty() && EHTypes.empty(); 843*06c3fb27SDimitry Andric } 844*06c3fb27SDimitry Andric }; 845*06c3fb27SDimitry Andric SymbolTypes Data; 846*06c3fb27SDimitry Andric SymbolTypes Text; 847*06c3fb27SDimitry Andric }; 848*06c3fb27SDimitry Andric 849*06c3fb27SDimitry Andric Array serializeSymbols(InterfaceFile::const_filtered_symbol_range Symbols, 850*06c3fb27SDimitry Andric const TargetList &ActiveTargets) { 851*06c3fb27SDimitry Andric auto AssignForSymbolType = [](SymbolFields::SymbolTypes &Assignment, 852*06c3fb27SDimitry Andric const Symbol *Sym) { 853*06c3fb27SDimitry Andric switch (Sym->getKind()) { 854*06c3fb27SDimitry Andric case SymbolKind::ObjectiveCClass: 855*06c3fb27SDimitry Andric Assignment.ObjCClasses.emplace_back(Sym->getName()); 856*06c3fb27SDimitry Andric return; 857*06c3fb27SDimitry Andric case SymbolKind::ObjectiveCClassEHType: 858*06c3fb27SDimitry Andric Assignment.EHTypes.emplace_back(Sym->getName()); 859*06c3fb27SDimitry Andric return; 860*06c3fb27SDimitry Andric case SymbolKind::ObjectiveCInstanceVariable: 861*06c3fb27SDimitry Andric Assignment.IVars.emplace_back(Sym->getName()); 862*06c3fb27SDimitry Andric return; 863*06c3fb27SDimitry Andric case SymbolKind::GlobalSymbol: { 864*06c3fb27SDimitry Andric if (Sym->isWeakReferenced() || Sym->isWeakDefined()) 865*06c3fb27SDimitry Andric Assignment.Weaks.emplace_back(Sym->getName()); 866*06c3fb27SDimitry Andric else if (Sym->isThreadLocalValue()) 867*06c3fb27SDimitry Andric Assignment.TLV.emplace_back(Sym->getName()); 868*06c3fb27SDimitry Andric else 869*06c3fb27SDimitry Andric Assignment.Globals.emplace_back(Sym->getName()); 870*06c3fb27SDimitry Andric return; 871*06c3fb27SDimitry Andric } 872*06c3fb27SDimitry Andric } 873*06c3fb27SDimitry Andric }; 874*06c3fb27SDimitry Andric 875*06c3fb27SDimitry Andric std::map<std::vector<std::string>, SymbolFields> Entries; 876*06c3fb27SDimitry Andric for (const auto *Sym : Symbols) { 877*06c3fb27SDimitry Andric std::set<MachO::Target> Targets{Sym->targets().begin(), 878*06c3fb27SDimitry Andric Sym->targets().end()}; 879*06c3fb27SDimitry Andric auto JSONTargets = serializeTargets(Targets, ActiveTargets); 880*06c3fb27SDimitry Andric if (Sym->isData()) 881*06c3fb27SDimitry Andric AssignForSymbolType(Entries[std::move(JSONTargets)].Data, Sym); 882*06c3fb27SDimitry Andric else if (Sym->isText()) 883*06c3fb27SDimitry Andric AssignForSymbolType(Entries[std::move(JSONTargets)].Text, Sym); 884*06c3fb27SDimitry Andric else 885*06c3fb27SDimitry Andric llvm_unreachable("unexpected symbol type"); 886*06c3fb27SDimitry Andric } 887*06c3fb27SDimitry Andric 888*06c3fb27SDimitry Andric auto InsertSymbolsToJSON = [](Object &SymSection, TBDKey SegmentKey, 889*06c3fb27SDimitry Andric SymbolFields::SymbolTypes &SymField) { 890*06c3fb27SDimitry Andric if (SymField.empty()) 891*06c3fb27SDimitry Andric return; 892*06c3fb27SDimitry Andric Object Segment; 893*06c3fb27SDimitry Andric insertNonEmptyValues(Segment, TBDKey::Globals, std::move(SymField.Globals)); 894*06c3fb27SDimitry Andric insertNonEmptyValues(Segment, TBDKey::ThreadLocal, std::move(SymField.TLV)); 895*06c3fb27SDimitry Andric insertNonEmptyValues(Segment, TBDKey::Weak, std::move(SymField.Weaks)); 896*06c3fb27SDimitry Andric insertNonEmptyValues(Segment, TBDKey::ObjCClass, 897*06c3fb27SDimitry Andric std::move(SymField.ObjCClasses)); 898*06c3fb27SDimitry Andric insertNonEmptyValues(Segment, TBDKey::ObjCEHType, 899*06c3fb27SDimitry Andric std::move(SymField.EHTypes)); 900*06c3fb27SDimitry Andric insertNonEmptyValues(Segment, TBDKey::ObjCIvar, std::move(SymField.IVars)); 901*06c3fb27SDimitry Andric insertNonEmptyValues(SymSection, SegmentKey, std::move(Segment)); 902*06c3fb27SDimitry Andric }; 903*06c3fb27SDimitry Andric 904*06c3fb27SDimitry Andric Array SymbolSection; 905*06c3fb27SDimitry Andric for (auto &[Targets, Fields] : Entries) { 906*06c3fb27SDimitry Andric Object AllSyms; 907*06c3fb27SDimitry Andric insertNonEmptyValues(AllSyms, TBDKey::Targets, std::move(Targets)); 908*06c3fb27SDimitry Andric InsertSymbolsToJSON(AllSyms, TBDKey::Data, Fields.Data); 909*06c3fb27SDimitry Andric InsertSymbolsToJSON(AllSyms, TBDKey::Text, Fields.Text); 910*06c3fb27SDimitry Andric SymbolSection.emplace_back(std::move(AllSyms)); 911*06c3fb27SDimitry Andric } 912*06c3fb27SDimitry Andric 913*06c3fb27SDimitry Andric return SymbolSection; 914*06c3fb27SDimitry Andric } 915*06c3fb27SDimitry Andric 916*06c3fb27SDimitry Andric Array serializeFlags(const InterfaceFile *File) { 917*06c3fb27SDimitry Andric // TODO: Give all Targets the same flags for now. 918*06c3fb27SDimitry Andric Array Flags; 919*06c3fb27SDimitry Andric if (!File->isTwoLevelNamespace()) 920*06c3fb27SDimitry Andric Flags.emplace_back("flat_namespace"); 921*06c3fb27SDimitry Andric if (!File->isApplicationExtensionSafe()) 922*06c3fb27SDimitry Andric Flags.emplace_back("not_app_extension_safe"); 923*06c3fb27SDimitry Andric return serializeScalar(TBDKey::Attributes, std::move(Flags)); 924*06c3fb27SDimitry Andric } 925*06c3fb27SDimitry Andric 926*06c3fb27SDimitry Andric Expected<Object> serializeIF(const InterfaceFile *File) { 927*06c3fb27SDimitry Andric Object Library; 928*06c3fb27SDimitry Andric 929*06c3fb27SDimitry Andric // Handle required keys. 930*06c3fb27SDimitry Andric TargetList ActiveTargets{File->targets().begin(), File->targets().end()}; 931*06c3fb27SDimitry Andric if (!insertNonEmptyValues(Library, TBDKey::TargetInfo, 932*06c3fb27SDimitry Andric serializeTargetInfo(ActiveTargets))) 933*06c3fb27SDimitry Andric return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::TargetInfo)); 934*06c3fb27SDimitry Andric 935*06c3fb27SDimitry Andric Array Name = serializeScalar<StringRef>(TBDKey::Name, File->getInstallName()); 936*06c3fb27SDimitry Andric if (!insertNonEmptyValues(Library, TBDKey::InstallName, std::move(Name))) 937*06c3fb27SDimitry Andric return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::InstallName)); 938*06c3fb27SDimitry Andric 939*06c3fb27SDimitry Andric // Handle optional keys. 940*06c3fb27SDimitry Andric Array Flags = serializeFlags(File); 941*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::Flags, std::move(Flags)); 942*06c3fb27SDimitry Andric 943*06c3fb27SDimitry Andric Array CurrentV = serializeScalar<PackedVersion, std::string>( 944*06c3fb27SDimitry Andric TBDKey::Version, File->getCurrentVersion(), PackedVersion(1, 0, 0)); 945*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::CurrentVersion, std::move(CurrentV)); 946*06c3fb27SDimitry Andric 947*06c3fb27SDimitry Andric Array CompatV = serializeScalar<PackedVersion, std::string>( 948*06c3fb27SDimitry Andric TBDKey::Version, File->getCompatibilityVersion(), PackedVersion(1, 0, 0)); 949*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::CompatibilityVersion, 950*06c3fb27SDimitry Andric std::move(CompatV)); 951*06c3fb27SDimitry Andric 952*06c3fb27SDimitry Andric Array SwiftABI = serializeScalar<uint8_t, int64_t>( 953*06c3fb27SDimitry Andric TBDKey::ABI, File->getSwiftABIVersion(), 0u); 954*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::SwiftABI, std::move(SwiftABI)); 955*06c3fb27SDimitry Andric 956*06c3fb27SDimitry Andric Array RPaths = serializeField(TBDKey::Paths, File->rpaths(), ActiveTargets); 957*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::RPath, std::move(RPaths)); 958*06c3fb27SDimitry Andric 959*06c3fb27SDimitry Andric Array Umbrellas = serializeField(TBDKey::Umbrella, File->umbrellas(), 960*06c3fb27SDimitry Andric ActiveTargets, /*IsArray=*/false); 961*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::ParentUmbrella, std::move(Umbrellas)); 962*06c3fb27SDimitry Andric 963*06c3fb27SDimitry Andric Array Clients = 964*06c3fb27SDimitry Andric serializeField(TBDKey::Clients, File->allowableClients(), ActiveTargets); 965*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::AllowableClients, std::move(Clients)); 966*06c3fb27SDimitry Andric 967*06c3fb27SDimitry Andric Array ReexportLibs = 968*06c3fb27SDimitry Andric serializeField(TBDKey::Names, File->reexportedLibraries(), ActiveTargets); 969*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::ReexportLibs, std::move(ReexportLibs)); 970*06c3fb27SDimitry Andric 971*06c3fb27SDimitry Andric // Handle symbols. 972*06c3fb27SDimitry Andric Array Exports = serializeSymbols(File->exports(), ActiveTargets); 973*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::Exports, std::move(Exports)); 974*06c3fb27SDimitry Andric 975*06c3fb27SDimitry Andric Array Reexports = serializeSymbols(File->reexports(), ActiveTargets); 976*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::Reexports, std::move(Reexports)); 977*06c3fb27SDimitry Andric 978*06c3fb27SDimitry Andric if (!File->isTwoLevelNamespace()) { 979*06c3fb27SDimitry Andric Array Undefineds = serializeSymbols(File->undefineds(), ActiveTargets); 980*06c3fb27SDimitry Andric insertNonEmptyValues(Library, TBDKey::Undefineds, std::move(Undefineds)); 981*06c3fb27SDimitry Andric } 982*06c3fb27SDimitry Andric 983*06c3fb27SDimitry Andric return std::move(Library); 984*06c3fb27SDimitry Andric } 985*06c3fb27SDimitry Andric 986*06c3fb27SDimitry Andric Expected<Object> getJSON(const InterfaceFile *File) { 987*06c3fb27SDimitry Andric assert(File->getFileType() == FileType::TBD_V5 && 988*06c3fb27SDimitry Andric "unexpected json file format version"); 989*06c3fb27SDimitry Andric Object Root; 990*06c3fb27SDimitry Andric 991*06c3fb27SDimitry Andric auto MainLibOrErr = serializeIF(File); 992*06c3fb27SDimitry Andric if (!MainLibOrErr) 993*06c3fb27SDimitry Andric return MainLibOrErr; 994*06c3fb27SDimitry Andric Root[Keys[TBDKey::MainLibrary]] = std::move(*MainLibOrErr); 995*06c3fb27SDimitry Andric Array Documents; 996*06c3fb27SDimitry Andric for (const auto &Doc : File->documents()) { 997*06c3fb27SDimitry Andric auto LibOrErr = serializeIF(Doc.get()); 998*06c3fb27SDimitry Andric if (!LibOrErr) 999*06c3fb27SDimitry Andric return LibOrErr; 1000*06c3fb27SDimitry Andric Documents.emplace_back(std::move(*LibOrErr)); 1001*06c3fb27SDimitry Andric } 1002*06c3fb27SDimitry Andric 1003*06c3fb27SDimitry Andric Root[Keys[TBDKey::TBDVersion]] = 5; 1004*06c3fb27SDimitry Andric insertNonEmptyValues(Root, TBDKey::Documents, std::move(Documents)); 1005*06c3fb27SDimitry Andric return std::move(Root); 1006*06c3fb27SDimitry Andric } 1007*06c3fb27SDimitry Andric 1008*06c3fb27SDimitry Andric } // namespace 1009*06c3fb27SDimitry Andric 1010*06c3fb27SDimitry Andric Error MachO::serializeInterfaceFileToJSON(raw_ostream &OS, 1011*06c3fb27SDimitry Andric const InterfaceFile &File, 1012*06c3fb27SDimitry Andric bool Compact) { 1013*06c3fb27SDimitry Andric auto TextFile = getJSON(&File); 1014*06c3fb27SDimitry Andric if (!TextFile) 1015*06c3fb27SDimitry Andric return TextFile.takeError(); 1016*06c3fb27SDimitry Andric if (Compact) 1017*06c3fb27SDimitry Andric OS << formatv("{0}", Value(std::move(*TextFile))) << "\n"; 1018*06c3fb27SDimitry Andric else 1019*06c3fb27SDimitry Andric OS << formatv("{0:2}", Value(std::move(*TextFile))) << "\n"; 1020*06c3fb27SDimitry Andric return Error::success(); 1021*06c3fb27SDimitry Andric } 1022