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