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