xref: /src/contrib/llvm-project/llvm/lib/TextAPI/TextStubV5.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
17fa27ce4SDimitry Andric //===- TextStubV5.cpp -----------------------------------------------------===//
27fa27ce4SDimitry Andric //
37fa27ce4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47fa27ce4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
57fa27ce4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67fa27ce4SDimitry Andric //
77fa27ce4SDimitry Andric //===----------------------------------------------------------------------===//
87fa27ce4SDimitry Andric //
97fa27ce4SDimitry Andric // Implements Text Stub JSON mappings.
107fa27ce4SDimitry Andric //
117fa27ce4SDimitry Andric //===----------------------------------------------------------------------===//
127fa27ce4SDimitry Andric #include "TextStubCommon.h"
137fa27ce4SDimitry Andric #include "llvm/ADT/StringSwitch.h"
147fa27ce4SDimitry Andric #include "llvm/Support/JSON.h"
157fa27ce4SDimitry Andric #include <utility>
167fa27ce4SDimitry Andric 
177fa27ce4SDimitry Andric // clang-format off
187fa27ce4SDimitry Andric /*
197fa27ce4SDimitry Andric 
207fa27ce4SDimitry Andric JSON Format specification.
217fa27ce4SDimitry Andric 
227fa27ce4SDimitry Andric All library level keys, accept target values and are defaulted if not specified.
237fa27ce4SDimitry Andric 
247fa27ce4SDimitry Andric {
257fa27ce4SDimitry Andric "tapi_tbd_version": 5,                            # Required: TBD version for all documents in file
267fa27ce4SDimitry Andric "main_library": {                                 # Required: top level library
277fa27ce4SDimitry Andric   "target_info": [                                # Required: target information
287fa27ce4SDimitry Andric     {
297fa27ce4SDimitry Andric       "target": "x86_64-macos",
30b1c73532SDimitry Andric       "min_deployment": "10.14"                   # Optional: minOS defaults to 0
317fa27ce4SDimitry Andric     },
327fa27ce4SDimitry Andric     {
337fa27ce4SDimitry Andric       "target": "arm64-macos",
347fa27ce4SDimitry Andric       "min_deployment": "10.14"
357fa27ce4SDimitry Andric     },
367fa27ce4SDimitry Andric     {
377fa27ce4SDimitry Andric       "target": "arm64-maccatalyst",
387fa27ce4SDimitry Andric       "min_deployment": "12.1"
397fa27ce4SDimitry Andric     }],
407fa27ce4SDimitry Andric   "flags":[{"attributes": ["flat_namespace"]}],     # Optional:
417fa27ce4SDimitry Andric   "install_names":[{"name":"/S/L/F/Foo.fwk/Foo"}],  # Required: library install name
427fa27ce4SDimitry Andric   "current_versions":[{"version": "1.2"}],          # Optional: defaults to 1
437fa27ce4SDimitry Andric   "compatibility_versions":[{ "version": "1.1"}],   # Optional: defaults to 1
447fa27ce4SDimitry Andric   "rpaths": [                                       # Optional:
457fa27ce4SDimitry Andric     {
467fa27ce4SDimitry Andric       "targets": ["x86_64-macos"],                  # Optional: defaults to targets in `target-info`
477fa27ce4SDimitry Andric       "paths": ["@executable_path/.../Frameworks"]
487fa27ce4SDimitry Andric     }],
497fa27ce4SDimitry Andric   "parent_umbrellas": [{"umbrella": "System"}],
507fa27ce4SDimitry Andric   "allowable_clients": [{"clients": ["ClientA"]}],
517fa27ce4SDimitry Andric   "reexported_libraries": [{"names": ["/u/l/l/foo.dylib"]}],
527fa27ce4SDimitry Andric   "exported_symbols": [{                            # List of export symbols section
537fa27ce4SDimitry Andric       "targets": ["x86_64-macos", "arm64-macos"],   # Optional: defaults to targets in `target-info`
547fa27ce4SDimitry Andric         "text": {                                   # List of Text segment symbols
557fa27ce4SDimitry Andric           "global": [ "_func" ],
567fa27ce4SDimitry Andric           "weak": [],
577fa27ce4SDimitry Andric           "thread_local": []
587fa27ce4SDimitry Andric         },
597fa27ce4SDimitry Andric         "data": { ... },                            # List of Data segment symbols
607fa27ce4SDimitry Andric    }],
617fa27ce4SDimitry Andric   "reexported_symbols": [{  ... }],                 # List of reexported symbols section
627fa27ce4SDimitry Andric   "undefined_symbols": [{ ... }]                    # List of undefined symbols section
637fa27ce4SDimitry Andric },
647fa27ce4SDimitry Andric "libraries": [                                      # Optional: Array of inlined libraries
657fa27ce4SDimitry Andric   {...}, {...}, {...}
667fa27ce4SDimitry Andric ]
677fa27ce4SDimitry Andric }
687fa27ce4SDimitry Andric */
697fa27ce4SDimitry Andric // clang-format on
707fa27ce4SDimitry Andric 
717fa27ce4SDimitry Andric using namespace llvm;
727fa27ce4SDimitry Andric using namespace llvm::json;
737fa27ce4SDimitry Andric using namespace llvm::MachO;
747fa27ce4SDimitry Andric 
757fa27ce4SDimitry Andric namespace {
767fa27ce4SDimitry Andric struct JSONSymbol {
77ac9a064cSDimitry Andric   EncodeKind Kind;
787fa27ce4SDimitry Andric   std::string Name;
797fa27ce4SDimitry Andric   SymbolFlags Flags;
807fa27ce4SDimitry Andric };
817fa27ce4SDimitry Andric 
827fa27ce4SDimitry Andric using AttrToTargets = std::map<std::string, TargetList>;
837fa27ce4SDimitry Andric using TargetsToSymbols =
847fa27ce4SDimitry Andric     SmallVector<std::pair<TargetList, std::vector<JSONSymbol>>>;
857fa27ce4SDimitry Andric 
867fa27ce4SDimitry Andric enum TBDKey : size_t {
877fa27ce4SDimitry Andric   TBDVersion = 0U,
887fa27ce4SDimitry Andric   MainLibrary,
897fa27ce4SDimitry Andric   Documents,
907fa27ce4SDimitry Andric   TargetInfo,
917fa27ce4SDimitry Andric   Targets,
927fa27ce4SDimitry Andric   Target,
937fa27ce4SDimitry Andric   Deployment,
947fa27ce4SDimitry Andric   Flags,
957fa27ce4SDimitry Andric   Attributes,
967fa27ce4SDimitry Andric   InstallName,
977fa27ce4SDimitry Andric   CurrentVersion,
987fa27ce4SDimitry Andric   CompatibilityVersion,
997fa27ce4SDimitry Andric   Version,
1007fa27ce4SDimitry Andric   SwiftABI,
1017fa27ce4SDimitry Andric   ABI,
1027fa27ce4SDimitry Andric   ParentUmbrella,
1037fa27ce4SDimitry Andric   Umbrella,
1047fa27ce4SDimitry Andric   AllowableClients,
1057fa27ce4SDimitry Andric   Clients,
1067fa27ce4SDimitry Andric   ReexportLibs,
1077fa27ce4SDimitry Andric   Names,
1087fa27ce4SDimitry Andric   Name,
1097fa27ce4SDimitry Andric   Exports,
1107fa27ce4SDimitry Andric   Reexports,
1117fa27ce4SDimitry Andric   Undefineds,
1127fa27ce4SDimitry Andric   Data,
1137fa27ce4SDimitry Andric   Text,
1147fa27ce4SDimitry Andric   Weak,
1157fa27ce4SDimitry Andric   ThreadLocal,
1167fa27ce4SDimitry Andric   Globals,
1177fa27ce4SDimitry Andric   ObjCClass,
1187fa27ce4SDimitry Andric   ObjCEHType,
1197fa27ce4SDimitry Andric   ObjCIvar,
1207fa27ce4SDimitry Andric   RPath,
1217fa27ce4SDimitry Andric   Paths,
1227fa27ce4SDimitry Andric };
1237fa27ce4SDimitry Andric 
1247fa27ce4SDimitry Andric std::array<StringRef, 64> Keys = {
1257fa27ce4SDimitry Andric     "tapi_tbd_version",
1267fa27ce4SDimitry Andric     "main_library",
1277fa27ce4SDimitry Andric     "libraries",
1287fa27ce4SDimitry Andric     "target_info",
1297fa27ce4SDimitry Andric     "targets",
1307fa27ce4SDimitry Andric     "target",
1317fa27ce4SDimitry Andric     "min_deployment",
1327fa27ce4SDimitry Andric     "flags",
1337fa27ce4SDimitry Andric     "attributes",
1347fa27ce4SDimitry Andric     "install_names",
1357fa27ce4SDimitry Andric     "current_versions",
1367fa27ce4SDimitry Andric     "compatibility_versions",
1377fa27ce4SDimitry Andric     "version",
1387fa27ce4SDimitry Andric     "swift_abi",
1397fa27ce4SDimitry Andric     "abi",
1407fa27ce4SDimitry Andric     "parent_umbrellas",
1417fa27ce4SDimitry Andric     "umbrella",
1427fa27ce4SDimitry Andric     "allowable_clients",
1437fa27ce4SDimitry Andric     "clients",
1447fa27ce4SDimitry Andric     "reexported_libraries",
1457fa27ce4SDimitry Andric     "names",
1467fa27ce4SDimitry Andric     "name",
1477fa27ce4SDimitry Andric     "exported_symbols",
1487fa27ce4SDimitry Andric     "reexported_symbols",
1497fa27ce4SDimitry Andric     "undefined_symbols",
1507fa27ce4SDimitry Andric     "data",
1517fa27ce4SDimitry Andric     "text",
1527fa27ce4SDimitry Andric     "weak",
1537fa27ce4SDimitry Andric     "thread_local",
1547fa27ce4SDimitry Andric     "global",
1557fa27ce4SDimitry Andric     "objc_class",
1567fa27ce4SDimitry Andric     "objc_eh_type",
1577fa27ce4SDimitry Andric     "objc_ivar",
1587fa27ce4SDimitry Andric     "rpaths",
1597fa27ce4SDimitry Andric     "paths",
1607fa27ce4SDimitry Andric };
1617fa27ce4SDimitry Andric 
getParseErrorMsg(TBDKey Key)1627fa27ce4SDimitry Andric static llvm::SmallString<128> getParseErrorMsg(TBDKey Key) {
1637fa27ce4SDimitry Andric   return {"invalid ", Keys[Key], " section"};
1647fa27ce4SDimitry Andric }
1657fa27ce4SDimitry Andric 
getSerializeErrorMsg(TBDKey Key)1667fa27ce4SDimitry Andric static llvm::SmallString<128> getSerializeErrorMsg(TBDKey Key) {
1677fa27ce4SDimitry Andric   return {"missing ", Keys[Key], " information"};
1687fa27ce4SDimitry Andric }
1697fa27ce4SDimitry Andric 
1707fa27ce4SDimitry Andric class JSONStubError : public llvm::ErrorInfo<llvm::json::ParseError> {
1717fa27ce4SDimitry Andric public:
JSONStubError(Twine ErrMsg)1727fa27ce4SDimitry Andric   JSONStubError(Twine ErrMsg) : Message(ErrMsg.str()) {}
1737fa27ce4SDimitry Andric 
log(llvm::raw_ostream & OS) const1747fa27ce4SDimitry Andric   void log(llvm::raw_ostream &OS) const override { OS << Message << "\n"; }
convertToErrorCode() const1757fa27ce4SDimitry Andric   std::error_code convertToErrorCode() const override {
1767fa27ce4SDimitry Andric     return llvm::inconvertibleErrorCode();
1777fa27ce4SDimitry Andric   }
1787fa27ce4SDimitry Andric 
1797fa27ce4SDimitry Andric private:
1807fa27ce4SDimitry Andric   std::string Message;
1817fa27ce4SDimitry Andric };
1827fa27ce4SDimitry Andric 
1837fa27ce4SDimitry Andric template <typename JsonT, typename StubT = JsonT>
getRequiredValue(TBDKey Key,const Object * Obj,std::function<std::optional<JsonT> (const Object *,StringRef)> GetValue,std::function<std::optional<StubT> (JsonT)> Validate=nullptr)1847fa27ce4SDimitry Andric Expected<StubT> getRequiredValue(
1857fa27ce4SDimitry Andric     TBDKey Key, const Object *Obj,
1867fa27ce4SDimitry Andric     std::function<std::optional<JsonT>(const Object *, StringRef)> GetValue,
1877fa27ce4SDimitry Andric     std::function<std::optional<StubT>(JsonT)> Validate = nullptr) {
1887fa27ce4SDimitry Andric   std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
1897fa27ce4SDimitry Andric   if (!Val)
1907fa27ce4SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(Key));
1917fa27ce4SDimitry Andric 
1927fa27ce4SDimitry Andric   if (Validate == nullptr)
1937fa27ce4SDimitry Andric     return static_cast<StubT>(*Val);
1947fa27ce4SDimitry Andric 
1957fa27ce4SDimitry Andric   std::optional<StubT> Result = Validate(*Val);
1967fa27ce4SDimitry Andric   if (!Result.has_value())
1977fa27ce4SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(Key));
1987fa27ce4SDimitry Andric   return Result.value();
1997fa27ce4SDimitry Andric }
2007fa27ce4SDimitry Andric 
2017fa27ce4SDimitry Andric template <typename JsonT, typename StubT = JsonT>
getRequiredValue(TBDKey Key,const Object * Obj,std::function<std::optional<JsonT> (const Object *,StringRef)> const GetValue,StubT DefaultValue,function_ref<std::optional<StubT> (JsonT)> Validate)2027fa27ce4SDimitry Andric Expected<StubT> getRequiredValue(
2037fa27ce4SDimitry Andric     TBDKey Key, const Object *Obj,
20477dbea07SDimitry Andric     std::function<std::optional<JsonT>(const Object *, StringRef)> const
20577dbea07SDimitry Andric         GetValue,
20677dbea07SDimitry Andric     StubT DefaultValue, function_ref<std::optional<StubT>(JsonT)> Validate) {
2077fa27ce4SDimitry Andric   std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
2087fa27ce4SDimitry Andric   if (!Val)
2097fa27ce4SDimitry Andric     return DefaultValue;
2107fa27ce4SDimitry Andric 
2117fa27ce4SDimitry Andric   std::optional<StubT> Result;
2127fa27ce4SDimitry Andric   Result = Validate(*Val);
2137fa27ce4SDimitry Andric   if (!Result.has_value())
2147fa27ce4SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(Key));
2157fa27ce4SDimitry Andric   return Result.value();
2167fa27ce4SDimitry Andric }
2177fa27ce4SDimitry Andric 
collectFromArray(TBDKey Key,const Object * Obj,function_ref<void (StringRef)> Append,bool IsRequired=false)2187fa27ce4SDimitry Andric Error collectFromArray(TBDKey Key, const Object *Obj,
21977dbea07SDimitry Andric                        function_ref<void(StringRef)> Append,
2207fa27ce4SDimitry Andric                        bool IsRequired = false) {
2217fa27ce4SDimitry Andric   const auto *Values = Obj->getArray(Keys[Key]);
2227fa27ce4SDimitry Andric   if (!Values) {
2237fa27ce4SDimitry Andric     if (IsRequired)
2247fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(Key));
2257fa27ce4SDimitry Andric     return Error::success();
2267fa27ce4SDimitry Andric   }
2277fa27ce4SDimitry Andric 
2287fa27ce4SDimitry Andric   for (const Value &Val : *Values) {
2297fa27ce4SDimitry Andric     auto ValStr = Val.getAsString();
2307fa27ce4SDimitry Andric     if (!ValStr.has_value())
2317fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(Key));
2327fa27ce4SDimitry Andric     Append(ValStr.value());
2337fa27ce4SDimitry Andric   }
2347fa27ce4SDimitry Andric 
2357fa27ce4SDimitry Andric   return Error::success();
2367fa27ce4SDimitry Andric }
2377fa27ce4SDimitry Andric 
2387fa27ce4SDimitry Andric namespace StubParser {
2397fa27ce4SDimitry Andric 
getVersion(const Object * File)2407fa27ce4SDimitry Andric Expected<FileType> getVersion(const Object *File) {
2417fa27ce4SDimitry Andric   auto VersionOrErr = getRequiredValue<int64_t, FileType>(
2427fa27ce4SDimitry Andric       TBDKey::TBDVersion, File, &Object::getInteger,
2437fa27ce4SDimitry Andric       [](int64_t Val) -> std::optional<FileType> {
2447fa27ce4SDimitry Andric         unsigned Result = Val;
2457fa27ce4SDimitry Andric         if (Result != 5)
2467fa27ce4SDimitry Andric           return std::nullopt;
2477fa27ce4SDimitry Andric         return FileType::TBD_V5;
2487fa27ce4SDimitry Andric       });
2497fa27ce4SDimitry Andric 
2507fa27ce4SDimitry Andric   if (!VersionOrErr)
2517fa27ce4SDimitry Andric     return VersionOrErr.takeError();
2527fa27ce4SDimitry Andric   return *VersionOrErr;
2537fa27ce4SDimitry Andric }
2547fa27ce4SDimitry Andric 
getTargets(const Object * Section)2557fa27ce4SDimitry Andric Expected<TargetList> getTargets(const Object *Section) {
2567fa27ce4SDimitry Andric   const auto *Targets = Section->getArray(Keys[TBDKey::Targets]);
2577fa27ce4SDimitry Andric   if (!Targets)
2587fa27ce4SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets));
2597fa27ce4SDimitry Andric 
2607fa27ce4SDimitry Andric   TargetList IFTargets;
2617fa27ce4SDimitry Andric   for (const Value &JSONTarget : *Targets) {
2627fa27ce4SDimitry Andric     auto TargetStr = JSONTarget.getAsString();
2637fa27ce4SDimitry Andric     if (!TargetStr.has_value())
2647fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
2657fa27ce4SDimitry Andric     auto TargetOrErr = Target::create(TargetStr.value());
2667fa27ce4SDimitry Andric     if (!TargetOrErr)
2677fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
2687fa27ce4SDimitry Andric     IFTargets.push_back(*TargetOrErr);
2697fa27ce4SDimitry Andric   }
2707fa27ce4SDimitry Andric   return std::move(IFTargets);
2717fa27ce4SDimitry Andric }
2727fa27ce4SDimitry Andric 
getTargetsSection(const Object * Section)2737fa27ce4SDimitry Andric Expected<TargetList> getTargetsSection(const Object *Section) {
2747fa27ce4SDimitry Andric   const Array *Targets = Section->getArray(Keys[TBDKey::TargetInfo]);
2757fa27ce4SDimitry Andric   if (!Targets)
2767fa27ce4SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets));
2777fa27ce4SDimitry Andric 
2787fa27ce4SDimitry Andric   TargetList IFTargets;
2797fa27ce4SDimitry Andric   for (const Value &JSONTarget : *Targets) {
2807fa27ce4SDimitry Andric     const auto *Obj = JSONTarget.getAsObject();
2817fa27ce4SDimitry Andric     if (!Obj)
2827fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
2837fa27ce4SDimitry Andric     auto TargetStr =
2847fa27ce4SDimitry Andric         getRequiredValue<StringRef>(TBDKey::Target, Obj, &Object::getString);
2857fa27ce4SDimitry Andric     if (!TargetStr)
2867fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
2877fa27ce4SDimitry Andric     auto TargetOrErr = Target::create(*TargetStr);
2887fa27ce4SDimitry Andric     if (!TargetOrErr)
2897fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
290b1c73532SDimitry Andric 
291b1c73532SDimitry Andric     auto VersionStr = Obj->getString(Keys[TBDKey::Deployment]);
292b1c73532SDimitry Andric     VersionTuple Version;
293b1c73532SDimitry Andric     if (VersionStr && Version.tryParse(*VersionStr))
294b1c73532SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Deployment));
2957fa27ce4SDimitry Andric     TargetOrErr->MinDeployment = Version;
296b1c73532SDimitry Andric 
2977fa27ce4SDimitry Andric     // Convert to LLVM::Triple to accurately compute minOS + platform + arch
2987fa27ce4SDimitry Andric     // pairing.
2997fa27ce4SDimitry Andric     IFTargets.push_back(
3007fa27ce4SDimitry Andric         MachO::Target(Triple(getTargetTripleName(*TargetOrErr))));
3017fa27ce4SDimitry Andric   }
3027fa27ce4SDimitry Andric   return std::move(IFTargets);
3037fa27ce4SDimitry Andric }
3047fa27ce4SDimitry Andric 
collectSymbolsFromSegment(const Object * Segment,TargetsToSymbols & Result,SymbolFlags SectionFlag)3057fa27ce4SDimitry Andric Error collectSymbolsFromSegment(const Object *Segment, TargetsToSymbols &Result,
3067fa27ce4SDimitry Andric                                 SymbolFlags SectionFlag) {
3077fa27ce4SDimitry Andric   auto Err = collectFromArray(
3087fa27ce4SDimitry Andric       TBDKey::Globals, Segment, [&Result, &SectionFlag](StringRef Name) {
309ac9a064cSDimitry Andric         JSONSymbol Sym = {EncodeKind::GlobalSymbol, Name.str(), SectionFlag};
3107fa27ce4SDimitry Andric         Result.back().second.emplace_back(Sym);
3117fa27ce4SDimitry Andric       });
3127fa27ce4SDimitry Andric   if (Err)
3137fa27ce4SDimitry Andric     return Err;
3147fa27ce4SDimitry Andric 
3157fa27ce4SDimitry Andric   Err = collectFromArray(
3167fa27ce4SDimitry Andric       TBDKey::ObjCClass, Segment, [&Result, &SectionFlag](StringRef Name) {
317ac9a064cSDimitry Andric         JSONSymbol Sym = {EncodeKind::ObjectiveCClass, Name.str(), SectionFlag};
3187fa27ce4SDimitry Andric         Result.back().second.emplace_back(Sym);
3197fa27ce4SDimitry Andric       });
3207fa27ce4SDimitry Andric   if (Err)
3217fa27ce4SDimitry Andric     return Err;
3227fa27ce4SDimitry Andric 
3237fa27ce4SDimitry Andric   Err = collectFromArray(TBDKey::ObjCEHType, Segment,
3247fa27ce4SDimitry Andric                          [&Result, &SectionFlag](StringRef Name) {
325ac9a064cSDimitry Andric                            JSONSymbol Sym = {EncodeKind::ObjectiveCClassEHType,
3267fa27ce4SDimitry Andric                                              Name.str(), SectionFlag};
3277fa27ce4SDimitry Andric                            Result.back().second.emplace_back(Sym);
3287fa27ce4SDimitry Andric                          });
3297fa27ce4SDimitry Andric   if (Err)
3307fa27ce4SDimitry Andric     return Err;
3317fa27ce4SDimitry Andric 
3327fa27ce4SDimitry Andric   Err = collectFromArray(
3337fa27ce4SDimitry Andric       TBDKey::ObjCIvar, Segment, [&Result, &SectionFlag](StringRef Name) {
334ac9a064cSDimitry Andric         JSONSymbol Sym = {EncodeKind::ObjectiveCInstanceVariable, Name.str(),
3357fa27ce4SDimitry Andric                           SectionFlag};
3367fa27ce4SDimitry Andric         Result.back().second.emplace_back(Sym);
3377fa27ce4SDimitry Andric       });
3387fa27ce4SDimitry Andric   if (Err)
3397fa27ce4SDimitry Andric     return Err;
3407fa27ce4SDimitry Andric 
3417fa27ce4SDimitry Andric   SymbolFlags WeakFlag =
3427fa27ce4SDimitry Andric       SectionFlag |
3437fa27ce4SDimitry Andric       (((SectionFlag & SymbolFlags::Undefined) == SymbolFlags::Undefined)
3447fa27ce4SDimitry Andric            ? SymbolFlags::WeakReferenced
3457fa27ce4SDimitry Andric            : SymbolFlags::WeakDefined);
3467fa27ce4SDimitry Andric   Err = collectFromArray(
3477fa27ce4SDimitry Andric       TBDKey::Weak, Segment, [&Result, WeakFlag](StringRef Name) {
348ac9a064cSDimitry Andric         JSONSymbol Sym = {EncodeKind::GlobalSymbol, Name.str(), WeakFlag};
3497fa27ce4SDimitry Andric         Result.back().second.emplace_back(Sym);
3507fa27ce4SDimitry Andric       });
3517fa27ce4SDimitry Andric   if (Err)
3527fa27ce4SDimitry Andric     return Err;
3537fa27ce4SDimitry Andric 
3547fa27ce4SDimitry Andric   Err = collectFromArray(
3557fa27ce4SDimitry Andric       TBDKey::ThreadLocal, Segment, [&Result, SectionFlag](StringRef Name) {
356ac9a064cSDimitry Andric         JSONSymbol Sym = {EncodeKind::GlobalSymbol, Name.str(),
3577fa27ce4SDimitry Andric                           SymbolFlags::ThreadLocalValue | SectionFlag};
3587fa27ce4SDimitry Andric         Result.back().second.emplace_back(Sym);
3597fa27ce4SDimitry Andric       });
3607fa27ce4SDimitry Andric   if (Err)
3617fa27ce4SDimitry Andric     return Err;
3627fa27ce4SDimitry Andric 
3637fa27ce4SDimitry Andric   return Error::success();
3647fa27ce4SDimitry Andric }
3657fa27ce4SDimitry Andric 
getNameSection(const Object * File)3667fa27ce4SDimitry Andric Expected<StringRef> getNameSection(const Object *File) {
3677fa27ce4SDimitry Andric   const Array *Section = File->getArray(Keys[TBDKey::InstallName]);
3687fa27ce4SDimitry Andric   if (!Section)
3697fa27ce4SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName));
3707fa27ce4SDimitry Andric 
3717fa27ce4SDimitry Andric   assert(!Section->empty() && "unexpected missing install name");
3727fa27ce4SDimitry Andric   // TODO: Just take first for now.
3737fa27ce4SDimitry Andric   const auto *Obj = Section->front().getAsObject();
3747fa27ce4SDimitry Andric   if (!Obj)
3757fa27ce4SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName));
3767fa27ce4SDimitry Andric 
3777fa27ce4SDimitry Andric   return getRequiredValue<StringRef>(TBDKey::Name, Obj, &Object::getString);
3787fa27ce4SDimitry Andric }
3797fa27ce4SDimitry Andric 
getSymbolSection(const Object * File,TBDKey Key,TargetList & Targets)3807fa27ce4SDimitry Andric Expected<TargetsToSymbols> getSymbolSection(const Object *File, TBDKey Key,
3817fa27ce4SDimitry Andric                                             TargetList &Targets) {
3827fa27ce4SDimitry Andric 
3837fa27ce4SDimitry Andric   const Array *Section = File->getArray(Keys[Key]);
3847fa27ce4SDimitry Andric   if (!Section)
3857fa27ce4SDimitry Andric     return TargetsToSymbols();
3867fa27ce4SDimitry Andric 
3877fa27ce4SDimitry Andric   SymbolFlags SectionFlag;
3887fa27ce4SDimitry Andric   switch (Key) {
3897fa27ce4SDimitry Andric   case TBDKey::Reexports:
3907fa27ce4SDimitry Andric     SectionFlag = SymbolFlags::Rexported;
3917fa27ce4SDimitry Andric     break;
3927fa27ce4SDimitry Andric   case TBDKey::Undefineds:
3937fa27ce4SDimitry Andric     SectionFlag = SymbolFlags::Undefined;
3947fa27ce4SDimitry Andric     break;
3957fa27ce4SDimitry Andric   default:
3967fa27ce4SDimitry Andric     SectionFlag = SymbolFlags::None;
3977fa27ce4SDimitry Andric     break;
3987fa27ce4SDimitry Andric   };
3997fa27ce4SDimitry Andric 
4007fa27ce4SDimitry Andric   TargetsToSymbols Result;
4017fa27ce4SDimitry Andric   TargetList MappedTargets;
4027fa27ce4SDimitry Andric   for (auto Val : *Section) {
4037fa27ce4SDimitry Andric     auto *Obj = Val.getAsObject();
4047fa27ce4SDimitry Andric     if (!Obj)
4057fa27ce4SDimitry Andric       continue;
4067fa27ce4SDimitry Andric 
4077fa27ce4SDimitry Andric     auto TargetsOrErr = getTargets(Obj);
4087fa27ce4SDimitry Andric     if (!TargetsOrErr) {
4097fa27ce4SDimitry Andric       MappedTargets = Targets;
4107fa27ce4SDimitry Andric       consumeError(TargetsOrErr.takeError());
4117fa27ce4SDimitry Andric     } else {
4127fa27ce4SDimitry Andric       MappedTargets = *TargetsOrErr;
4137fa27ce4SDimitry Andric     }
4147fa27ce4SDimitry Andric     Result.emplace_back(
4157fa27ce4SDimitry Andric         std::make_pair(std::move(MappedTargets), std::vector<JSONSymbol>()));
4167fa27ce4SDimitry Andric 
4177fa27ce4SDimitry Andric     auto *DataSection = Obj->getObject(Keys[TBDKey::Data]);
4187fa27ce4SDimitry Andric     auto *TextSection = Obj->getObject(Keys[TBDKey::Text]);
4197fa27ce4SDimitry Andric     // There should be at least one valid section.
4207fa27ce4SDimitry Andric     if (!DataSection && !TextSection)
4217fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(Key));
4227fa27ce4SDimitry Andric 
4237fa27ce4SDimitry Andric     if (DataSection) {
4247fa27ce4SDimitry Andric       auto Err = collectSymbolsFromSegment(DataSection, Result,
4257fa27ce4SDimitry Andric                                            SectionFlag | SymbolFlags::Data);
4267fa27ce4SDimitry Andric       if (Err)
4277fa27ce4SDimitry Andric         return std::move(Err);
4287fa27ce4SDimitry Andric     }
4297fa27ce4SDimitry Andric     if (TextSection) {
4307fa27ce4SDimitry Andric       auto Err = collectSymbolsFromSegment(TextSection, Result,
4317fa27ce4SDimitry Andric                                            SectionFlag | SymbolFlags::Text);
4327fa27ce4SDimitry Andric       if (Err)
4337fa27ce4SDimitry Andric         return std::move(Err);
4347fa27ce4SDimitry Andric     }
4357fa27ce4SDimitry Andric   }
4367fa27ce4SDimitry Andric 
4377fa27ce4SDimitry Andric   return std::move(Result);
4387fa27ce4SDimitry Andric }
4397fa27ce4SDimitry Andric 
getLibSection(const Object * File,TBDKey Key,TBDKey SubKey,const TargetList & Targets)4407fa27ce4SDimitry Andric Expected<AttrToTargets> getLibSection(const Object *File, TBDKey Key,
4417fa27ce4SDimitry Andric                                       TBDKey SubKey,
4427fa27ce4SDimitry Andric                                       const TargetList &Targets) {
4437fa27ce4SDimitry Andric   auto *Section = File->getArray(Keys[Key]);
4447fa27ce4SDimitry Andric   if (!Section)
4457fa27ce4SDimitry Andric     return AttrToTargets();
4467fa27ce4SDimitry Andric 
4477fa27ce4SDimitry Andric   AttrToTargets Result;
4487fa27ce4SDimitry Andric   TargetList MappedTargets;
4497fa27ce4SDimitry Andric   for (auto Val : *Section) {
4507fa27ce4SDimitry Andric     auto *Obj = Val.getAsObject();
4517fa27ce4SDimitry Andric     if (!Obj)
4527fa27ce4SDimitry Andric       continue;
4537fa27ce4SDimitry Andric 
4547fa27ce4SDimitry Andric     auto TargetsOrErr = getTargets(Obj);
4557fa27ce4SDimitry Andric     if (!TargetsOrErr) {
4567fa27ce4SDimitry Andric       MappedTargets = Targets;
4577fa27ce4SDimitry Andric       consumeError(TargetsOrErr.takeError());
4587fa27ce4SDimitry Andric     } else {
4597fa27ce4SDimitry Andric       MappedTargets = *TargetsOrErr;
4607fa27ce4SDimitry Andric     }
4617fa27ce4SDimitry Andric     auto Err =
4627fa27ce4SDimitry Andric         collectFromArray(SubKey, Obj, [&Result, &MappedTargets](StringRef Key) {
4637fa27ce4SDimitry Andric           Result[Key.str()] = MappedTargets;
4647fa27ce4SDimitry Andric         });
4657fa27ce4SDimitry Andric     if (Err)
4667fa27ce4SDimitry Andric       return std::move(Err);
4677fa27ce4SDimitry Andric   }
4687fa27ce4SDimitry Andric 
4697fa27ce4SDimitry Andric   return std::move(Result);
4707fa27ce4SDimitry Andric }
4717fa27ce4SDimitry Andric 
getUmbrellaSection(const Object * File,const TargetList & Targets)4727fa27ce4SDimitry Andric Expected<AttrToTargets> getUmbrellaSection(const Object *File,
4737fa27ce4SDimitry Andric                                            const TargetList &Targets) {
4747fa27ce4SDimitry Andric   const auto *Umbrella = File->getArray(Keys[TBDKey::ParentUmbrella]);
4757fa27ce4SDimitry Andric   if (!Umbrella)
4767fa27ce4SDimitry Andric     return AttrToTargets();
4777fa27ce4SDimitry Andric 
4787fa27ce4SDimitry Andric   AttrToTargets Result;
4797fa27ce4SDimitry Andric   TargetList MappedTargets;
4807fa27ce4SDimitry Andric   for (auto Val : *Umbrella) {
4817fa27ce4SDimitry Andric     auto *Obj = Val.getAsObject();
4827fa27ce4SDimitry Andric     if (!Obj)
4837fa27ce4SDimitry Andric       return make_error<JSONStubError>(
4847fa27ce4SDimitry Andric           getParseErrorMsg(TBDKey::ParentUmbrella));
4857fa27ce4SDimitry Andric 
4867fa27ce4SDimitry Andric     // Get Targets section.
4877fa27ce4SDimitry Andric     auto TargetsOrErr = getTargets(Obj);
4887fa27ce4SDimitry Andric     if (!TargetsOrErr) {
4897fa27ce4SDimitry Andric       MappedTargets = Targets;
4907fa27ce4SDimitry Andric       consumeError(TargetsOrErr.takeError());
4917fa27ce4SDimitry Andric     } else {
4927fa27ce4SDimitry Andric       MappedTargets = *TargetsOrErr;
4937fa27ce4SDimitry Andric     }
4947fa27ce4SDimitry Andric 
4957fa27ce4SDimitry Andric     auto UmbrellaOrErr =
4967fa27ce4SDimitry Andric         getRequiredValue<StringRef>(TBDKey::Umbrella, Obj, &Object::getString);
4977fa27ce4SDimitry Andric     if (!UmbrellaOrErr)
4987fa27ce4SDimitry Andric       return UmbrellaOrErr.takeError();
4997fa27ce4SDimitry Andric     Result[UmbrellaOrErr->str()] = Targets;
5007fa27ce4SDimitry Andric   }
5017fa27ce4SDimitry Andric   return std::move(Result);
5027fa27ce4SDimitry Andric }
5037fa27ce4SDimitry Andric 
getSwiftVersion(const Object * File)5047fa27ce4SDimitry Andric Expected<uint8_t> getSwiftVersion(const Object *File) {
5057fa27ce4SDimitry Andric   const Array *Versions = File->getArray(Keys[TBDKey::SwiftABI]);
5067fa27ce4SDimitry Andric   if (!Versions)
5077fa27ce4SDimitry Andric     return 0;
5087fa27ce4SDimitry Andric 
5097fa27ce4SDimitry Andric   for (const auto &Val : *Versions) {
5107fa27ce4SDimitry Andric     const auto *Obj = Val.getAsObject();
5117fa27ce4SDimitry Andric     if (!Obj)
5127fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::SwiftABI));
5137fa27ce4SDimitry Andric 
5147fa27ce4SDimitry Andric     // TODO: Take first for now.
5157fa27ce4SDimitry Andric     return getRequiredValue<int64_t, uint8_t>(TBDKey::ABI, Obj,
5167fa27ce4SDimitry Andric                                               &Object::getInteger);
5177fa27ce4SDimitry Andric   }
5187fa27ce4SDimitry Andric 
5197fa27ce4SDimitry Andric   return 0;
5207fa27ce4SDimitry Andric }
5217fa27ce4SDimitry Andric 
getPackedVersion(const Object * File,TBDKey Key)5227fa27ce4SDimitry Andric Expected<PackedVersion> getPackedVersion(const Object *File, TBDKey Key) {
5237fa27ce4SDimitry Andric   const Array *Versions = File->getArray(Keys[Key]);
5247fa27ce4SDimitry Andric   if (!Versions)
5257fa27ce4SDimitry Andric     return PackedVersion(1, 0, 0);
5267fa27ce4SDimitry Andric 
5277fa27ce4SDimitry Andric   for (const auto &Val : *Versions) {
5287fa27ce4SDimitry Andric     const auto *Obj = Val.getAsObject();
5297fa27ce4SDimitry Andric     if (!Obj)
5307fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(Key));
5317fa27ce4SDimitry Andric 
5327fa27ce4SDimitry Andric     auto ValidatePV = [](StringRef Version) -> std::optional<PackedVersion> {
5337fa27ce4SDimitry Andric       PackedVersion PV;
5347fa27ce4SDimitry Andric       auto [success, truncated] = PV.parse64(Version);
5357fa27ce4SDimitry Andric       if (!success || truncated)
5367fa27ce4SDimitry Andric         return std::nullopt;
5377fa27ce4SDimitry Andric       return PV;
5387fa27ce4SDimitry Andric     };
5397fa27ce4SDimitry Andric     // TODO: Take first for now.
5407fa27ce4SDimitry Andric     return getRequiredValue<StringRef, PackedVersion>(
5417fa27ce4SDimitry Andric         TBDKey::Version, Obj, &Object::getString, PackedVersion(1, 0, 0),
5427fa27ce4SDimitry Andric         ValidatePV);
5437fa27ce4SDimitry Andric   }
5447fa27ce4SDimitry Andric 
5457fa27ce4SDimitry Andric   return PackedVersion(1, 0, 0);
5467fa27ce4SDimitry Andric }
5477fa27ce4SDimitry Andric 
getFlags(const Object * File)5487fa27ce4SDimitry Andric Expected<TBDFlags> getFlags(const Object *File) {
5497fa27ce4SDimitry Andric   TBDFlags Flags = TBDFlags::None;
5507fa27ce4SDimitry Andric   const Array *Section = File->getArray(Keys[TBDKey::Flags]);
551b1c73532SDimitry Andric   if (!Section || Section->empty())
5527fa27ce4SDimitry Andric     return Flags;
5537fa27ce4SDimitry Andric 
5547fa27ce4SDimitry Andric   for (auto &Val : *Section) {
555b1c73532SDimitry Andric     // FIXME: Flags currently apply to all target triples.
5567fa27ce4SDimitry Andric     const auto *Obj = Val.getAsObject();
5577fa27ce4SDimitry Andric     if (!Obj)
5587fa27ce4SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Flags));
5597fa27ce4SDimitry Andric 
5607fa27ce4SDimitry Andric     auto FlagsOrErr =
5617fa27ce4SDimitry Andric         collectFromArray(TBDKey::Attributes, Obj, [&Flags](StringRef Flag) {
5627fa27ce4SDimitry Andric           TBDFlags TBDFlag =
5637fa27ce4SDimitry Andric               StringSwitch<TBDFlags>(Flag)
5647fa27ce4SDimitry Andric                   .Case("flat_namespace", TBDFlags::FlatNamespace)
5657fa27ce4SDimitry Andric                   .Case("not_app_extension_safe",
5667fa27ce4SDimitry Andric                         TBDFlags::NotApplicationExtensionSafe)
567b1c73532SDimitry Andric                   .Case("sim_support", TBDFlags::SimulatorSupport)
568b1c73532SDimitry Andric                   .Case("not_for_dyld_shared_cache",
569b1c73532SDimitry Andric                         TBDFlags::OSLibNotForSharedCache)
5707fa27ce4SDimitry Andric                   .Default(TBDFlags::None);
5717fa27ce4SDimitry Andric           Flags |= TBDFlag;
5727fa27ce4SDimitry Andric         });
5737fa27ce4SDimitry Andric 
5747fa27ce4SDimitry Andric     if (FlagsOrErr)
5757fa27ce4SDimitry Andric       return std::move(FlagsOrErr);
5767fa27ce4SDimitry Andric 
5777fa27ce4SDimitry Andric     return Flags;
5787fa27ce4SDimitry Andric   }
5797fa27ce4SDimitry Andric 
5807fa27ce4SDimitry Andric   return Flags;
5817fa27ce4SDimitry Andric }
5827fa27ce4SDimitry Andric 
5837fa27ce4SDimitry Andric using IFPtr = std::unique_ptr<InterfaceFile>;
parseToInterfaceFile(const Object * File)5847fa27ce4SDimitry Andric Expected<IFPtr> parseToInterfaceFile(const Object *File) {
5857fa27ce4SDimitry Andric   auto TargetsOrErr = getTargetsSection(File);
5867fa27ce4SDimitry Andric   if (!TargetsOrErr)
5877fa27ce4SDimitry Andric     return TargetsOrErr.takeError();
5887fa27ce4SDimitry Andric   TargetList Targets = *TargetsOrErr;
5897fa27ce4SDimitry Andric 
5907fa27ce4SDimitry Andric   auto NameOrErr = getNameSection(File);
5917fa27ce4SDimitry Andric   if (!NameOrErr)
5927fa27ce4SDimitry Andric     return NameOrErr.takeError();
5937fa27ce4SDimitry Andric   StringRef Name = *NameOrErr;
5947fa27ce4SDimitry Andric 
5957fa27ce4SDimitry Andric   auto CurrVersionOrErr = getPackedVersion(File, TBDKey::CurrentVersion);
5967fa27ce4SDimitry Andric   if (!CurrVersionOrErr)
5977fa27ce4SDimitry Andric     return CurrVersionOrErr.takeError();
5987fa27ce4SDimitry Andric   PackedVersion CurrVersion = *CurrVersionOrErr;
5997fa27ce4SDimitry Andric 
6007fa27ce4SDimitry Andric   auto CompVersionOrErr = getPackedVersion(File, TBDKey::CompatibilityVersion);
6017fa27ce4SDimitry Andric   if (!CompVersionOrErr)
6027fa27ce4SDimitry Andric     return CompVersionOrErr.takeError();
6037fa27ce4SDimitry Andric   PackedVersion CompVersion = *CompVersionOrErr;
6047fa27ce4SDimitry Andric 
6057fa27ce4SDimitry Andric   auto SwiftABIOrErr = getSwiftVersion(File);
6067fa27ce4SDimitry Andric   if (!SwiftABIOrErr)
6077fa27ce4SDimitry Andric     return SwiftABIOrErr.takeError();
6087fa27ce4SDimitry Andric   uint8_t SwiftABI = *SwiftABIOrErr;
6097fa27ce4SDimitry Andric 
6107fa27ce4SDimitry Andric   auto FlagsOrErr = getFlags(File);
6117fa27ce4SDimitry Andric   if (!FlagsOrErr)
6127fa27ce4SDimitry Andric     return FlagsOrErr.takeError();
6137fa27ce4SDimitry Andric   TBDFlags Flags = *FlagsOrErr;
6147fa27ce4SDimitry Andric 
6157fa27ce4SDimitry Andric   auto UmbrellasOrErr = getUmbrellaSection(File, Targets);
6167fa27ce4SDimitry Andric   if (!UmbrellasOrErr)
6177fa27ce4SDimitry Andric     return UmbrellasOrErr.takeError();
6187fa27ce4SDimitry Andric   AttrToTargets Umbrellas = *UmbrellasOrErr;
6197fa27ce4SDimitry Andric 
6207fa27ce4SDimitry Andric   auto ClientsOrErr =
6217fa27ce4SDimitry Andric       getLibSection(File, TBDKey::AllowableClients, TBDKey::Clients, Targets);
6227fa27ce4SDimitry Andric   if (!ClientsOrErr)
6237fa27ce4SDimitry Andric     return ClientsOrErr.takeError();
6247fa27ce4SDimitry Andric   AttrToTargets Clients = *ClientsOrErr;
6257fa27ce4SDimitry Andric 
6267fa27ce4SDimitry Andric   auto RLOrErr =
6277fa27ce4SDimitry Andric       getLibSection(File, TBDKey::ReexportLibs, TBDKey::Names, Targets);
6287fa27ce4SDimitry Andric   if (!RLOrErr)
6297fa27ce4SDimitry Andric     return RLOrErr.takeError();
6307fa27ce4SDimitry Andric   AttrToTargets ReexportLibs = std::move(*RLOrErr);
6317fa27ce4SDimitry Andric 
6327fa27ce4SDimitry Andric   auto RPathsOrErr = getLibSection(File, TBDKey::RPath, TBDKey::Paths, Targets);
6337fa27ce4SDimitry Andric   if (!RPathsOrErr)
6347fa27ce4SDimitry Andric     return RPathsOrErr.takeError();
6357fa27ce4SDimitry Andric   AttrToTargets RPaths = std::move(*RPathsOrErr);
6367fa27ce4SDimitry Andric 
6377fa27ce4SDimitry Andric   auto ExportsOrErr = getSymbolSection(File, TBDKey::Exports, Targets);
6387fa27ce4SDimitry Andric   if (!ExportsOrErr)
6397fa27ce4SDimitry Andric     return ExportsOrErr.takeError();
6407fa27ce4SDimitry Andric   TargetsToSymbols Exports = std::move(*ExportsOrErr);
6417fa27ce4SDimitry Andric 
6427fa27ce4SDimitry Andric   auto ReexportsOrErr = getSymbolSection(File, TBDKey::Reexports, Targets);
6437fa27ce4SDimitry Andric   if (!ReexportsOrErr)
6447fa27ce4SDimitry Andric     return ReexportsOrErr.takeError();
6457fa27ce4SDimitry Andric   TargetsToSymbols Reexports = std::move(*ReexportsOrErr);
6467fa27ce4SDimitry Andric 
6477fa27ce4SDimitry Andric   auto UndefinedsOrErr = getSymbolSection(File, TBDKey::Undefineds, Targets);
6487fa27ce4SDimitry Andric   if (!UndefinedsOrErr)
6497fa27ce4SDimitry Andric     return UndefinedsOrErr.takeError();
6507fa27ce4SDimitry Andric   TargetsToSymbols Undefineds = std::move(*UndefinedsOrErr);
6517fa27ce4SDimitry Andric 
6527fa27ce4SDimitry Andric   IFPtr F(new InterfaceFile);
6537fa27ce4SDimitry Andric   F->setInstallName(Name);
6547fa27ce4SDimitry Andric   F->setCurrentVersion(CurrVersion);
6557fa27ce4SDimitry Andric   F->setCompatibilityVersion(CompVersion);
6567fa27ce4SDimitry Andric   F->setSwiftABIVersion(SwiftABI);
6577fa27ce4SDimitry Andric   F->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
6587fa27ce4SDimitry Andric   F->setApplicationExtensionSafe(
6597fa27ce4SDimitry Andric       !(Flags & TBDFlags::NotApplicationExtensionSafe));
660b1c73532SDimitry Andric   F->setSimulatorSupport((Flags & TBDFlags::SimulatorSupport));
661b1c73532SDimitry Andric   F->setOSLibNotForSharedCache((Flags & TBDFlags::OSLibNotForSharedCache));
6627fa27ce4SDimitry Andric   for (auto &T : Targets)
6637fa27ce4SDimitry Andric     F->addTarget(T);
6647fa27ce4SDimitry Andric   for (auto &[Lib, Targets] : Clients)
6657fa27ce4SDimitry Andric     for (auto Target : Targets)
6667fa27ce4SDimitry Andric       F->addAllowableClient(Lib, Target);
6677fa27ce4SDimitry Andric   for (auto &[Lib, Targets] : ReexportLibs)
6687fa27ce4SDimitry Andric     for (auto Target : Targets)
6697fa27ce4SDimitry Andric       F->addReexportedLibrary(Lib, Target);
6707fa27ce4SDimitry Andric   for (auto &[Lib, Targets] : Umbrellas)
6717fa27ce4SDimitry Andric     for (auto Target : Targets)
6727fa27ce4SDimitry Andric       F->addParentUmbrella(Target, Lib);
6737fa27ce4SDimitry Andric   for (auto &[Path, Targets] : RPaths)
6747fa27ce4SDimitry Andric     for (auto Target : Targets)
675ac9a064cSDimitry Andric       F->addRPath(Path, Target);
6767fa27ce4SDimitry Andric   for (auto &[Targets, Symbols] : Exports)
6777fa27ce4SDimitry Andric     for (auto &Sym : Symbols)
6787fa27ce4SDimitry Andric       F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
6797fa27ce4SDimitry Andric   for (auto &[Targets, Symbols] : Reexports)
6807fa27ce4SDimitry Andric     for (auto &Sym : Symbols)
6817fa27ce4SDimitry Andric       F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
6827fa27ce4SDimitry Andric   for (auto &[Targets, Symbols] : Undefineds)
6837fa27ce4SDimitry Andric     for (auto &Sym : Symbols)
6847fa27ce4SDimitry Andric       F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
6857fa27ce4SDimitry Andric 
6867fa27ce4SDimitry Andric   return std::move(F);
6877fa27ce4SDimitry Andric }
6887fa27ce4SDimitry Andric 
getInlinedLibs(const Object * File)6897fa27ce4SDimitry Andric Expected<std::vector<IFPtr>> getInlinedLibs(const Object *File) {
6907fa27ce4SDimitry Andric   std::vector<IFPtr> IFs;
6917fa27ce4SDimitry Andric   const Array *Files = File->getArray(Keys[TBDKey::Documents]);
6927fa27ce4SDimitry Andric   if (!Files)
6937fa27ce4SDimitry Andric     return std::move(IFs);
6947fa27ce4SDimitry Andric 
6957fa27ce4SDimitry Andric   for (auto Lib : *Files) {
6967fa27ce4SDimitry Andric     auto IFOrErr = parseToInterfaceFile(Lib.getAsObject());
6977fa27ce4SDimitry Andric     if (!IFOrErr)
6987fa27ce4SDimitry Andric       return IFOrErr.takeError();
6997fa27ce4SDimitry Andric     auto IF = std::move(*IFOrErr);
7007fa27ce4SDimitry Andric     IFs.emplace_back(std::move(IF));
7017fa27ce4SDimitry Andric   }
7027fa27ce4SDimitry Andric   return std::move(IFs);
7037fa27ce4SDimitry Andric }
7047fa27ce4SDimitry Andric 
7057fa27ce4SDimitry Andric } // namespace StubParser
7067fa27ce4SDimitry Andric } // namespace
7077fa27ce4SDimitry Andric 
7087fa27ce4SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
getInterfaceFileFromJSON(StringRef JSON)7097fa27ce4SDimitry Andric MachO::getInterfaceFileFromJSON(StringRef JSON) {
7107fa27ce4SDimitry Andric   auto ValOrErr = parse(JSON);
7117fa27ce4SDimitry Andric   if (!ValOrErr)
7127fa27ce4SDimitry Andric     return ValOrErr.takeError();
7137fa27ce4SDimitry Andric 
7147fa27ce4SDimitry Andric   auto *Root = ValOrErr->getAsObject();
7157fa27ce4SDimitry Andric   auto VersionOrErr = StubParser::getVersion(Root);
7167fa27ce4SDimitry Andric   if (!VersionOrErr)
7177fa27ce4SDimitry Andric     return VersionOrErr.takeError();
7187fa27ce4SDimitry Andric   FileType Version = *VersionOrErr;
7197fa27ce4SDimitry Andric 
7207fa27ce4SDimitry Andric   Object *MainLib = Root->getObject(Keys[TBDKey::MainLibrary]);
7217fa27ce4SDimitry Andric   auto IFOrErr = StubParser::parseToInterfaceFile(MainLib);
7227fa27ce4SDimitry Andric   if (!IFOrErr)
7237fa27ce4SDimitry Andric     return IFOrErr.takeError();
7247fa27ce4SDimitry Andric   (*IFOrErr)->setFileType(Version);
7257fa27ce4SDimitry Andric   std::unique_ptr<InterfaceFile> IF(std::move(*IFOrErr));
7267fa27ce4SDimitry Andric 
7277fa27ce4SDimitry Andric   auto IFsOrErr = StubParser::getInlinedLibs(Root);
7287fa27ce4SDimitry Andric   if (!IFsOrErr)
7297fa27ce4SDimitry Andric     return IFsOrErr.takeError();
7307fa27ce4SDimitry Andric   for (auto &File : *IFsOrErr) {
7317fa27ce4SDimitry Andric     File->setFileType(Version);
7327fa27ce4SDimitry Andric     IF->addDocument(std::shared_ptr<InterfaceFile>(std::move(File)));
7337fa27ce4SDimitry Andric   }
7347fa27ce4SDimitry Andric   return std::move(IF);
7357fa27ce4SDimitry Andric }
7367fa27ce4SDimitry Andric 
7377fa27ce4SDimitry Andric namespace {
7387fa27ce4SDimitry Andric 
7397fa27ce4SDimitry Andric template <typename ContainerT = Array>
insertNonEmptyValues(Object & Obj,TBDKey Key,ContainerT && Contents)7407fa27ce4SDimitry Andric bool insertNonEmptyValues(Object &Obj, TBDKey Key, ContainerT &&Contents) {
7417fa27ce4SDimitry Andric   if (Contents.empty())
7427fa27ce4SDimitry Andric     return false;
7437fa27ce4SDimitry Andric   Obj[Keys[Key]] = std::move(Contents);
7447fa27ce4SDimitry Andric   return true;
7457fa27ce4SDimitry Andric }
7467fa27ce4SDimitry Andric 
getFormattedStr(const MachO::Target & Targ)7477fa27ce4SDimitry Andric std::string getFormattedStr(const MachO::Target &Targ) {
7487fa27ce4SDimitry Andric   std::string PlatformStr = Targ.Platform == PLATFORM_MACCATALYST
7497fa27ce4SDimitry Andric                                 ? "maccatalyst"
7507fa27ce4SDimitry Andric                                 : getOSAndEnvironmentName(Targ.Platform);
7517fa27ce4SDimitry Andric   return (getArchitectureName(Targ.Arch) + "-" + PlatformStr).str();
7527fa27ce4SDimitry Andric }
7537fa27ce4SDimitry Andric 
7547fa27ce4SDimitry Andric template <typename AggregateT>
serializeTargets(const AggregateT Targets,const TargetList & ActiveTargets)7557fa27ce4SDimitry Andric std::vector<std::string> serializeTargets(const AggregateT Targets,
7567fa27ce4SDimitry Andric                                           const TargetList &ActiveTargets) {
7577fa27ce4SDimitry Andric   std::vector<std::string> TargetsStr;
7587fa27ce4SDimitry Andric   if (Targets.size() == ActiveTargets.size())
7597fa27ce4SDimitry Andric     return TargetsStr;
7607fa27ce4SDimitry Andric 
761b1c73532SDimitry Andric   for (const MachO::Target &Target : Targets)
7627fa27ce4SDimitry Andric     TargetsStr.emplace_back(getFormattedStr(Target));
763b1c73532SDimitry Andric 
7647fa27ce4SDimitry Andric   return TargetsStr;
7657fa27ce4SDimitry Andric }
7667fa27ce4SDimitry Andric 
serializeTargetInfo(const TargetList & ActiveTargets)7677fa27ce4SDimitry Andric Array serializeTargetInfo(const TargetList &ActiveTargets) {
7687fa27ce4SDimitry Andric   Array Targets;
7697fa27ce4SDimitry Andric   for (const auto Targ : ActiveTargets) {
7707fa27ce4SDimitry Andric     Object TargetInfo;
771b1c73532SDimitry Andric     if (!Targ.MinDeployment.empty())
7727fa27ce4SDimitry Andric       TargetInfo[Keys[TBDKey::Deployment]] = Targ.MinDeployment.getAsString();
7737fa27ce4SDimitry Andric     TargetInfo[Keys[TBDKey::Target]] = getFormattedStr(Targ);
7747fa27ce4SDimitry Andric     Targets.emplace_back(std::move(TargetInfo));
7757fa27ce4SDimitry Andric   }
7767fa27ce4SDimitry Andric   return Targets;
7777fa27ce4SDimitry Andric }
7787fa27ce4SDimitry Andric 
7797fa27ce4SDimitry Andric template <typename ValueT, typename EntryT = ValueT>
serializeScalar(TBDKey Key,ValueT Value,ValueT Default=ValueT ())7807fa27ce4SDimitry Andric Array serializeScalar(TBDKey Key, ValueT Value, ValueT Default = ValueT()) {
7817fa27ce4SDimitry Andric   if (Value == Default)
7827fa27ce4SDimitry Andric     return {};
7837fa27ce4SDimitry Andric   Array Container;
7847fa27ce4SDimitry Andric   Object ScalarObj({Object::KV({Keys[Key], EntryT(Value)})});
7857fa27ce4SDimitry Andric 
7867fa27ce4SDimitry Andric   Container.emplace_back(std::move(ScalarObj));
7877fa27ce4SDimitry Andric   return Container;
7887fa27ce4SDimitry Andric }
7897fa27ce4SDimitry Andric 
7907fa27ce4SDimitry Andric using TargetsToValuesMap =
7917fa27ce4SDimitry Andric     std::map<std::vector<std::string>, std::vector<std::string>>;
7927fa27ce4SDimitry Andric 
7937fa27ce4SDimitry Andric template <typename AggregateT = TargetsToValuesMap>
serializeAttrToTargets(AggregateT & Entries,TBDKey Key)7947fa27ce4SDimitry Andric Array serializeAttrToTargets(AggregateT &Entries, TBDKey Key) {
7957fa27ce4SDimitry Andric   Array Container;
7967fa27ce4SDimitry Andric   for (const auto &[Targets, Values] : Entries) {
7977fa27ce4SDimitry Andric     Object Obj;
7987fa27ce4SDimitry Andric     insertNonEmptyValues(Obj, TBDKey::Targets, std::move(Targets));
7997fa27ce4SDimitry Andric     Obj[Keys[Key]] = Values;
8007fa27ce4SDimitry Andric     Container.emplace_back(std::move(Obj));
8017fa27ce4SDimitry Andric   }
8027fa27ce4SDimitry Andric   return Container;
8037fa27ce4SDimitry Andric }
8047fa27ce4SDimitry Andric 
8057fa27ce4SDimitry Andric template <typename ValueT = std::string,
8067fa27ce4SDimitry Andric           typename AggregateT = std::vector<std::pair<MachO::Target, ValueT>>>
serializeField(TBDKey Key,const AggregateT & Values,const TargetList & ActiveTargets,bool IsArray=true)8077fa27ce4SDimitry Andric Array serializeField(TBDKey Key, const AggregateT &Values,
8087fa27ce4SDimitry Andric                      const TargetList &ActiveTargets, bool IsArray = true) {
8097fa27ce4SDimitry Andric   std::map<ValueT, std::set<MachO::Target>> Entries;
8107fa27ce4SDimitry Andric   for (const auto &[Target, Val] : Values)
8117fa27ce4SDimitry Andric     Entries[Val].insert(Target);
8127fa27ce4SDimitry Andric 
8137fa27ce4SDimitry Andric   if (!IsArray) {
8147fa27ce4SDimitry Andric     std::map<std::vector<std::string>, std::string> FinalEntries;
8157fa27ce4SDimitry Andric     for (const auto &[Val, Targets] : Entries)
8167fa27ce4SDimitry Andric       FinalEntries[serializeTargets(Targets, ActiveTargets)] = Val;
8177fa27ce4SDimitry Andric     return serializeAttrToTargets(FinalEntries, Key);
8187fa27ce4SDimitry Andric   }
8197fa27ce4SDimitry Andric 
8207fa27ce4SDimitry Andric   TargetsToValuesMap FinalEntries;
8217fa27ce4SDimitry Andric   for (const auto &[Val, Targets] : Entries)
8227fa27ce4SDimitry Andric     FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(Val);
8237fa27ce4SDimitry Andric   return serializeAttrToTargets(FinalEntries, Key);
8247fa27ce4SDimitry Andric }
8257fa27ce4SDimitry Andric 
serializeField(TBDKey Key,const std::vector<InterfaceFileRef> & Values,const TargetList & ActiveTargets)8267fa27ce4SDimitry Andric Array serializeField(TBDKey Key, const std::vector<InterfaceFileRef> &Values,
8277fa27ce4SDimitry Andric                      const TargetList &ActiveTargets) {
8287fa27ce4SDimitry Andric   TargetsToValuesMap FinalEntries;
8297fa27ce4SDimitry Andric   for (const auto &Ref : Values) {
8307fa27ce4SDimitry Andric     TargetList Targets{Ref.targets().begin(), Ref.targets().end()};
8317fa27ce4SDimitry Andric     FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(
8327fa27ce4SDimitry Andric         Ref.getInstallName());
8337fa27ce4SDimitry Andric   }
8347fa27ce4SDimitry Andric   return serializeAttrToTargets(FinalEntries, Key);
8357fa27ce4SDimitry Andric }
8367fa27ce4SDimitry Andric 
8377fa27ce4SDimitry Andric struct SymbolFields {
8387fa27ce4SDimitry Andric   struct SymbolTypes {
8397fa27ce4SDimitry Andric     std::vector<StringRef> Weaks;
8407fa27ce4SDimitry Andric     std::vector<StringRef> Globals;
8417fa27ce4SDimitry Andric     std::vector<StringRef> TLV;
8427fa27ce4SDimitry Andric     std::vector<StringRef> ObjCClasses;
8437fa27ce4SDimitry Andric     std::vector<StringRef> IVars;
8447fa27ce4SDimitry Andric     std::vector<StringRef> EHTypes;
8457fa27ce4SDimitry Andric 
empty__anon7871e7c10c11::SymbolFields::SymbolTypes8467fa27ce4SDimitry Andric     bool empty() const {
8477fa27ce4SDimitry Andric       return Weaks.empty() && Globals.empty() && TLV.empty() &&
8487fa27ce4SDimitry Andric              ObjCClasses.empty() && IVars.empty() && EHTypes.empty();
8497fa27ce4SDimitry Andric     }
8507fa27ce4SDimitry Andric   };
8517fa27ce4SDimitry Andric   SymbolTypes Data;
8527fa27ce4SDimitry Andric   SymbolTypes Text;
8537fa27ce4SDimitry Andric };
8547fa27ce4SDimitry Andric 
serializeSymbols(InterfaceFile::const_filtered_symbol_range Symbols,const TargetList & ActiveTargets)8557fa27ce4SDimitry Andric Array serializeSymbols(InterfaceFile::const_filtered_symbol_range Symbols,
8567fa27ce4SDimitry Andric                        const TargetList &ActiveTargets) {
8577fa27ce4SDimitry Andric   auto AssignForSymbolType = [](SymbolFields::SymbolTypes &Assignment,
8587fa27ce4SDimitry Andric                                 const Symbol *Sym) {
8597fa27ce4SDimitry Andric     switch (Sym->getKind()) {
860ac9a064cSDimitry Andric     case EncodeKind::ObjectiveCClass:
8617fa27ce4SDimitry Andric       Assignment.ObjCClasses.emplace_back(Sym->getName());
8627fa27ce4SDimitry Andric       return;
863ac9a064cSDimitry Andric     case EncodeKind::ObjectiveCClassEHType:
8647fa27ce4SDimitry Andric       Assignment.EHTypes.emplace_back(Sym->getName());
8657fa27ce4SDimitry Andric       return;
866ac9a064cSDimitry Andric     case EncodeKind::ObjectiveCInstanceVariable:
8677fa27ce4SDimitry Andric       Assignment.IVars.emplace_back(Sym->getName());
8687fa27ce4SDimitry Andric       return;
869ac9a064cSDimitry Andric     case EncodeKind::GlobalSymbol: {
8707fa27ce4SDimitry Andric       if (Sym->isWeakReferenced() || Sym->isWeakDefined())
8717fa27ce4SDimitry Andric         Assignment.Weaks.emplace_back(Sym->getName());
8727fa27ce4SDimitry Andric       else if (Sym->isThreadLocalValue())
8737fa27ce4SDimitry Andric         Assignment.TLV.emplace_back(Sym->getName());
8747fa27ce4SDimitry Andric       else
8757fa27ce4SDimitry Andric         Assignment.Globals.emplace_back(Sym->getName());
8767fa27ce4SDimitry Andric       return;
8777fa27ce4SDimitry Andric     }
8787fa27ce4SDimitry Andric     }
8797fa27ce4SDimitry Andric   };
8807fa27ce4SDimitry Andric 
8817fa27ce4SDimitry Andric   std::map<std::vector<std::string>, SymbolFields> Entries;
8827fa27ce4SDimitry Andric   for (const auto *Sym : Symbols) {
8837fa27ce4SDimitry Andric     std::set<MachO::Target> Targets{Sym->targets().begin(),
8847fa27ce4SDimitry Andric                                     Sym->targets().end()};
8857fa27ce4SDimitry Andric     auto JSONTargets = serializeTargets(Targets, ActiveTargets);
8867fa27ce4SDimitry Andric     if (Sym->isData())
8877fa27ce4SDimitry Andric       AssignForSymbolType(Entries[std::move(JSONTargets)].Data, Sym);
8887fa27ce4SDimitry Andric     else if (Sym->isText())
8897fa27ce4SDimitry Andric       AssignForSymbolType(Entries[std::move(JSONTargets)].Text, Sym);
8907fa27ce4SDimitry Andric     else
8917fa27ce4SDimitry Andric       llvm_unreachable("unexpected symbol type");
8927fa27ce4SDimitry Andric   }
8937fa27ce4SDimitry Andric 
8947fa27ce4SDimitry Andric   auto InsertSymbolsToJSON = [](Object &SymSection, TBDKey SegmentKey,
8957fa27ce4SDimitry Andric                                 SymbolFields::SymbolTypes &SymField) {
8967fa27ce4SDimitry Andric     if (SymField.empty())
8977fa27ce4SDimitry Andric       return;
8987fa27ce4SDimitry Andric     Object Segment;
8997fa27ce4SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::Globals, std::move(SymField.Globals));
9007fa27ce4SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::ThreadLocal, std::move(SymField.TLV));
9017fa27ce4SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::Weak, std::move(SymField.Weaks));
9027fa27ce4SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::ObjCClass,
9037fa27ce4SDimitry Andric                          std::move(SymField.ObjCClasses));
9047fa27ce4SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::ObjCEHType,
9057fa27ce4SDimitry Andric                          std::move(SymField.EHTypes));
9067fa27ce4SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::ObjCIvar, std::move(SymField.IVars));
9077fa27ce4SDimitry Andric     insertNonEmptyValues(SymSection, SegmentKey, std::move(Segment));
9087fa27ce4SDimitry Andric   };
9097fa27ce4SDimitry Andric 
9107fa27ce4SDimitry Andric   Array SymbolSection;
9117fa27ce4SDimitry Andric   for (auto &[Targets, Fields] : Entries) {
9127fa27ce4SDimitry Andric     Object AllSyms;
9137fa27ce4SDimitry Andric     insertNonEmptyValues(AllSyms, TBDKey::Targets, std::move(Targets));
9147fa27ce4SDimitry Andric     InsertSymbolsToJSON(AllSyms, TBDKey::Data, Fields.Data);
9157fa27ce4SDimitry Andric     InsertSymbolsToJSON(AllSyms, TBDKey::Text, Fields.Text);
9167fa27ce4SDimitry Andric     SymbolSection.emplace_back(std::move(AllSyms));
9177fa27ce4SDimitry Andric   }
9187fa27ce4SDimitry Andric 
9197fa27ce4SDimitry Andric   return SymbolSection;
9207fa27ce4SDimitry Andric }
9217fa27ce4SDimitry Andric 
serializeFlags(const InterfaceFile * File)9227fa27ce4SDimitry Andric Array serializeFlags(const InterfaceFile *File) {
9237fa27ce4SDimitry Andric   // TODO: Give all Targets the same flags for now.
9247fa27ce4SDimitry Andric   Array Flags;
9257fa27ce4SDimitry Andric   if (!File->isTwoLevelNamespace())
9267fa27ce4SDimitry Andric     Flags.emplace_back("flat_namespace");
9277fa27ce4SDimitry Andric   if (!File->isApplicationExtensionSafe())
9287fa27ce4SDimitry Andric     Flags.emplace_back("not_app_extension_safe");
929b1c73532SDimitry Andric   if (File->hasSimulatorSupport())
930b1c73532SDimitry Andric     Flags.emplace_back("sim_support");
931b1c73532SDimitry Andric   if (File->isOSLibNotForSharedCache())
932b1c73532SDimitry Andric     Flags.emplace_back("not_for_dyld_shared_cache");
9337fa27ce4SDimitry Andric   return serializeScalar(TBDKey::Attributes, std::move(Flags));
9347fa27ce4SDimitry Andric }
9357fa27ce4SDimitry Andric 
serializeIF(const InterfaceFile * File)9367fa27ce4SDimitry Andric Expected<Object> serializeIF(const InterfaceFile *File) {
9377fa27ce4SDimitry Andric   Object Library;
9387fa27ce4SDimitry Andric 
9397fa27ce4SDimitry Andric   // Handle required keys.
9407fa27ce4SDimitry Andric   TargetList ActiveTargets{File->targets().begin(), File->targets().end()};
9417fa27ce4SDimitry Andric   if (!insertNonEmptyValues(Library, TBDKey::TargetInfo,
9427fa27ce4SDimitry Andric                             serializeTargetInfo(ActiveTargets)))
9437fa27ce4SDimitry Andric     return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::TargetInfo));
9447fa27ce4SDimitry Andric 
9457fa27ce4SDimitry Andric   Array Name = serializeScalar<StringRef>(TBDKey::Name, File->getInstallName());
9467fa27ce4SDimitry Andric   if (!insertNonEmptyValues(Library, TBDKey::InstallName, std::move(Name)))
9477fa27ce4SDimitry Andric     return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::InstallName));
9487fa27ce4SDimitry Andric 
9497fa27ce4SDimitry Andric   // Handle optional keys.
9507fa27ce4SDimitry Andric   Array Flags = serializeFlags(File);
9517fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::Flags, std::move(Flags));
9527fa27ce4SDimitry Andric 
9537fa27ce4SDimitry Andric   Array CurrentV = serializeScalar<PackedVersion, std::string>(
9547fa27ce4SDimitry Andric       TBDKey::Version, File->getCurrentVersion(), PackedVersion(1, 0, 0));
9557fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::CurrentVersion, std::move(CurrentV));
9567fa27ce4SDimitry Andric 
9577fa27ce4SDimitry Andric   Array CompatV = serializeScalar<PackedVersion, std::string>(
9587fa27ce4SDimitry Andric       TBDKey::Version, File->getCompatibilityVersion(), PackedVersion(1, 0, 0));
9597fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::CompatibilityVersion,
9607fa27ce4SDimitry Andric                        std::move(CompatV));
9617fa27ce4SDimitry Andric 
9627fa27ce4SDimitry Andric   Array SwiftABI = serializeScalar<uint8_t, int64_t>(
9637fa27ce4SDimitry Andric       TBDKey::ABI, File->getSwiftABIVersion(), 0u);
9647fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::SwiftABI, std::move(SwiftABI));
9657fa27ce4SDimitry Andric 
9667fa27ce4SDimitry Andric   Array RPaths = serializeField(TBDKey::Paths, File->rpaths(), ActiveTargets);
9677fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::RPath, std::move(RPaths));
9687fa27ce4SDimitry Andric 
9697fa27ce4SDimitry Andric   Array Umbrellas = serializeField(TBDKey::Umbrella, File->umbrellas(),
9707fa27ce4SDimitry Andric                                    ActiveTargets, /*IsArray=*/false);
9717fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::ParentUmbrella, std::move(Umbrellas));
9727fa27ce4SDimitry Andric 
9737fa27ce4SDimitry Andric   Array Clients =
9747fa27ce4SDimitry Andric       serializeField(TBDKey::Clients, File->allowableClients(), ActiveTargets);
9757fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::AllowableClients, std::move(Clients));
9767fa27ce4SDimitry Andric 
9777fa27ce4SDimitry Andric   Array ReexportLibs =
9787fa27ce4SDimitry Andric       serializeField(TBDKey::Names, File->reexportedLibraries(), ActiveTargets);
9797fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::ReexportLibs, std::move(ReexportLibs));
9807fa27ce4SDimitry Andric 
9817fa27ce4SDimitry Andric   // Handle symbols.
9827fa27ce4SDimitry Andric   Array Exports = serializeSymbols(File->exports(), ActiveTargets);
9837fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::Exports, std::move(Exports));
9847fa27ce4SDimitry Andric 
9857fa27ce4SDimitry Andric   Array Reexports = serializeSymbols(File->reexports(), ActiveTargets);
9867fa27ce4SDimitry Andric   insertNonEmptyValues(Library, TBDKey::Reexports, std::move(Reexports));
9877fa27ce4SDimitry Andric 
9887fa27ce4SDimitry Andric   if (!File->isTwoLevelNamespace()) {
9897fa27ce4SDimitry Andric     Array Undefineds = serializeSymbols(File->undefineds(), ActiveTargets);
9907fa27ce4SDimitry Andric     insertNonEmptyValues(Library, TBDKey::Undefineds, std::move(Undefineds));
9917fa27ce4SDimitry Andric   }
9927fa27ce4SDimitry Andric 
9937fa27ce4SDimitry Andric   return std::move(Library);
9947fa27ce4SDimitry Andric }
9957fa27ce4SDimitry Andric 
getJSON(const InterfaceFile * File,const FileType FileKind)996b1c73532SDimitry Andric Expected<Object> getJSON(const InterfaceFile *File, const FileType FileKind) {
997b1c73532SDimitry Andric   assert(FileKind == FileType::TBD_V5 && "unexpected json file format version");
9987fa27ce4SDimitry Andric   Object Root;
9997fa27ce4SDimitry Andric 
10007fa27ce4SDimitry Andric   auto MainLibOrErr = serializeIF(File);
10017fa27ce4SDimitry Andric   if (!MainLibOrErr)
10027fa27ce4SDimitry Andric     return MainLibOrErr;
10037fa27ce4SDimitry Andric   Root[Keys[TBDKey::MainLibrary]] = std::move(*MainLibOrErr);
10047fa27ce4SDimitry Andric   Array Documents;
10057fa27ce4SDimitry Andric   for (const auto &Doc : File->documents()) {
10067fa27ce4SDimitry Andric     auto LibOrErr = serializeIF(Doc.get());
10077fa27ce4SDimitry Andric     if (!LibOrErr)
10087fa27ce4SDimitry Andric       return LibOrErr;
10097fa27ce4SDimitry Andric     Documents.emplace_back(std::move(*LibOrErr));
10107fa27ce4SDimitry Andric   }
10117fa27ce4SDimitry Andric 
10127fa27ce4SDimitry Andric   Root[Keys[TBDKey::TBDVersion]] = 5;
10137fa27ce4SDimitry Andric   insertNonEmptyValues(Root, TBDKey::Documents, std::move(Documents));
10147fa27ce4SDimitry Andric   return std::move(Root);
10157fa27ce4SDimitry Andric }
10167fa27ce4SDimitry Andric 
10177fa27ce4SDimitry Andric } // namespace
10187fa27ce4SDimitry Andric 
serializeInterfaceFileToJSON(raw_ostream & OS,const InterfaceFile & File,const FileType FileKind,bool Compact)10197fa27ce4SDimitry Andric Error MachO::serializeInterfaceFileToJSON(raw_ostream &OS,
10207fa27ce4SDimitry Andric                                           const InterfaceFile &File,
1021b1c73532SDimitry Andric                                           const FileType FileKind,
10227fa27ce4SDimitry Andric                                           bool Compact) {
1023b1c73532SDimitry Andric   auto TextFile = getJSON(&File, FileKind);
10247fa27ce4SDimitry Andric   if (!TextFile)
10257fa27ce4SDimitry Andric     return TextFile.takeError();
10267fa27ce4SDimitry Andric   if (Compact)
10277fa27ce4SDimitry Andric     OS << formatv("{0}", Value(std::move(*TextFile))) << "\n";
10287fa27ce4SDimitry Andric   else
10297fa27ce4SDimitry Andric     OS << formatv("{0:2}", Value(std::move(*TextFile))) << "\n";
10307fa27ce4SDimitry Andric   return Error::success();
10317fa27ce4SDimitry Andric }
1032