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