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