xref: /freebsd/contrib/llvm-project/llvm/lib/TextAPI/TextStubV5.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===- TextStubV5.cpp -----------------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric //
906c3fb27SDimitry Andric // Implements Text Stub JSON mappings.
1006c3fb27SDimitry Andric //
1106c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1206c3fb27SDimitry Andric #include "TextStubCommon.h"
1306c3fb27SDimitry Andric #include "llvm/ADT/StringSwitch.h"
1406c3fb27SDimitry Andric #include "llvm/Support/JSON.h"
1506c3fb27SDimitry Andric #include <utility>
1606c3fb27SDimitry Andric 
1706c3fb27SDimitry Andric // clang-format off
1806c3fb27SDimitry Andric /*
1906c3fb27SDimitry Andric 
2006c3fb27SDimitry Andric JSON Format specification.
2106c3fb27SDimitry Andric 
2206c3fb27SDimitry Andric All library level keys, accept target values and are defaulted if not specified.
2306c3fb27SDimitry Andric 
2406c3fb27SDimitry Andric {
2506c3fb27SDimitry Andric "tapi_tbd_version": 5,                            # Required: TBD version for all documents in file
2606c3fb27SDimitry Andric "main_library": {                                 # Required: top level library
2706c3fb27SDimitry Andric   "target_info": [                                # Required: target information
2806c3fb27SDimitry Andric     {
2906c3fb27SDimitry Andric       "target": "x86_64-macos",
305f757f3fSDimitry Andric       "min_deployment": "10.14"                   # Optional: minOS defaults to 0
3106c3fb27SDimitry Andric     },
3206c3fb27SDimitry Andric     {
3306c3fb27SDimitry Andric       "target": "arm64-macos",
3406c3fb27SDimitry Andric       "min_deployment": "10.14"
3506c3fb27SDimitry Andric     },
3606c3fb27SDimitry Andric     {
3706c3fb27SDimitry Andric       "target": "arm64-maccatalyst",
3806c3fb27SDimitry Andric       "min_deployment": "12.1"
3906c3fb27SDimitry Andric     }],
4006c3fb27SDimitry Andric   "flags":[{"attributes": ["flat_namespace"]}],     # Optional:
4106c3fb27SDimitry Andric   "install_names":[{"name":"/S/L/F/Foo.fwk/Foo"}],  # Required: library install name
4206c3fb27SDimitry Andric   "current_versions":[{"version": "1.2"}],          # Optional: defaults to 1
4306c3fb27SDimitry Andric   "compatibility_versions":[{ "version": "1.1"}],   # Optional: defaults to 1
4406c3fb27SDimitry Andric   "rpaths": [                                       # Optional:
4506c3fb27SDimitry Andric     {
4606c3fb27SDimitry Andric       "targets": ["x86_64-macos"],                  # Optional: defaults to targets in `target-info`
4706c3fb27SDimitry Andric       "paths": ["@executable_path/.../Frameworks"]
4806c3fb27SDimitry Andric     }],
4906c3fb27SDimitry Andric   "parent_umbrellas": [{"umbrella": "System"}],
5006c3fb27SDimitry Andric   "allowable_clients": [{"clients": ["ClientA"]}],
5106c3fb27SDimitry Andric   "reexported_libraries": [{"names": ["/u/l/l/foo.dylib"]}],
5206c3fb27SDimitry Andric   "exported_symbols": [{                            # List of export symbols section
5306c3fb27SDimitry Andric       "targets": ["x86_64-macos", "arm64-macos"],   # Optional: defaults to targets in `target-info`
5406c3fb27SDimitry Andric         "text": {                                   # List of Text segment symbols
5506c3fb27SDimitry Andric           "global": [ "_func" ],
5606c3fb27SDimitry Andric           "weak": [],
5706c3fb27SDimitry Andric           "thread_local": []
5806c3fb27SDimitry Andric         },
5906c3fb27SDimitry Andric         "data": { ... },                            # List of Data segment symbols
6006c3fb27SDimitry Andric    }],
6106c3fb27SDimitry Andric   "reexported_symbols": [{  ... }],                 # List of reexported symbols section
6206c3fb27SDimitry Andric   "undefined_symbols": [{ ... }]                    # List of undefined symbols section
6306c3fb27SDimitry Andric },
6406c3fb27SDimitry Andric "libraries": [                                      # Optional: Array of inlined libraries
6506c3fb27SDimitry Andric   {...}, {...}, {...}
6606c3fb27SDimitry Andric ]
6706c3fb27SDimitry Andric }
6806c3fb27SDimitry Andric */
6906c3fb27SDimitry Andric // clang-format on
7006c3fb27SDimitry Andric 
7106c3fb27SDimitry Andric using namespace llvm;
7206c3fb27SDimitry Andric using namespace llvm::json;
7306c3fb27SDimitry Andric using namespace llvm::MachO;
7406c3fb27SDimitry Andric 
7506c3fb27SDimitry Andric namespace {
7606c3fb27SDimitry Andric struct JSONSymbol {
77*0fca6ea1SDimitry Andric   EncodeKind Kind;
7806c3fb27SDimitry Andric   std::string Name;
7906c3fb27SDimitry Andric   SymbolFlags Flags;
8006c3fb27SDimitry Andric };
8106c3fb27SDimitry Andric 
8206c3fb27SDimitry Andric using AttrToTargets = std::map<std::string, TargetList>;
8306c3fb27SDimitry Andric using TargetsToSymbols =
8406c3fb27SDimitry Andric     SmallVector<std::pair<TargetList, std::vector<JSONSymbol>>>;
8506c3fb27SDimitry Andric 
8606c3fb27SDimitry Andric enum TBDKey : size_t {
8706c3fb27SDimitry Andric   TBDVersion = 0U,
8806c3fb27SDimitry Andric   MainLibrary,
8906c3fb27SDimitry Andric   Documents,
9006c3fb27SDimitry Andric   TargetInfo,
9106c3fb27SDimitry Andric   Targets,
9206c3fb27SDimitry Andric   Target,
9306c3fb27SDimitry Andric   Deployment,
9406c3fb27SDimitry Andric   Flags,
9506c3fb27SDimitry Andric   Attributes,
9606c3fb27SDimitry Andric   InstallName,
9706c3fb27SDimitry Andric   CurrentVersion,
9806c3fb27SDimitry Andric   CompatibilityVersion,
9906c3fb27SDimitry Andric   Version,
10006c3fb27SDimitry Andric   SwiftABI,
10106c3fb27SDimitry Andric   ABI,
10206c3fb27SDimitry Andric   ParentUmbrella,
10306c3fb27SDimitry Andric   Umbrella,
10406c3fb27SDimitry Andric   AllowableClients,
10506c3fb27SDimitry Andric   Clients,
10606c3fb27SDimitry Andric   ReexportLibs,
10706c3fb27SDimitry Andric   Names,
10806c3fb27SDimitry Andric   Name,
10906c3fb27SDimitry Andric   Exports,
11006c3fb27SDimitry Andric   Reexports,
11106c3fb27SDimitry Andric   Undefineds,
11206c3fb27SDimitry Andric   Data,
11306c3fb27SDimitry Andric   Text,
11406c3fb27SDimitry Andric   Weak,
11506c3fb27SDimitry Andric   ThreadLocal,
11606c3fb27SDimitry Andric   Globals,
11706c3fb27SDimitry Andric   ObjCClass,
11806c3fb27SDimitry Andric   ObjCEHType,
11906c3fb27SDimitry Andric   ObjCIvar,
12006c3fb27SDimitry Andric   RPath,
12106c3fb27SDimitry Andric   Paths,
12206c3fb27SDimitry Andric };
12306c3fb27SDimitry Andric 
12406c3fb27SDimitry Andric std::array<StringRef, 64> Keys = {
12506c3fb27SDimitry Andric     "tapi_tbd_version",
12606c3fb27SDimitry Andric     "main_library",
12706c3fb27SDimitry Andric     "libraries",
12806c3fb27SDimitry Andric     "target_info",
12906c3fb27SDimitry Andric     "targets",
13006c3fb27SDimitry Andric     "target",
13106c3fb27SDimitry Andric     "min_deployment",
13206c3fb27SDimitry Andric     "flags",
13306c3fb27SDimitry Andric     "attributes",
13406c3fb27SDimitry Andric     "install_names",
13506c3fb27SDimitry Andric     "current_versions",
13606c3fb27SDimitry Andric     "compatibility_versions",
13706c3fb27SDimitry Andric     "version",
13806c3fb27SDimitry Andric     "swift_abi",
13906c3fb27SDimitry Andric     "abi",
14006c3fb27SDimitry Andric     "parent_umbrellas",
14106c3fb27SDimitry Andric     "umbrella",
14206c3fb27SDimitry Andric     "allowable_clients",
14306c3fb27SDimitry Andric     "clients",
14406c3fb27SDimitry Andric     "reexported_libraries",
14506c3fb27SDimitry Andric     "names",
14606c3fb27SDimitry Andric     "name",
14706c3fb27SDimitry Andric     "exported_symbols",
14806c3fb27SDimitry Andric     "reexported_symbols",
14906c3fb27SDimitry Andric     "undefined_symbols",
15006c3fb27SDimitry Andric     "data",
15106c3fb27SDimitry Andric     "text",
15206c3fb27SDimitry Andric     "weak",
15306c3fb27SDimitry Andric     "thread_local",
15406c3fb27SDimitry Andric     "global",
15506c3fb27SDimitry Andric     "objc_class",
15606c3fb27SDimitry Andric     "objc_eh_type",
15706c3fb27SDimitry Andric     "objc_ivar",
15806c3fb27SDimitry Andric     "rpaths",
15906c3fb27SDimitry Andric     "paths",
16006c3fb27SDimitry Andric };
16106c3fb27SDimitry Andric 
getParseErrorMsg(TBDKey Key)16206c3fb27SDimitry Andric static llvm::SmallString<128> getParseErrorMsg(TBDKey Key) {
16306c3fb27SDimitry Andric   return {"invalid ", Keys[Key], " section"};
16406c3fb27SDimitry Andric }
16506c3fb27SDimitry Andric 
getSerializeErrorMsg(TBDKey Key)16606c3fb27SDimitry Andric static llvm::SmallString<128> getSerializeErrorMsg(TBDKey Key) {
16706c3fb27SDimitry Andric   return {"missing ", Keys[Key], " information"};
16806c3fb27SDimitry Andric }
16906c3fb27SDimitry Andric 
17006c3fb27SDimitry Andric class JSONStubError : public llvm::ErrorInfo<llvm::json::ParseError> {
17106c3fb27SDimitry Andric public:
JSONStubError(Twine ErrMsg)17206c3fb27SDimitry Andric   JSONStubError(Twine ErrMsg) : Message(ErrMsg.str()) {}
17306c3fb27SDimitry Andric 
log(llvm::raw_ostream & OS) const17406c3fb27SDimitry Andric   void log(llvm::raw_ostream &OS) const override { OS << Message << "\n"; }
convertToErrorCode() const17506c3fb27SDimitry Andric   std::error_code convertToErrorCode() const override {
17606c3fb27SDimitry Andric     return llvm::inconvertibleErrorCode();
17706c3fb27SDimitry Andric   }
17806c3fb27SDimitry Andric 
17906c3fb27SDimitry Andric private:
18006c3fb27SDimitry Andric   std::string Message;
18106c3fb27SDimitry Andric };
18206c3fb27SDimitry Andric 
18306c3fb27SDimitry 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)18406c3fb27SDimitry Andric Expected<StubT> getRequiredValue(
18506c3fb27SDimitry Andric     TBDKey Key, const Object *Obj,
18606c3fb27SDimitry Andric     std::function<std::optional<JsonT>(const Object *, StringRef)> GetValue,
18706c3fb27SDimitry Andric     std::function<std::optional<StubT>(JsonT)> Validate = nullptr) {
18806c3fb27SDimitry Andric   std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
18906c3fb27SDimitry Andric   if (!Val)
19006c3fb27SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(Key));
19106c3fb27SDimitry Andric 
19206c3fb27SDimitry Andric   if (Validate == nullptr)
19306c3fb27SDimitry Andric     return static_cast<StubT>(*Val);
19406c3fb27SDimitry Andric 
19506c3fb27SDimitry Andric   std::optional<StubT> Result = Validate(*Val);
19606c3fb27SDimitry Andric   if (!Result.has_value())
19706c3fb27SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(Key));
19806c3fb27SDimitry Andric   return Result.value();
19906c3fb27SDimitry Andric }
20006c3fb27SDimitry Andric 
20106c3fb27SDimitry 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)20206c3fb27SDimitry Andric Expected<StubT> getRequiredValue(
20306c3fb27SDimitry Andric     TBDKey Key, const Object *Obj,
204647cbc5dSDimitry Andric     std::function<std::optional<JsonT>(const Object *, StringRef)> const
205647cbc5dSDimitry Andric         GetValue,
206647cbc5dSDimitry Andric     StubT DefaultValue, function_ref<std::optional<StubT>(JsonT)> Validate) {
20706c3fb27SDimitry Andric   std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
20806c3fb27SDimitry Andric   if (!Val)
20906c3fb27SDimitry Andric     return DefaultValue;
21006c3fb27SDimitry Andric 
21106c3fb27SDimitry Andric   std::optional<StubT> Result;
21206c3fb27SDimitry Andric   Result = Validate(*Val);
21306c3fb27SDimitry Andric   if (!Result.has_value())
21406c3fb27SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(Key));
21506c3fb27SDimitry Andric   return Result.value();
21606c3fb27SDimitry Andric }
21706c3fb27SDimitry Andric 
collectFromArray(TBDKey Key,const Object * Obj,function_ref<void (StringRef)> Append,bool IsRequired=false)21806c3fb27SDimitry Andric Error collectFromArray(TBDKey Key, const Object *Obj,
219647cbc5dSDimitry Andric                        function_ref<void(StringRef)> Append,
22006c3fb27SDimitry Andric                        bool IsRequired = false) {
22106c3fb27SDimitry Andric   const auto *Values = Obj->getArray(Keys[Key]);
22206c3fb27SDimitry Andric   if (!Values) {
22306c3fb27SDimitry Andric     if (IsRequired)
22406c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(Key));
22506c3fb27SDimitry Andric     return Error::success();
22606c3fb27SDimitry Andric   }
22706c3fb27SDimitry Andric 
22806c3fb27SDimitry Andric   for (const Value &Val : *Values) {
22906c3fb27SDimitry Andric     auto ValStr = Val.getAsString();
23006c3fb27SDimitry Andric     if (!ValStr.has_value())
23106c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(Key));
23206c3fb27SDimitry Andric     Append(ValStr.value());
23306c3fb27SDimitry Andric   }
23406c3fb27SDimitry Andric 
23506c3fb27SDimitry Andric   return Error::success();
23606c3fb27SDimitry Andric }
23706c3fb27SDimitry Andric 
23806c3fb27SDimitry Andric namespace StubParser {
23906c3fb27SDimitry Andric 
getVersion(const Object * File)24006c3fb27SDimitry Andric Expected<FileType> getVersion(const Object *File) {
24106c3fb27SDimitry Andric   auto VersionOrErr = getRequiredValue<int64_t, FileType>(
24206c3fb27SDimitry Andric       TBDKey::TBDVersion, File, &Object::getInteger,
24306c3fb27SDimitry Andric       [](int64_t Val) -> std::optional<FileType> {
24406c3fb27SDimitry Andric         unsigned Result = Val;
24506c3fb27SDimitry Andric         if (Result != 5)
24606c3fb27SDimitry Andric           return std::nullopt;
24706c3fb27SDimitry Andric         return FileType::TBD_V5;
24806c3fb27SDimitry Andric       });
24906c3fb27SDimitry Andric 
25006c3fb27SDimitry Andric   if (!VersionOrErr)
25106c3fb27SDimitry Andric     return VersionOrErr.takeError();
25206c3fb27SDimitry Andric   return *VersionOrErr;
25306c3fb27SDimitry Andric }
25406c3fb27SDimitry Andric 
getTargets(const Object * Section)25506c3fb27SDimitry Andric Expected<TargetList> getTargets(const Object *Section) {
25606c3fb27SDimitry Andric   const auto *Targets = Section->getArray(Keys[TBDKey::Targets]);
25706c3fb27SDimitry Andric   if (!Targets)
25806c3fb27SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets));
25906c3fb27SDimitry Andric 
26006c3fb27SDimitry Andric   TargetList IFTargets;
26106c3fb27SDimitry Andric   for (const Value &JSONTarget : *Targets) {
26206c3fb27SDimitry Andric     auto TargetStr = JSONTarget.getAsString();
26306c3fb27SDimitry Andric     if (!TargetStr.has_value())
26406c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
26506c3fb27SDimitry Andric     auto TargetOrErr = Target::create(TargetStr.value());
26606c3fb27SDimitry Andric     if (!TargetOrErr)
26706c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
26806c3fb27SDimitry Andric     IFTargets.push_back(*TargetOrErr);
26906c3fb27SDimitry Andric   }
27006c3fb27SDimitry Andric   return std::move(IFTargets);
27106c3fb27SDimitry Andric }
27206c3fb27SDimitry Andric 
getTargetsSection(const Object * Section)27306c3fb27SDimitry Andric Expected<TargetList> getTargetsSection(const Object *Section) {
27406c3fb27SDimitry Andric   const Array *Targets = Section->getArray(Keys[TBDKey::TargetInfo]);
27506c3fb27SDimitry Andric   if (!Targets)
27606c3fb27SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets));
27706c3fb27SDimitry Andric 
27806c3fb27SDimitry Andric   TargetList IFTargets;
27906c3fb27SDimitry Andric   for (const Value &JSONTarget : *Targets) {
28006c3fb27SDimitry Andric     const auto *Obj = JSONTarget.getAsObject();
28106c3fb27SDimitry Andric     if (!Obj)
28206c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
28306c3fb27SDimitry Andric     auto TargetStr =
28406c3fb27SDimitry Andric         getRequiredValue<StringRef>(TBDKey::Target, Obj, &Object::getString);
28506c3fb27SDimitry Andric     if (!TargetStr)
28606c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
28706c3fb27SDimitry Andric     auto TargetOrErr = Target::create(*TargetStr);
28806c3fb27SDimitry Andric     if (!TargetOrErr)
28906c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
2905f757f3fSDimitry Andric 
2915f757f3fSDimitry Andric     auto VersionStr = Obj->getString(Keys[TBDKey::Deployment]);
2925f757f3fSDimitry Andric     VersionTuple Version;
2935f757f3fSDimitry Andric     if (VersionStr && Version.tryParse(*VersionStr))
2945f757f3fSDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Deployment));
29506c3fb27SDimitry Andric     TargetOrErr->MinDeployment = Version;
2965f757f3fSDimitry Andric 
29706c3fb27SDimitry Andric     // Convert to LLVM::Triple to accurately compute minOS + platform + arch
29806c3fb27SDimitry Andric     // pairing.
29906c3fb27SDimitry Andric     IFTargets.push_back(
30006c3fb27SDimitry Andric         MachO::Target(Triple(getTargetTripleName(*TargetOrErr))));
30106c3fb27SDimitry Andric   }
30206c3fb27SDimitry Andric   return std::move(IFTargets);
30306c3fb27SDimitry Andric }
30406c3fb27SDimitry Andric 
collectSymbolsFromSegment(const Object * Segment,TargetsToSymbols & Result,SymbolFlags SectionFlag)30506c3fb27SDimitry Andric Error collectSymbolsFromSegment(const Object *Segment, TargetsToSymbols &Result,
30606c3fb27SDimitry Andric                                 SymbolFlags SectionFlag) {
30706c3fb27SDimitry Andric   auto Err = collectFromArray(
30806c3fb27SDimitry Andric       TBDKey::Globals, Segment, [&Result, &SectionFlag](StringRef Name) {
309*0fca6ea1SDimitry Andric         JSONSymbol Sym = {EncodeKind::GlobalSymbol, Name.str(), SectionFlag};
31006c3fb27SDimitry Andric         Result.back().second.emplace_back(Sym);
31106c3fb27SDimitry Andric       });
31206c3fb27SDimitry Andric   if (Err)
31306c3fb27SDimitry Andric     return Err;
31406c3fb27SDimitry Andric 
31506c3fb27SDimitry Andric   Err = collectFromArray(
31606c3fb27SDimitry Andric       TBDKey::ObjCClass, Segment, [&Result, &SectionFlag](StringRef Name) {
317*0fca6ea1SDimitry Andric         JSONSymbol Sym = {EncodeKind::ObjectiveCClass, Name.str(), SectionFlag};
31806c3fb27SDimitry Andric         Result.back().second.emplace_back(Sym);
31906c3fb27SDimitry Andric       });
32006c3fb27SDimitry Andric   if (Err)
32106c3fb27SDimitry Andric     return Err;
32206c3fb27SDimitry Andric 
32306c3fb27SDimitry Andric   Err = collectFromArray(TBDKey::ObjCEHType, Segment,
32406c3fb27SDimitry Andric                          [&Result, &SectionFlag](StringRef Name) {
325*0fca6ea1SDimitry Andric                            JSONSymbol Sym = {EncodeKind::ObjectiveCClassEHType,
32606c3fb27SDimitry Andric                                              Name.str(), SectionFlag};
32706c3fb27SDimitry Andric                            Result.back().second.emplace_back(Sym);
32806c3fb27SDimitry Andric                          });
32906c3fb27SDimitry Andric   if (Err)
33006c3fb27SDimitry Andric     return Err;
33106c3fb27SDimitry Andric 
33206c3fb27SDimitry Andric   Err = collectFromArray(
33306c3fb27SDimitry Andric       TBDKey::ObjCIvar, Segment, [&Result, &SectionFlag](StringRef Name) {
334*0fca6ea1SDimitry Andric         JSONSymbol Sym = {EncodeKind::ObjectiveCInstanceVariable, Name.str(),
33506c3fb27SDimitry Andric                           SectionFlag};
33606c3fb27SDimitry Andric         Result.back().second.emplace_back(Sym);
33706c3fb27SDimitry Andric       });
33806c3fb27SDimitry Andric   if (Err)
33906c3fb27SDimitry Andric     return Err;
34006c3fb27SDimitry Andric 
34106c3fb27SDimitry Andric   SymbolFlags WeakFlag =
34206c3fb27SDimitry Andric       SectionFlag |
34306c3fb27SDimitry Andric       (((SectionFlag & SymbolFlags::Undefined) == SymbolFlags::Undefined)
34406c3fb27SDimitry Andric            ? SymbolFlags::WeakReferenced
34506c3fb27SDimitry Andric            : SymbolFlags::WeakDefined);
34606c3fb27SDimitry Andric   Err = collectFromArray(
34706c3fb27SDimitry Andric       TBDKey::Weak, Segment, [&Result, WeakFlag](StringRef Name) {
348*0fca6ea1SDimitry Andric         JSONSymbol Sym = {EncodeKind::GlobalSymbol, Name.str(), WeakFlag};
34906c3fb27SDimitry Andric         Result.back().second.emplace_back(Sym);
35006c3fb27SDimitry Andric       });
35106c3fb27SDimitry Andric   if (Err)
35206c3fb27SDimitry Andric     return Err;
35306c3fb27SDimitry Andric 
35406c3fb27SDimitry Andric   Err = collectFromArray(
35506c3fb27SDimitry Andric       TBDKey::ThreadLocal, Segment, [&Result, SectionFlag](StringRef Name) {
356*0fca6ea1SDimitry Andric         JSONSymbol Sym = {EncodeKind::GlobalSymbol, Name.str(),
35706c3fb27SDimitry Andric                           SymbolFlags::ThreadLocalValue | SectionFlag};
35806c3fb27SDimitry Andric         Result.back().second.emplace_back(Sym);
35906c3fb27SDimitry Andric       });
36006c3fb27SDimitry Andric   if (Err)
36106c3fb27SDimitry Andric     return Err;
36206c3fb27SDimitry Andric 
36306c3fb27SDimitry Andric   return Error::success();
36406c3fb27SDimitry Andric }
36506c3fb27SDimitry Andric 
getNameSection(const Object * File)36606c3fb27SDimitry Andric Expected<StringRef> getNameSection(const Object *File) {
36706c3fb27SDimitry Andric   const Array *Section = File->getArray(Keys[TBDKey::InstallName]);
36806c3fb27SDimitry Andric   if (!Section)
36906c3fb27SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName));
37006c3fb27SDimitry Andric 
37106c3fb27SDimitry Andric   assert(!Section->empty() && "unexpected missing install name");
37206c3fb27SDimitry Andric   // TODO: Just take first for now.
37306c3fb27SDimitry Andric   const auto *Obj = Section->front().getAsObject();
37406c3fb27SDimitry Andric   if (!Obj)
37506c3fb27SDimitry Andric     return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName));
37606c3fb27SDimitry Andric 
37706c3fb27SDimitry Andric   return getRequiredValue<StringRef>(TBDKey::Name, Obj, &Object::getString);
37806c3fb27SDimitry Andric }
37906c3fb27SDimitry Andric 
getSymbolSection(const Object * File,TBDKey Key,TargetList & Targets)38006c3fb27SDimitry Andric Expected<TargetsToSymbols> getSymbolSection(const Object *File, TBDKey Key,
38106c3fb27SDimitry Andric                                             TargetList &Targets) {
38206c3fb27SDimitry Andric 
38306c3fb27SDimitry Andric   const Array *Section = File->getArray(Keys[Key]);
38406c3fb27SDimitry Andric   if (!Section)
38506c3fb27SDimitry Andric     return TargetsToSymbols();
38606c3fb27SDimitry Andric 
38706c3fb27SDimitry Andric   SymbolFlags SectionFlag;
38806c3fb27SDimitry Andric   switch (Key) {
38906c3fb27SDimitry Andric   case TBDKey::Reexports:
39006c3fb27SDimitry Andric     SectionFlag = SymbolFlags::Rexported;
39106c3fb27SDimitry Andric     break;
39206c3fb27SDimitry Andric   case TBDKey::Undefineds:
39306c3fb27SDimitry Andric     SectionFlag = SymbolFlags::Undefined;
39406c3fb27SDimitry Andric     break;
39506c3fb27SDimitry Andric   default:
39606c3fb27SDimitry Andric     SectionFlag = SymbolFlags::None;
39706c3fb27SDimitry Andric     break;
39806c3fb27SDimitry Andric   };
39906c3fb27SDimitry Andric 
40006c3fb27SDimitry Andric   TargetsToSymbols Result;
40106c3fb27SDimitry Andric   TargetList MappedTargets;
40206c3fb27SDimitry Andric   for (auto Val : *Section) {
40306c3fb27SDimitry Andric     auto *Obj = Val.getAsObject();
40406c3fb27SDimitry Andric     if (!Obj)
40506c3fb27SDimitry Andric       continue;
40606c3fb27SDimitry Andric 
40706c3fb27SDimitry Andric     auto TargetsOrErr = getTargets(Obj);
40806c3fb27SDimitry Andric     if (!TargetsOrErr) {
40906c3fb27SDimitry Andric       MappedTargets = Targets;
41006c3fb27SDimitry Andric       consumeError(TargetsOrErr.takeError());
41106c3fb27SDimitry Andric     } else {
41206c3fb27SDimitry Andric       MappedTargets = *TargetsOrErr;
41306c3fb27SDimitry Andric     }
41406c3fb27SDimitry Andric     Result.emplace_back(
41506c3fb27SDimitry Andric         std::make_pair(std::move(MappedTargets), std::vector<JSONSymbol>()));
41606c3fb27SDimitry Andric 
41706c3fb27SDimitry Andric     auto *DataSection = Obj->getObject(Keys[TBDKey::Data]);
41806c3fb27SDimitry Andric     auto *TextSection = Obj->getObject(Keys[TBDKey::Text]);
41906c3fb27SDimitry Andric     // There should be at least one valid section.
42006c3fb27SDimitry Andric     if (!DataSection && !TextSection)
42106c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(Key));
42206c3fb27SDimitry Andric 
42306c3fb27SDimitry Andric     if (DataSection) {
42406c3fb27SDimitry Andric       auto Err = collectSymbolsFromSegment(DataSection, Result,
42506c3fb27SDimitry Andric                                            SectionFlag | SymbolFlags::Data);
42606c3fb27SDimitry Andric       if (Err)
42706c3fb27SDimitry Andric         return std::move(Err);
42806c3fb27SDimitry Andric     }
42906c3fb27SDimitry Andric     if (TextSection) {
43006c3fb27SDimitry Andric       auto Err = collectSymbolsFromSegment(TextSection, Result,
43106c3fb27SDimitry Andric                                            SectionFlag | SymbolFlags::Text);
43206c3fb27SDimitry Andric       if (Err)
43306c3fb27SDimitry Andric         return std::move(Err);
43406c3fb27SDimitry Andric     }
43506c3fb27SDimitry Andric   }
43606c3fb27SDimitry Andric 
43706c3fb27SDimitry Andric   return std::move(Result);
43806c3fb27SDimitry Andric }
43906c3fb27SDimitry Andric 
getLibSection(const Object * File,TBDKey Key,TBDKey SubKey,const TargetList & Targets)44006c3fb27SDimitry Andric Expected<AttrToTargets> getLibSection(const Object *File, TBDKey Key,
44106c3fb27SDimitry Andric                                       TBDKey SubKey,
44206c3fb27SDimitry Andric                                       const TargetList &Targets) {
44306c3fb27SDimitry Andric   auto *Section = File->getArray(Keys[Key]);
44406c3fb27SDimitry Andric   if (!Section)
44506c3fb27SDimitry Andric     return AttrToTargets();
44606c3fb27SDimitry Andric 
44706c3fb27SDimitry Andric   AttrToTargets Result;
44806c3fb27SDimitry Andric   TargetList MappedTargets;
44906c3fb27SDimitry Andric   for (auto Val : *Section) {
45006c3fb27SDimitry Andric     auto *Obj = Val.getAsObject();
45106c3fb27SDimitry Andric     if (!Obj)
45206c3fb27SDimitry Andric       continue;
45306c3fb27SDimitry Andric 
45406c3fb27SDimitry Andric     auto TargetsOrErr = getTargets(Obj);
45506c3fb27SDimitry Andric     if (!TargetsOrErr) {
45606c3fb27SDimitry Andric       MappedTargets = Targets;
45706c3fb27SDimitry Andric       consumeError(TargetsOrErr.takeError());
45806c3fb27SDimitry Andric     } else {
45906c3fb27SDimitry Andric       MappedTargets = *TargetsOrErr;
46006c3fb27SDimitry Andric     }
46106c3fb27SDimitry Andric     auto Err =
46206c3fb27SDimitry Andric         collectFromArray(SubKey, Obj, [&Result, &MappedTargets](StringRef Key) {
46306c3fb27SDimitry Andric           Result[Key.str()] = MappedTargets;
46406c3fb27SDimitry Andric         });
46506c3fb27SDimitry Andric     if (Err)
46606c3fb27SDimitry Andric       return std::move(Err);
46706c3fb27SDimitry Andric   }
46806c3fb27SDimitry Andric 
46906c3fb27SDimitry Andric   return std::move(Result);
47006c3fb27SDimitry Andric }
47106c3fb27SDimitry Andric 
getUmbrellaSection(const Object * File,const TargetList & Targets)47206c3fb27SDimitry Andric Expected<AttrToTargets> getUmbrellaSection(const Object *File,
47306c3fb27SDimitry Andric                                            const TargetList &Targets) {
47406c3fb27SDimitry Andric   const auto *Umbrella = File->getArray(Keys[TBDKey::ParentUmbrella]);
47506c3fb27SDimitry Andric   if (!Umbrella)
47606c3fb27SDimitry Andric     return AttrToTargets();
47706c3fb27SDimitry Andric 
47806c3fb27SDimitry Andric   AttrToTargets Result;
47906c3fb27SDimitry Andric   TargetList MappedTargets;
48006c3fb27SDimitry Andric   for (auto Val : *Umbrella) {
48106c3fb27SDimitry Andric     auto *Obj = Val.getAsObject();
48206c3fb27SDimitry Andric     if (!Obj)
48306c3fb27SDimitry Andric       return make_error<JSONStubError>(
48406c3fb27SDimitry Andric           getParseErrorMsg(TBDKey::ParentUmbrella));
48506c3fb27SDimitry Andric 
48606c3fb27SDimitry Andric     // Get Targets section.
48706c3fb27SDimitry Andric     auto TargetsOrErr = getTargets(Obj);
48806c3fb27SDimitry Andric     if (!TargetsOrErr) {
48906c3fb27SDimitry Andric       MappedTargets = Targets;
49006c3fb27SDimitry Andric       consumeError(TargetsOrErr.takeError());
49106c3fb27SDimitry Andric     } else {
49206c3fb27SDimitry Andric       MappedTargets = *TargetsOrErr;
49306c3fb27SDimitry Andric     }
49406c3fb27SDimitry Andric 
49506c3fb27SDimitry Andric     auto UmbrellaOrErr =
49606c3fb27SDimitry Andric         getRequiredValue<StringRef>(TBDKey::Umbrella, Obj, &Object::getString);
49706c3fb27SDimitry Andric     if (!UmbrellaOrErr)
49806c3fb27SDimitry Andric       return UmbrellaOrErr.takeError();
49906c3fb27SDimitry Andric     Result[UmbrellaOrErr->str()] = Targets;
50006c3fb27SDimitry Andric   }
50106c3fb27SDimitry Andric   return std::move(Result);
50206c3fb27SDimitry Andric }
50306c3fb27SDimitry Andric 
getSwiftVersion(const Object * File)50406c3fb27SDimitry Andric Expected<uint8_t> getSwiftVersion(const Object *File) {
50506c3fb27SDimitry Andric   const Array *Versions = File->getArray(Keys[TBDKey::SwiftABI]);
50606c3fb27SDimitry Andric   if (!Versions)
50706c3fb27SDimitry Andric     return 0;
50806c3fb27SDimitry Andric 
50906c3fb27SDimitry Andric   for (const auto &Val : *Versions) {
51006c3fb27SDimitry Andric     const auto *Obj = Val.getAsObject();
51106c3fb27SDimitry Andric     if (!Obj)
51206c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::SwiftABI));
51306c3fb27SDimitry Andric 
51406c3fb27SDimitry Andric     // TODO: Take first for now.
51506c3fb27SDimitry Andric     return getRequiredValue<int64_t, uint8_t>(TBDKey::ABI, Obj,
51606c3fb27SDimitry Andric                                               &Object::getInteger);
51706c3fb27SDimitry Andric   }
51806c3fb27SDimitry Andric 
51906c3fb27SDimitry Andric   return 0;
52006c3fb27SDimitry Andric }
52106c3fb27SDimitry Andric 
getPackedVersion(const Object * File,TBDKey Key)52206c3fb27SDimitry Andric Expected<PackedVersion> getPackedVersion(const Object *File, TBDKey Key) {
52306c3fb27SDimitry Andric   const Array *Versions = File->getArray(Keys[Key]);
52406c3fb27SDimitry Andric   if (!Versions)
52506c3fb27SDimitry Andric     return PackedVersion(1, 0, 0);
52606c3fb27SDimitry Andric 
52706c3fb27SDimitry Andric   for (const auto &Val : *Versions) {
52806c3fb27SDimitry Andric     const auto *Obj = Val.getAsObject();
52906c3fb27SDimitry Andric     if (!Obj)
53006c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(Key));
53106c3fb27SDimitry Andric 
53206c3fb27SDimitry Andric     auto ValidatePV = [](StringRef Version) -> std::optional<PackedVersion> {
53306c3fb27SDimitry Andric       PackedVersion PV;
53406c3fb27SDimitry Andric       auto [success, truncated] = PV.parse64(Version);
53506c3fb27SDimitry Andric       if (!success || truncated)
53606c3fb27SDimitry Andric         return std::nullopt;
53706c3fb27SDimitry Andric       return PV;
53806c3fb27SDimitry Andric     };
53906c3fb27SDimitry Andric     // TODO: Take first for now.
54006c3fb27SDimitry Andric     return getRequiredValue<StringRef, PackedVersion>(
54106c3fb27SDimitry Andric         TBDKey::Version, Obj, &Object::getString, PackedVersion(1, 0, 0),
54206c3fb27SDimitry Andric         ValidatePV);
54306c3fb27SDimitry Andric   }
54406c3fb27SDimitry Andric 
54506c3fb27SDimitry Andric   return PackedVersion(1, 0, 0);
54606c3fb27SDimitry Andric }
54706c3fb27SDimitry Andric 
getFlags(const Object * File)54806c3fb27SDimitry Andric Expected<TBDFlags> getFlags(const Object *File) {
54906c3fb27SDimitry Andric   TBDFlags Flags = TBDFlags::None;
55006c3fb27SDimitry Andric   const Array *Section = File->getArray(Keys[TBDKey::Flags]);
5515f757f3fSDimitry Andric   if (!Section || Section->empty())
55206c3fb27SDimitry Andric     return Flags;
55306c3fb27SDimitry Andric 
55406c3fb27SDimitry Andric   for (auto &Val : *Section) {
5555f757f3fSDimitry Andric     // FIXME: Flags currently apply to all target triples.
55606c3fb27SDimitry Andric     const auto *Obj = Val.getAsObject();
55706c3fb27SDimitry Andric     if (!Obj)
55806c3fb27SDimitry Andric       return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Flags));
55906c3fb27SDimitry Andric 
56006c3fb27SDimitry Andric     auto FlagsOrErr =
56106c3fb27SDimitry Andric         collectFromArray(TBDKey::Attributes, Obj, [&Flags](StringRef Flag) {
56206c3fb27SDimitry Andric           TBDFlags TBDFlag =
56306c3fb27SDimitry Andric               StringSwitch<TBDFlags>(Flag)
56406c3fb27SDimitry Andric                   .Case("flat_namespace", TBDFlags::FlatNamespace)
56506c3fb27SDimitry Andric                   .Case("not_app_extension_safe",
56606c3fb27SDimitry Andric                         TBDFlags::NotApplicationExtensionSafe)
5675f757f3fSDimitry Andric                   .Case("sim_support", TBDFlags::SimulatorSupport)
5685f757f3fSDimitry Andric                   .Case("not_for_dyld_shared_cache",
5695f757f3fSDimitry Andric                         TBDFlags::OSLibNotForSharedCache)
57006c3fb27SDimitry Andric                   .Default(TBDFlags::None);
57106c3fb27SDimitry Andric           Flags |= TBDFlag;
57206c3fb27SDimitry Andric         });
57306c3fb27SDimitry Andric 
57406c3fb27SDimitry Andric     if (FlagsOrErr)
57506c3fb27SDimitry Andric       return std::move(FlagsOrErr);
57606c3fb27SDimitry Andric 
57706c3fb27SDimitry Andric     return Flags;
57806c3fb27SDimitry Andric   }
57906c3fb27SDimitry Andric 
58006c3fb27SDimitry Andric   return Flags;
58106c3fb27SDimitry Andric }
58206c3fb27SDimitry Andric 
58306c3fb27SDimitry Andric using IFPtr = std::unique_ptr<InterfaceFile>;
parseToInterfaceFile(const Object * File)58406c3fb27SDimitry Andric Expected<IFPtr> parseToInterfaceFile(const Object *File) {
58506c3fb27SDimitry Andric   auto TargetsOrErr = getTargetsSection(File);
58606c3fb27SDimitry Andric   if (!TargetsOrErr)
58706c3fb27SDimitry Andric     return TargetsOrErr.takeError();
58806c3fb27SDimitry Andric   TargetList Targets = *TargetsOrErr;
58906c3fb27SDimitry Andric 
59006c3fb27SDimitry Andric   auto NameOrErr = getNameSection(File);
59106c3fb27SDimitry Andric   if (!NameOrErr)
59206c3fb27SDimitry Andric     return NameOrErr.takeError();
59306c3fb27SDimitry Andric   StringRef Name = *NameOrErr;
59406c3fb27SDimitry Andric 
59506c3fb27SDimitry Andric   auto CurrVersionOrErr = getPackedVersion(File, TBDKey::CurrentVersion);
59606c3fb27SDimitry Andric   if (!CurrVersionOrErr)
59706c3fb27SDimitry Andric     return CurrVersionOrErr.takeError();
59806c3fb27SDimitry Andric   PackedVersion CurrVersion = *CurrVersionOrErr;
59906c3fb27SDimitry Andric 
60006c3fb27SDimitry Andric   auto CompVersionOrErr = getPackedVersion(File, TBDKey::CompatibilityVersion);
60106c3fb27SDimitry Andric   if (!CompVersionOrErr)
60206c3fb27SDimitry Andric     return CompVersionOrErr.takeError();
60306c3fb27SDimitry Andric   PackedVersion CompVersion = *CompVersionOrErr;
60406c3fb27SDimitry Andric 
60506c3fb27SDimitry Andric   auto SwiftABIOrErr = getSwiftVersion(File);
60606c3fb27SDimitry Andric   if (!SwiftABIOrErr)
60706c3fb27SDimitry Andric     return SwiftABIOrErr.takeError();
60806c3fb27SDimitry Andric   uint8_t SwiftABI = *SwiftABIOrErr;
60906c3fb27SDimitry Andric 
61006c3fb27SDimitry Andric   auto FlagsOrErr = getFlags(File);
61106c3fb27SDimitry Andric   if (!FlagsOrErr)
61206c3fb27SDimitry Andric     return FlagsOrErr.takeError();
61306c3fb27SDimitry Andric   TBDFlags Flags = *FlagsOrErr;
61406c3fb27SDimitry Andric 
61506c3fb27SDimitry Andric   auto UmbrellasOrErr = getUmbrellaSection(File, Targets);
61606c3fb27SDimitry Andric   if (!UmbrellasOrErr)
61706c3fb27SDimitry Andric     return UmbrellasOrErr.takeError();
61806c3fb27SDimitry Andric   AttrToTargets Umbrellas = *UmbrellasOrErr;
61906c3fb27SDimitry Andric 
62006c3fb27SDimitry Andric   auto ClientsOrErr =
62106c3fb27SDimitry Andric       getLibSection(File, TBDKey::AllowableClients, TBDKey::Clients, Targets);
62206c3fb27SDimitry Andric   if (!ClientsOrErr)
62306c3fb27SDimitry Andric     return ClientsOrErr.takeError();
62406c3fb27SDimitry Andric   AttrToTargets Clients = *ClientsOrErr;
62506c3fb27SDimitry Andric 
62606c3fb27SDimitry Andric   auto RLOrErr =
62706c3fb27SDimitry Andric       getLibSection(File, TBDKey::ReexportLibs, TBDKey::Names, Targets);
62806c3fb27SDimitry Andric   if (!RLOrErr)
62906c3fb27SDimitry Andric     return RLOrErr.takeError();
63006c3fb27SDimitry Andric   AttrToTargets ReexportLibs = std::move(*RLOrErr);
63106c3fb27SDimitry Andric 
63206c3fb27SDimitry Andric   auto RPathsOrErr = getLibSection(File, TBDKey::RPath, TBDKey::Paths, Targets);
63306c3fb27SDimitry Andric   if (!RPathsOrErr)
63406c3fb27SDimitry Andric     return RPathsOrErr.takeError();
63506c3fb27SDimitry Andric   AttrToTargets RPaths = std::move(*RPathsOrErr);
63606c3fb27SDimitry Andric 
63706c3fb27SDimitry Andric   auto ExportsOrErr = getSymbolSection(File, TBDKey::Exports, Targets);
63806c3fb27SDimitry Andric   if (!ExportsOrErr)
63906c3fb27SDimitry Andric     return ExportsOrErr.takeError();
64006c3fb27SDimitry Andric   TargetsToSymbols Exports = std::move(*ExportsOrErr);
64106c3fb27SDimitry Andric 
64206c3fb27SDimitry Andric   auto ReexportsOrErr = getSymbolSection(File, TBDKey::Reexports, Targets);
64306c3fb27SDimitry Andric   if (!ReexportsOrErr)
64406c3fb27SDimitry Andric     return ReexportsOrErr.takeError();
64506c3fb27SDimitry Andric   TargetsToSymbols Reexports = std::move(*ReexportsOrErr);
64606c3fb27SDimitry Andric 
64706c3fb27SDimitry Andric   auto UndefinedsOrErr = getSymbolSection(File, TBDKey::Undefineds, Targets);
64806c3fb27SDimitry Andric   if (!UndefinedsOrErr)
64906c3fb27SDimitry Andric     return UndefinedsOrErr.takeError();
65006c3fb27SDimitry Andric   TargetsToSymbols Undefineds = std::move(*UndefinedsOrErr);
65106c3fb27SDimitry Andric 
65206c3fb27SDimitry Andric   IFPtr F(new InterfaceFile);
65306c3fb27SDimitry Andric   F->setInstallName(Name);
65406c3fb27SDimitry Andric   F->setCurrentVersion(CurrVersion);
65506c3fb27SDimitry Andric   F->setCompatibilityVersion(CompVersion);
65606c3fb27SDimitry Andric   F->setSwiftABIVersion(SwiftABI);
65706c3fb27SDimitry Andric   F->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
65806c3fb27SDimitry Andric   F->setApplicationExtensionSafe(
65906c3fb27SDimitry Andric       !(Flags & TBDFlags::NotApplicationExtensionSafe));
6605f757f3fSDimitry Andric   F->setSimulatorSupport((Flags & TBDFlags::SimulatorSupport));
6615f757f3fSDimitry Andric   F->setOSLibNotForSharedCache((Flags & TBDFlags::OSLibNotForSharedCache));
66206c3fb27SDimitry Andric   for (auto &T : Targets)
66306c3fb27SDimitry Andric     F->addTarget(T);
66406c3fb27SDimitry Andric   for (auto &[Lib, Targets] : Clients)
66506c3fb27SDimitry Andric     for (auto Target : Targets)
66606c3fb27SDimitry Andric       F->addAllowableClient(Lib, Target);
66706c3fb27SDimitry Andric   for (auto &[Lib, Targets] : ReexportLibs)
66806c3fb27SDimitry Andric     for (auto Target : Targets)
66906c3fb27SDimitry Andric       F->addReexportedLibrary(Lib, Target);
67006c3fb27SDimitry Andric   for (auto &[Lib, Targets] : Umbrellas)
67106c3fb27SDimitry Andric     for (auto Target : Targets)
67206c3fb27SDimitry Andric       F->addParentUmbrella(Target, Lib);
67306c3fb27SDimitry Andric   for (auto &[Path, Targets] : RPaths)
67406c3fb27SDimitry Andric     for (auto Target : Targets)
675*0fca6ea1SDimitry Andric       F->addRPath(Path, Target);
67606c3fb27SDimitry Andric   for (auto &[Targets, Symbols] : Exports)
67706c3fb27SDimitry Andric     for (auto &Sym : Symbols)
67806c3fb27SDimitry Andric       F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
67906c3fb27SDimitry Andric   for (auto &[Targets, Symbols] : Reexports)
68006c3fb27SDimitry Andric     for (auto &Sym : Symbols)
68106c3fb27SDimitry Andric       F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
68206c3fb27SDimitry Andric   for (auto &[Targets, Symbols] : Undefineds)
68306c3fb27SDimitry Andric     for (auto &Sym : Symbols)
68406c3fb27SDimitry Andric       F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
68506c3fb27SDimitry Andric 
68606c3fb27SDimitry Andric   return std::move(F);
68706c3fb27SDimitry Andric }
68806c3fb27SDimitry Andric 
getInlinedLibs(const Object * File)68906c3fb27SDimitry Andric Expected<std::vector<IFPtr>> getInlinedLibs(const Object *File) {
69006c3fb27SDimitry Andric   std::vector<IFPtr> IFs;
69106c3fb27SDimitry Andric   const Array *Files = File->getArray(Keys[TBDKey::Documents]);
69206c3fb27SDimitry Andric   if (!Files)
69306c3fb27SDimitry Andric     return std::move(IFs);
69406c3fb27SDimitry Andric 
69506c3fb27SDimitry Andric   for (auto Lib : *Files) {
69606c3fb27SDimitry Andric     auto IFOrErr = parseToInterfaceFile(Lib.getAsObject());
69706c3fb27SDimitry Andric     if (!IFOrErr)
69806c3fb27SDimitry Andric       return IFOrErr.takeError();
69906c3fb27SDimitry Andric     auto IF = std::move(*IFOrErr);
70006c3fb27SDimitry Andric     IFs.emplace_back(std::move(IF));
70106c3fb27SDimitry Andric   }
70206c3fb27SDimitry Andric   return std::move(IFs);
70306c3fb27SDimitry Andric }
70406c3fb27SDimitry Andric 
70506c3fb27SDimitry Andric } // namespace StubParser
70606c3fb27SDimitry Andric } // namespace
70706c3fb27SDimitry Andric 
70806c3fb27SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
getInterfaceFileFromJSON(StringRef JSON)70906c3fb27SDimitry Andric MachO::getInterfaceFileFromJSON(StringRef JSON) {
71006c3fb27SDimitry Andric   auto ValOrErr = parse(JSON);
71106c3fb27SDimitry Andric   if (!ValOrErr)
71206c3fb27SDimitry Andric     return ValOrErr.takeError();
71306c3fb27SDimitry Andric 
71406c3fb27SDimitry Andric   auto *Root = ValOrErr->getAsObject();
71506c3fb27SDimitry Andric   auto VersionOrErr = StubParser::getVersion(Root);
71606c3fb27SDimitry Andric   if (!VersionOrErr)
71706c3fb27SDimitry Andric     return VersionOrErr.takeError();
71806c3fb27SDimitry Andric   FileType Version = *VersionOrErr;
71906c3fb27SDimitry Andric 
72006c3fb27SDimitry Andric   Object *MainLib = Root->getObject(Keys[TBDKey::MainLibrary]);
72106c3fb27SDimitry Andric   auto IFOrErr = StubParser::parseToInterfaceFile(MainLib);
72206c3fb27SDimitry Andric   if (!IFOrErr)
72306c3fb27SDimitry Andric     return IFOrErr.takeError();
72406c3fb27SDimitry Andric   (*IFOrErr)->setFileType(Version);
72506c3fb27SDimitry Andric   std::unique_ptr<InterfaceFile> IF(std::move(*IFOrErr));
72606c3fb27SDimitry Andric 
72706c3fb27SDimitry Andric   auto IFsOrErr = StubParser::getInlinedLibs(Root);
72806c3fb27SDimitry Andric   if (!IFsOrErr)
72906c3fb27SDimitry Andric     return IFsOrErr.takeError();
73006c3fb27SDimitry Andric   for (auto &File : *IFsOrErr) {
73106c3fb27SDimitry Andric     File->setFileType(Version);
73206c3fb27SDimitry Andric     IF->addDocument(std::shared_ptr<InterfaceFile>(std::move(File)));
73306c3fb27SDimitry Andric   }
73406c3fb27SDimitry Andric   return std::move(IF);
73506c3fb27SDimitry Andric }
73606c3fb27SDimitry Andric 
73706c3fb27SDimitry Andric namespace {
73806c3fb27SDimitry Andric 
73906c3fb27SDimitry Andric template <typename ContainerT = Array>
insertNonEmptyValues(Object & Obj,TBDKey Key,ContainerT && Contents)74006c3fb27SDimitry Andric bool insertNonEmptyValues(Object &Obj, TBDKey Key, ContainerT &&Contents) {
74106c3fb27SDimitry Andric   if (Contents.empty())
74206c3fb27SDimitry Andric     return false;
74306c3fb27SDimitry Andric   Obj[Keys[Key]] = std::move(Contents);
74406c3fb27SDimitry Andric   return true;
74506c3fb27SDimitry Andric }
74606c3fb27SDimitry Andric 
getFormattedStr(const MachO::Target & Targ)74706c3fb27SDimitry Andric std::string getFormattedStr(const MachO::Target &Targ) {
74806c3fb27SDimitry Andric   std::string PlatformStr = Targ.Platform == PLATFORM_MACCATALYST
74906c3fb27SDimitry Andric                                 ? "maccatalyst"
75006c3fb27SDimitry Andric                                 : getOSAndEnvironmentName(Targ.Platform);
75106c3fb27SDimitry Andric   return (getArchitectureName(Targ.Arch) + "-" + PlatformStr).str();
75206c3fb27SDimitry Andric }
75306c3fb27SDimitry Andric 
75406c3fb27SDimitry Andric template <typename AggregateT>
serializeTargets(const AggregateT Targets,const TargetList & ActiveTargets)75506c3fb27SDimitry Andric std::vector<std::string> serializeTargets(const AggregateT Targets,
75606c3fb27SDimitry Andric                                           const TargetList &ActiveTargets) {
75706c3fb27SDimitry Andric   std::vector<std::string> TargetsStr;
75806c3fb27SDimitry Andric   if (Targets.size() == ActiveTargets.size())
75906c3fb27SDimitry Andric     return TargetsStr;
76006c3fb27SDimitry Andric 
7615f757f3fSDimitry Andric   for (const MachO::Target &Target : Targets)
76206c3fb27SDimitry Andric     TargetsStr.emplace_back(getFormattedStr(Target));
7635f757f3fSDimitry Andric 
76406c3fb27SDimitry Andric   return TargetsStr;
76506c3fb27SDimitry Andric }
76606c3fb27SDimitry Andric 
serializeTargetInfo(const TargetList & ActiveTargets)76706c3fb27SDimitry Andric Array serializeTargetInfo(const TargetList &ActiveTargets) {
76806c3fb27SDimitry Andric   Array Targets;
76906c3fb27SDimitry Andric   for (const auto Targ : ActiveTargets) {
77006c3fb27SDimitry Andric     Object TargetInfo;
7715f757f3fSDimitry Andric     if (!Targ.MinDeployment.empty())
77206c3fb27SDimitry Andric       TargetInfo[Keys[TBDKey::Deployment]] = Targ.MinDeployment.getAsString();
77306c3fb27SDimitry Andric     TargetInfo[Keys[TBDKey::Target]] = getFormattedStr(Targ);
77406c3fb27SDimitry Andric     Targets.emplace_back(std::move(TargetInfo));
77506c3fb27SDimitry Andric   }
77606c3fb27SDimitry Andric   return Targets;
77706c3fb27SDimitry Andric }
77806c3fb27SDimitry Andric 
77906c3fb27SDimitry Andric template <typename ValueT, typename EntryT = ValueT>
serializeScalar(TBDKey Key,ValueT Value,ValueT Default=ValueT ())78006c3fb27SDimitry Andric Array serializeScalar(TBDKey Key, ValueT Value, ValueT Default = ValueT()) {
78106c3fb27SDimitry Andric   if (Value == Default)
78206c3fb27SDimitry Andric     return {};
78306c3fb27SDimitry Andric   Array Container;
78406c3fb27SDimitry Andric   Object ScalarObj({Object::KV({Keys[Key], EntryT(Value)})});
78506c3fb27SDimitry Andric 
78606c3fb27SDimitry Andric   Container.emplace_back(std::move(ScalarObj));
78706c3fb27SDimitry Andric   return Container;
78806c3fb27SDimitry Andric }
78906c3fb27SDimitry Andric 
79006c3fb27SDimitry Andric using TargetsToValuesMap =
79106c3fb27SDimitry Andric     std::map<std::vector<std::string>, std::vector<std::string>>;
79206c3fb27SDimitry Andric 
79306c3fb27SDimitry Andric template <typename AggregateT = TargetsToValuesMap>
serializeAttrToTargets(AggregateT & Entries,TBDKey Key)79406c3fb27SDimitry Andric Array serializeAttrToTargets(AggregateT &Entries, TBDKey Key) {
79506c3fb27SDimitry Andric   Array Container;
79606c3fb27SDimitry Andric   for (const auto &[Targets, Values] : Entries) {
79706c3fb27SDimitry Andric     Object Obj;
79806c3fb27SDimitry Andric     insertNonEmptyValues(Obj, TBDKey::Targets, std::move(Targets));
79906c3fb27SDimitry Andric     Obj[Keys[Key]] = Values;
80006c3fb27SDimitry Andric     Container.emplace_back(std::move(Obj));
80106c3fb27SDimitry Andric   }
80206c3fb27SDimitry Andric   return Container;
80306c3fb27SDimitry Andric }
80406c3fb27SDimitry Andric 
80506c3fb27SDimitry Andric template <typename ValueT = std::string,
80606c3fb27SDimitry Andric           typename AggregateT = std::vector<std::pair<MachO::Target, ValueT>>>
serializeField(TBDKey Key,const AggregateT & Values,const TargetList & ActiveTargets,bool IsArray=true)80706c3fb27SDimitry Andric Array serializeField(TBDKey Key, const AggregateT &Values,
80806c3fb27SDimitry Andric                      const TargetList &ActiveTargets, bool IsArray = true) {
80906c3fb27SDimitry Andric   std::map<ValueT, std::set<MachO::Target>> Entries;
81006c3fb27SDimitry Andric   for (const auto &[Target, Val] : Values)
81106c3fb27SDimitry Andric     Entries[Val].insert(Target);
81206c3fb27SDimitry Andric 
81306c3fb27SDimitry Andric   if (!IsArray) {
81406c3fb27SDimitry Andric     std::map<std::vector<std::string>, std::string> FinalEntries;
81506c3fb27SDimitry Andric     for (const auto &[Val, Targets] : Entries)
81606c3fb27SDimitry Andric       FinalEntries[serializeTargets(Targets, ActiveTargets)] = Val;
81706c3fb27SDimitry Andric     return serializeAttrToTargets(FinalEntries, Key);
81806c3fb27SDimitry Andric   }
81906c3fb27SDimitry Andric 
82006c3fb27SDimitry Andric   TargetsToValuesMap FinalEntries;
82106c3fb27SDimitry Andric   for (const auto &[Val, Targets] : Entries)
82206c3fb27SDimitry Andric     FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(Val);
82306c3fb27SDimitry Andric   return serializeAttrToTargets(FinalEntries, Key);
82406c3fb27SDimitry Andric }
82506c3fb27SDimitry Andric 
serializeField(TBDKey Key,const std::vector<InterfaceFileRef> & Values,const TargetList & ActiveTargets)82606c3fb27SDimitry Andric Array serializeField(TBDKey Key, const std::vector<InterfaceFileRef> &Values,
82706c3fb27SDimitry Andric                      const TargetList &ActiveTargets) {
82806c3fb27SDimitry Andric   TargetsToValuesMap FinalEntries;
82906c3fb27SDimitry Andric   for (const auto &Ref : Values) {
83006c3fb27SDimitry Andric     TargetList Targets{Ref.targets().begin(), Ref.targets().end()};
83106c3fb27SDimitry Andric     FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(
83206c3fb27SDimitry Andric         Ref.getInstallName());
83306c3fb27SDimitry Andric   }
83406c3fb27SDimitry Andric   return serializeAttrToTargets(FinalEntries, Key);
83506c3fb27SDimitry Andric }
83606c3fb27SDimitry Andric 
83706c3fb27SDimitry Andric struct SymbolFields {
83806c3fb27SDimitry Andric   struct SymbolTypes {
83906c3fb27SDimitry Andric     std::vector<StringRef> Weaks;
84006c3fb27SDimitry Andric     std::vector<StringRef> Globals;
84106c3fb27SDimitry Andric     std::vector<StringRef> TLV;
84206c3fb27SDimitry Andric     std::vector<StringRef> ObjCClasses;
84306c3fb27SDimitry Andric     std::vector<StringRef> IVars;
84406c3fb27SDimitry Andric     std::vector<StringRef> EHTypes;
84506c3fb27SDimitry Andric 
empty__anon8456efec0c11::SymbolFields::SymbolTypes84606c3fb27SDimitry Andric     bool empty() const {
84706c3fb27SDimitry Andric       return Weaks.empty() && Globals.empty() && TLV.empty() &&
84806c3fb27SDimitry Andric              ObjCClasses.empty() && IVars.empty() && EHTypes.empty();
84906c3fb27SDimitry Andric     }
85006c3fb27SDimitry Andric   };
85106c3fb27SDimitry Andric   SymbolTypes Data;
85206c3fb27SDimitry Andric   SymbolTypes Text;
85306c3fb27SDimitry Andric };
85406c3fb27SDimitry Andric 
serializeSymbols(InterfaceFile::const_filtered_symbol_range Symbols,const TargetList & ActiveTargets)85506c3fb27SDimitry Andric Array serializeSymbols(InterfaceFile::const_filtered_symbol_range Symbols,
85606c3fb27SDimitry Andric                        const TargetList &ActiveTargets) {
85706c3fb27SDimitry Andric   auto AssignForSymbolType = [](SymbolFields::SymbolTypes &Assignment,
85806c3fb27SDimitry Andric                                 const Symbol *Sym) {
85906c3fb27SDimitry Andric     switch (Sym->getKind()) {
860*0fca6ea1SDimitry Andric     case EncodeKind::ObjectiveCClass:
86106c3fb27SDimitry Andric       Assignment.ObjCClasses.emplace_back(Sym->getName());
86206c3fb27SDimitry Andric       return;
863*0fca6ea1SDimitry Andric     case EncodeKind::ObjectiveCClassEHType:
86406c3fb27SDimitry Andric       Assignment.EHTypes.emplace_back(Sym->getName());
86506c3fb27SDimitry Andric       return;
866*0fca6ea1SDimitry Andric     case EncodeKind::ObjectiveCInstanceVariable:
86706c3fb27SDimitry Andric       Assignment.IVars.emplace_back(Sym->getName());
86806c3fb27SDimitry Andric       return;
869*0fca6ea1SDimitry Andric     case EncodeKind::GlobalSymbol: {
87006c3fb27SDimitry Andric       if (Sym->isWeakReferenced() || Sym->isWeakDefined())
87106c3fb27SDimitry Andric         Assignment.Weaks.emplace_back(Sym->getName());
87206c3fb27SDimitry Andric       else if (Sym->isThreadLocalValue())
87306c3fb27SDimitry Andric         Assignment.TLV.emplace_back(Sym->getName());
87406c3fb27SDimitry Andric       else
87506c3fb27SDimitry Andric         Assignment.Globals.emplace_back(Sym->getName());
87606c3fb27SDimitry Andric       return;
87706c3fb27SDimitry Andric     }
87806c3fb27SDimitry Andric     }
87906c3fb27SDimitry Andric   };
88006c3fb27SDimitry Andric 
88106c3fb27SDimitry Andric   std::map<std::vector<std::string>, SymbolFields> Entries;
88206c3fb27SDimitry Andric   for (const auto *Sym : Symbols) {
88306c3fb27SDimitry Andric     std::set<MachO::Target> Targets{Sym->targets().begin(),
88406c3fb27SDimitry Andric                                     Sym->targets().end()};
88506c3fb27SDimitry Andric     auto JSONTargets = serializeTargets(Targets, ActiveTargets);
88606c3fb27SDimitry Andric     if (Sym->isData())
88706c3fb27SDimitry Andric       AssignForSymbolType(Entries[std::move(JSONTargets)].Data, Sym);
88806c3fb27SDimitry Andric     else if (Sym->isText())
88906c3fb27SDimitry Andric       AssignForSymbolType(Entries[std::move(JSONTargets)].Text, Sym);
89006c3fb27SDimitry Andric     else
89106c3fb27SDimitry Andric       llvm_unreachable("unexpected symbol type");
89206c3fb27SDimitry Andric   }
89306c3fb27SDimitry Andric 
89406c3fb27SDimitry Andric   auto InsertSymbolsToJSON = [](Object &SymSection, TBDKey SegmentKey,
89506c3fb27SDimitry Andric                                 SymbolFields::SymbolTypes &SymField) {
89606c3fb27SDimitry Andric     if (SymField.empty())
89706c3fb27SDimitry Andric       return;
89806c3fb27SDimitry Andric     Object Segment;
89906c3fb27SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::Globals, std::move(SymField.Globals));
90006c3fb27SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::ThreadLocal, std::move(SymField.TLV));
90106c3fb27SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::Weak, std::move(SymField.Weaks));
90206c3fb27SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::ObjCClass,
90306c3fb27SDimitry Andric                          std::move(SymField.ObjCClasses));
90406c3fb27SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::ObjCEHType,
90506c3fb27SDimitry Andric                          std::move(SymField.EHTypes));
90606c3fb27SDimitry Andric     insertNonEmptyValues(Segment, TBDKey::ObjCIvar, std::move(SymField.IVars));
90706c3fb27SDimitry Andric     insertNonEmptyValues(SymSection, SegmentKey, std::move(Segment));
90806c3fb27SDimitry Andric   };
90906c3fb27SDimitry Andric 
91006c3fb27SDimitry Andric   Array SymbolSection;
91106c3fb27SDimitry Andric   for (auto &[Targets, Fields] : Entries) {
91206c3fb27SDimitry Andric     Object AllSyms;
91306c3fb27SDimitry Andric     insertNonEmptyValues(AllSyms, TBDKey::Targets, std::move(Targets));
91406c3fb27SDimitry Andric     InsertSymbolsToJSON(AllSyms, TBDKey::Data, Fields.Data);
91506c3fb27SDimitry Andric     InsertSymbolsToJSON(AllSyms, TBDKey::Text, Fields.Text);
91606c3fb27SDimitry Andric     SymbolSection.emplace_back(std::move(AllSyms));
91706c3fb27SDimitry Andric   }
91806c3fb27SDimitry Andric 
91906c3fb27SDimitry Andric   return SymbolSection;
92006c3fb27SDimitry Andric }
92106c3fb27SDimitry Andric 
serializeFlags(const InterfaceFile * File)92206c3fb27SDimitry Andric Array serializeFlags(const InterfaceFile *File) {
92306c3fb27SDimitry Andric   // TODO: Give all Targets the same flags for now.
92406c3fb27SDimitry Andric   Array Flags;
92506c3fb27SDimitry Andric   if (!File->isTwoLevelNamespace())
92606c3fb27SDimitry Andric     Flags.emplace_back("flat_namespace");
92706c3fb27SDimitry Andric   if (!File->isApplicationExtensionSafe())
92806c3fb27SDimitry Andric     Flags.emplace_back("not_app_extension_safe");
9295f757f3fSDimitry Andric   if (File->hasSimulatorSupport())
9305f757f3fSDimitry Andric     Flags.emplace_back("sim_support");
9315f757f3fSDimitry Andric   if (File->isOSLibNotForSharedCache())
9325f757f3fSDimitry Andric     Flags.emplace_back("not_for_dyld_shared_cache");
93306c3fb27SDimitry Andric   return serializeScalar(TBDKey::Attributes, std::move(Flags));
93406c3fb27SDimitry Andric }
93506c3fb27SDimitry Andric 
serializeIF(const InterfaceFile * File)93606c3fb27SDimitry Andric Expected<Object> serializeIF(const InterfaceFile *File) {
93706c3fb27SDimitry Andric   Object Library;
93806c3fb27SDimitry Andric 
93906c3fb27SDimitry Andric   // Handle required keys.
94006c3fb27SDimitry Andric   TargetList ActiveTargets{File->targets().begin(), File->targets().end()};
94106c3fb27SDimitry Andric   if (!insertNonEmptyValues(Library, TBDKey::TargetInfo,
94206c3fb27SDimitry Andric                             serializeTargetInfo(ActiveTargets)))
94306c3fb27SDimitry Andric     return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::TargetInfo));
94406c3fb27SDimitry Andric 
94506c3fb27SDimitry Andric   Array Name = serializeScalar<StringRef>(TBDKey::Name, File->getInstallName());
94606c3fb27SDimitry Andric   if (!insertNonEmptyValues(Library, TBDKey::InstallName, std::move(Name)))
94706c3fb27SDimitry Andric     return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::InstallName));
94806c3fb27SDimitry Andric 
94906c3fb27SDimitry Andric   // Handle optional keys.
95006c3fb27SDimitry Andric   Array Flags = serializeFlags(File);
95106c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::Flags, std::move(Flags));
95206c3fb27SDimitry Andric 
95306c3fb27SDimitry Andric   Array CurrentV = serializeScalar<PackedVersion, std::string>(
95406c3fb27SDimitry Andric       TBDKey::Version, File->getCurrentVersion(), PackedVersion(1, 0, 0));
95506c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::CurrentVersion, std::move(CurrentV));
95606c3fb27SDimitry Andric 
95706c3fb27SDimitry Andric   Array CompatV = serializeScalar<PackedVersion, std::string>(
95806c3fb27SDimitry Andric       TBDKey::Version, File->getCompatibilityVersion(), PackedVersion(1, 0, 0));
95906c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::CompatibilityVersion,
96006c3fb27SDimitry Andric                        std::move(CompatV));
96106c3fb27SDimitry Andric 
96206c3fb27SDimitry Andric   Array SwiftABI = serializeScalar<uint8_t, int64_t>(
96306c3fb27SDimitry Andric       TBDKey::ABI, File->getSwiftABIVersion(), 0u);
96406c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::SwiftABI, std::move(SwiftABI));
96506c3fb27SDimitry Andric 
96606c3fb27SDimitry Andric   Array RPaths = serializeField(TBDKey::Paths, File->rpaths(), ActiveTargets);
96706c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::RPath, std::move(RPaths));
96806c3fb27SDimitry Andric 
96906c3fb27SDimitry Andric   Array Umbrellas = serializeField(TBDKey::Umbrella, File->umbrellas(),
97006c3fb27SDimitry Andric                                    ActiveTargets, /*IsArray=*/false);
97106c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::ParentUmbrella, std::move(Umbrellas));
97206c3fb27SDimitry Andric 
97306c3fb27SDimitry Andric   Array Clients =
97406c3fb27SDimitry Andric       serializeField(TBDKey::Clients, File->allowableClients(), ActiveTargets);
97506c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::AllowableClients, std::move(Clients));
97606c3fb27SDimitry Andric 
97706c3fb27SDimitry Andric   Array ReexportLibs =
97806c3fb27SDimitry Andric       serializeField(TBDKey::Names, File->reexportedLibraries(), ActiveTargets);
97906c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::ReexportLibs, std::move(ReexportLibs));
98006c3fb27SDimitry Andric 
98106c3fb27SDimitry Andric   // Handle symbols.
98206c3fb27SDimitry Andric   Array Exports = serializeSymbols(File->exports(), ActiveTargets);
98306c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::Exports, std::move(Exports));
98406c3fb27SDimitry Andric 
98506c3fb27SDimitry Andric   Array Reexports = serializeSymbols(File->reexports(), ActiveTargets);
98606c3fb27SDimitry Andric   insertNonEmptyValues(Library, TBDKey::Reexports, std::move(Reexports));
98706c3fb27SDimitry Andric 
98806c3fb27SDimitry Andric   if (!File->isTwoLevelNamespace()) {
98906c3fb27SDimitry Andric     Array Undefineds = serializeSymbols(File->undefineds(), ActiveTargets);
99006c3fb27SDimitry Andric     insertNonEmptyValues(Library, TBDKey::Undefineds, std::move(Undefineds));
99106c3fb27SDimitry Andric   }
99206c3fb27SDimitry Andric 
99306c3fb27SDimitry Andric   return std::move(Library);
99406c3fb27SDimitry Andric }
99506c3fb27SDimitry Andric 
getJSON(const InterfaceFile * File,const FileType FileKind)9965f757f3fSDimitry Andric Expected<Object> getJSON(const InterfaceFile *File, const FileType FileKind) {
9975f757f3fSDimitry Andric   assert(FileKind == FileType::TBD_V5 && "unexpected json file format version");
99806c3fb27SDimitry Andric   Object Root;
99906c3fb27SDimitry Andric 
100006c3fb27SDimitry Andric   auto MainLibOrErr = serializeIF(File);
100106c3fb27SDimitry Andric   if (!MainLibOrErr)
100206c3fb27SDimitry Andric     return MainLibOrErr;
100306c3fb27SDimitry Andric   Root[Keys[TBDKey::MainLibrary]] = std::move(*MainLibOrErr);
100406c3fb27SDimitry Andric   Array Documents;
100506c3fb27SDimitry Andric   for (const auto &Doc : File->documents()) {
100606c3fb27SDimitry Andric     auto LibOrErr = serializeIF(Doc.get());
100706c3fb27SDimitry Andric     if (!LibOrErr)
100806c3fb27SDimitry Andric       return LibOrErr;
100906c3fb27SDimitry Andric     Documents.emplace_back(std::move(*LibOrErr));
101006c3fb27SDimitry Andric   }
101106c3fb27SDimitry Andric 
101206c3fb27SDimitry Andric   Root[Keys[TBDKey::TBDVersion]] = 5;
101306c3fb27SDimitry Andric   insertNonEmptyValues(Root, TBDKey::Documents, std::move(Documents));
101406c3fb27SDimitry Andric   return std::move(Root);
101506c3fb27SDimitry Andric }
101606c3fb27SDimitry Andric 
101706c3fb27SDimitry Andric } // namespace
101806c3fb27SDimitry Andric 
serializeInterfaceFileToJSON(raw_ostream & OS,const InterfaceFile & File,const FileType FileKind,bool Compact)101906c3fb27SDimitry Andric Error MachO::serializeInterfaceFileToJSON(raw_ostream &OS,
102006c3fb27SDimitry Andric                                           const InterfaceFile &File,
10215f757f3fSDimitry Andric                                           const FileType FileKind,
102206c3fb27SDimitry Andric                                           bool Compact) {
10235f757f3fSDimitry Andric   auto TextFile = getJSON(&File, FileKind);
102406c3fb27SDimitry Andric   if (!TextFile)
102506c3fb27SDimitry Andric     return TextFile.takeError();
102606c3fb27SDimitry Andric   if (Compact)
102706c3fb27SDimitry Andric     OS << formatv("{0}", Value(std::move(*TextFile))) << "\n";
102806c3fb27SDimitry Andric   else
102906c3fb27SDimitry Andric     OS << formatv("{0:2}", Value(std::move(*TextFile))) << "\n";
103006c3fb27SDimitry Andric   return Error::success();
103106c3fb27SDimitry Andric }
1032