aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/TextAPI
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/TextAPI')
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp280
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/PackedVersion.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/Platform.cpp41
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/RecordsSlice.cpp224
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/Symbol.cpp26
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/SymbolSet.cpp5
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/Target.cpp16
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/TextAPIError.cpp39
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/TextStub.cpp136
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/TextStubCommon.h6
-rw-r--r--contrib/llvm-project/llvm/lib/TextAPI/TextStubV5.cpp43
11 files changed, 675 insertions, 145 deletions
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp b/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp
index b7f967aa754e..3689ab919191 100644
--- a/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp
+++ b/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/TextAPI/InterfaceFile.h"
+#include "llvm/TextAPI/TextAPIError.h"
#include <iomanip>
#include <sstream>
@@ -47,16 +48,16 @@ void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
}
void InterfaceFile::addRPath(const Target &InputTarget, StringRef RPath) {
- auto Iter = lower_bound(RPaths, InputTarget,
- [](const std::pair<Target, std::string> &LHS,
- Target RHS) { return LHS.first < RHS; });
+ using RPathEntryT = const std::pair<Target, std::string>;
+ RPathEntryT Entry(InputTarget, RPath);
+ auto Iter =
+ lower_bound(RPaths, Entry,
+ [](RPathEntryT &LHS, RPathEntryT &RHS) { return LHS < RHS; });
- if ((Iter != RPaths.end()) && !(InputTarget < Iter->first)) {
- Iter->second = std::string(RPath);
+ if ((Iter != RPaths.end()) && (*Iter == Entry))
return;
- }
- RPaths.emplace(Iter, InputTarget, std::string(RPath));
+ RPaths.emplace(Iter, Entry);
}
void InterfaceFile::addTarget(const Target &Target) {
@@ -81,6 +82,267 @@ void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
Documents.insert(Pos, Document);
}
+void InterfaceFile::inlineLibrary(std::shared_ptr<InterfaceFile> Library,
+ bool Overwrite) {
+ auto AddFwk = [&](std::shared_ptr<InterfaceFile> &&Reexport) {
+ auto It = lower_bound(
+ Documents, Reexport->getInstallName(),
+ [](std::shared_ptr<InterfaceFile> &Lhs, const StringRef Rhs) {
+ return Lhs->getInstallName() < Rhs;
+ });
+
+ if (Overwrite && It != Documents.end() &&
+ Reexport->getInstallName() == (*It)->getInstallName()) {
+ std::replace(Documents.begin(), Documents.end(), *It,
+ std::move(Reexport));
+ return;
+ }
+
+ if ((It != Documents.end()) &&
+ !(Reexport->getInstallName() < (*It)->getInstallName()))
+ return;
+
+ Documents.emplace(It, std::move(Reexport));
+ };
+ for (auto Doc : Library->documents())
+ AddFwk(std::move(Doc));
+
+ Library->Documents.clear();
+ AddFwk(std::move(Library));
+}
+
+Expected<std::unique_ptr<InterfaceFile>>
+InterfaceFile::merge(const InterfaceFile *O) const {
+ // Verify files can be merged.
+ if (getInstallName() != O->getInstallName()) {
+ return make_error<StringError>("install names do not match",
+ inconvertibleErrorCode());
+ }
+
+ if (getCurrentVersion() != O->getCurrentVersion()) {
+ return make_error<StringError>("current versions do not match",
+ inconvertibleErrorCode());
+ }
+
+ if (getCompatibilityVersion() != O->getCompatibilityVersion()) {
+ return make_error<StringError>("compatibility versions do not match",
+ inconvertibleErrorCode());
+ }
+
+ if ((getSwiftABIVersion() != 0) && (O->getSwiftABIVersion() != 0) &&
+ (getSwiftABIVersion() != O->getSwiftABIVersion())) {
+ return make_error<StringError>("swift ABI versions do not match",
+ inconvertibleErrorCode());
+ }
+
+ if (isTwoLevelNamespace() != O->isTwoLevelNamespace()) {
+ return make_error<StringError>("two level namespace flags do not match",
+ inconvertibleErrorCode());
+ }
+
+ if (isApplicationExtensionSafe() != O->isApplicationExtensionSafe()) {
+ return make_error<StringError>(
+ "application extension safe flags do not match",
+ inconvertibleErrorCode());
+ }
+
+ std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
+ IF->setFileType(std::max(getFileType(), O->getFileType()));
+ IF->setPath(getPath());
+ IF->setInstallName(getInstallName());
+ IF->setCurrentVersion(getCurrentVersion());
+ IF->setCompatibilityVersion(getCompatibilityVersion());
+
+ if (getSwiftABIVersion() == 0)
+ IF->setSwiftABIVersion(O->getSwiftABIVersion());
+ else
+ IF->setSwiftABIVersion(getSwiftABIVersion());
+
+ IF->setTwoLevelNamespace(isTwoLevelNamespace());
+ IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
+
+ for (const auto &It : umbrellas()) {
+ if (!It.second.empty())
+ IF->addParentUmbrella(It.first, It.second);
+ }
+ for (const auto &It : O->umbrellas()) {
+ if (!It.second.empty())
+ IF->addParentUmbrella(It.first, It.second);
+ }
+ IF->addTargets(targets());
+ IF->addTargets(O->targets());
+
+ for (const auto &Lib : allowableClients())
+ for (const auto &Target : Lib.targets())
+ IF->addAllowableClient(Lib.getInstallName(), Target);
+
+ for (const auto &Lib : O->allowableClients())
+ for (const auto &Target : Lib.targets())
+ IF->addAllowableClient(Lib.getInstallName(), Target);
+
+ for (const auto &Lib : reexportedLibraries())
+ for (const auto &Target : Lib.targets())
+ IF->addReexportedLibrary(Lib.getInstallName(), Target);
+
+ for (const auto &Lib : O->reexportedLibraries())
+ for (const auto &Target : Lib.targets())
+ IF->addReexportedLibrary(Lib.getInstallName(), Target);
+
+ for (const auto &[Target, Path] : rpaths())
+ IF->addRPath(Target, Path);
+ for (const auto &[Target, Path] : O->rpaths())
+ IF->addRPath(Target, Path);
+
+ for (const auto *Sym : symbols()) {
+ IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
+ Sym->getFlags());
+ }
+
+ for (const auto *Sym : O->symbols()) {
+ IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
+ Sym->getFlags());
+ }
+
+ return std::move(IF);
+}
+
+Expected<std::unique_ptr<InterfaceFile>>
+InterfaceFile::remove(Architecture Arch) const {
+ if (getArchitectures() == Arch)
+ return make_error<StringError>("cannot remove last architecture slice '" +
+ getArchitectureName(Arch) + "'",
+ inconvertibleErrorCode());
+
+ if (!getArchitectures().has(Arch)) {
+ bool Found = false;
+ for (auto &Doc : Documents) {
+ if (Doc->getArchitectures().has(Arch)) {
+ Found = true;
+ break;
+ }
+ }
+
+ if (!Found)
+ return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture);
+ }
+
+ std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
+ IF->setFileType(getFileType());
+ IF->setPath(getPath());
+ IF->addTargets(targets(ArchitectureSet::All().clear(Arch)));
+ IF->setInstallName(getInstallName());
+ IF->setCurrentVersion(getCurrentVersion());
+ IF->setCompatibilityVersion(getCompatibilityVersion());
+ IF->setSwiftABIVersion(getSwiftABIVersion());
+ IF->setTwoLevelNamespace(isTwoLevelNamespace());
+ IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
+ for (const auto &It : umbrellas())
+ if (It.first.Arch != Arch)
+ IF->addParentUmbrella(It.first, It.second);
+
+ for (const auto &Lib : allowableClients()) {
+ for (const auto &Target : Lib.targets())
+ if (Target.Arch != Arch)
+ IF->addAllowableClient(Lib.getInstallName(), Target);
+ }
+
+ for (const auto &Lib : reexportedLibraries()) {
+ for (const auto &Target : Lib.targets())
+ if (Target.Arch != Arch)
+ IF->addReexportedLibrary(Lib.getInstallName(), Target);
+ }
+
+ for (const auto *Sym : symbols()) {
+ auto Archs = Sym->getArchitectures();
+ Archs.clear(Arch);
+ if (Archs.empty())
+ continue;
+
+ IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Archs),
+ Sym->getFlags());
+ }
+
+ for (auto &Doc : Documents) {
+ // Skip the inlined document if the to be removed architecture is the
+ // only one left.
+ if (Doc->getArchitectures() == Arch)
+ continue;
+
+ // If the document doesn't contain the arch, then no work is to be done
+ // and it can be copied over.
+ if (!Doc->getArchitectures().has(Arch)) {
+ auto NewDoc = Doc;
+ IF->addDocument(std::move(NewDoc));
+ continue;
+ }
+
+ auto Result = Doc->remove(Arch);
+ if (!Result)
+ return Result;
+
+ IF->addDocument(std::move(Result.get()));
+ }
+
+ return std::move(IF);
+}
+
+Expected<std::unique_ptr<InterfaceFile>>
+InterfaceFile::extract(Architecture Arch) const {
+ if (!getArchitectures().has(Arch)) {
+ return make_error<StringError>("file doesn't have architecture '" +
+ getArchitectureName(Arch) + "'",
+ inconvertibleErrorCode());
+ }
+
+ std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
+ IF->setFileType(getFileType());
+ IF->setPath(getPath());
+ IF->addTargets(targets(Arch));
+ IF->setInstallName(getInstallName());
+ IF->setCurrentVersion(getCurrentVersion());
+ IF->setCompatibilityVersion(getCompatibilityVersion());
+ IF->setSwiftABIVersion(getSwiftABIVersion());
+ IF->setTwoLevelNamespace(isTwoLevelNamespace());
+ IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
+ for (const auto &It : umbrellas())
+ if (It.first.Arch == Arch)
+ IF->addParentUmbrella(It.first, It.second);
+
+ for (const auto &It : rpaths())
+ if (It.first.Arch == Arch)
+ IF->addRPath(It.first, It.second);
+
+ for (const auto &Lib : allowableClients())
+ for (const auto &Target : Lib.targets())
+ if (Target.Arch == Arch)
+ IF->addAllowableClient(Lib.getInstallName(), Target);
+
+ for (const auto &Lib : reexportedLibraries())
+ for (const auto &Target : Lib.targets())
+ if (Target.Arch == Arch)
+ IF->addReexportedLibrary(Lib.getInstallName(), Target);
+
+ for (const auto *Sym : symbols()) {
+ if (Sym->hasArchitecture(Arch))
+ IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Arch),
+ Sym->getFlags());
+ }
+
+ for (auto &Doc : Documents) {
+ // Skip documents that don't have the requested architecture.
+ if (!Doc->getArchitectures().has(Arch))
+ continue;
+
+ auto Result = Doc->extract(Arch);
+ if (!Result)
+ return Result;
+
+ IF->addDocument(std::move(Result.get()));
+ }
+
+ return std::move(IF);
+}
+
static bool isYAMLTextStub(const FileType &Kind) {
return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);
}
@@ -99,6 +361,10 @@ bool InterfaceFile::operator==(const InterfaceFile &O) const {
return false;
if (IsAppExtensionSafe != O.IsAppExtensionSafe)
return false;
+ if (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache)
+ return false;
+ if (HasSimSupport != O.HasSimSupport)
+ return false;
if (ParentUmbrellas != O.ParentUmbrellas)
return false;
if (AllowableClients != O.AllowableClients)
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/PackedVersion.cpp b/contrib/llvm-project/llvm/lib/TextAPI/PackedVersion.cpp
index 22960c33e9ee..4742be79f457 100644
--- a/contrib/llvm-project/llvm/lib/TextAPI/PackedVersion.cpp
+++ b/contrib/llvm-project/llvm/lib/TextAPI/PackedVersion.cpp
@@ -28,7 +28,7 @@ bool PackedVersion::parse32(StringRef Str) {
SmallVector<StringRef, 3> Parts;
SplitString(Str, Parts, ".");
- if (Parts.size() > 3)
+ if (Parts.size() > 3 || Parts.empty())
return false;
unsigned long long Num;
@@ -63,7 +63,7 @@ std::pair<bool, bool> PackedVersion::parse64(StringRef Str) {
SmallVector<StringRef, 5> Parts;
SplitString(Str, Parts, ".");
- if (Parts.size() > 5)
+ if (Parts.size() > 5 || Parts.empty())
return std::make_pair(false, Truncated);
unsigned long long Num;
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/Platform.cpp b/contrib/llvm-project/llvm/lib/TextAPI/Platform.cpp
index d0575847a876..ed041af40aa5 100644
--- a/contrib/llvm-project/llvm/lib/TextAPI/Platform.cpp
+++ b/contrib/llvm-project/llvm/lib/TextAPI/Platform.cpp
@@ -62,28 +62,11 @@ PlatformSet mapToPlatformSet(ArrayRef<Triple> Targets) {
StringRef getPlatformName(PlatformType Platform) {
switch (Platform) {
- case PLATFORM_UNKNOWN:
- return "unknown";
- case PLATFORM_MACOS:
- return "macOS";
- case PLATFORM_IOS:
- return "iOS";
- case PLATFORM_TVOS:
- return "tvOS";
- case PLATFORM_WATCHOS:
- return "watchOS";
- case PLATFORM_BRIDGEOS:
- return "bridgeOS";
- case PLATFORM_MACCATALYST:
- return "macCatalyst";
- case PLATFORM_IOSSIMULATOR:
- return "iOS Simulator";
- case PLATFORM_TVOSSIMULATOR:
- return "tvOS Simulator";
- case PLATFORM_WATCHOSSIMULATOR:
- return "watchOS Simulator";
- case PLATFORM_DRIVERKIT:
- return "DriverKit";
+#define PLATFORM(platform, id, name, build_name, target, tapi_target, \
+ marketing) \
+ case PLATFORM_##platform: \
+ return #marketing;
+#include "llvm/BinaryFormat/MachO.def"
}
llvm_unreachable("Unknown llvm::MachO::PlatformType enum");
}
@@ -91,16 +74,10 @@ StringRef getPlatformName(PlatformType Platform) {
PlatformType getPlatformFromName(StringRef Name) {
return StringSwitch<PlatformType>(Name)
.Case("osx", PLATFORM_MACOS)
- .Case("macos", PLATFORM_MACOS)
- .Case("ios", PLATFORM_IOS)
- .Case("tvos", PLATFORM_TVOS)
- .Case("watchos", PLATFORM_WATCHOS)
- .Case("bridgeos", PLATFORM_BRIDGEOS)
- .Case("ios-macabi", PLATFORM_MACCATALYST)
- .Case("ios-simulator", PLATFORM_IOSSIMULATOR)
- .Case("tvos-simulator", PLATFORM_TVOSSIMULATOR)
- .Case("watchos-simulator", PLATFORM_WATCHOSSIMULATOR)
- .Case("driverkit", PLATFORM_DRIVERKIT)
+#define PLATFORM(platform, id, name, build_name, target, tapi_target, \
+ marketing) \
+ .Case(#target, PLATFORM_##platform)
+#include "llvm/BinaryFormat/MachO.def"
.Default(PLATFORM_UNKNOWN);
}
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/RecordsSlice.cpp b/contrib/llvm-project/llvm/lib/TextAPI/RecordsSlice.cpp
new file mode 100644
index 000000000000..a220b255aea3
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/TextAPI/RecordsSlice.cpp
@@ -0,0 +1,224 @@
+//===- RecordsSlice.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements the Records Slice APIs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TextAPI/RecordsSlice.h"
+#include "llvm/TextAPI/Record.h"
+#include "llvm/TextAPI/Symbol.h"
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::MachO;
+
+Record *RecordsSlice::addRecord(StringRef Name, SymbolFlags Flags,
+ GlobalRecord::Kind GV, RecordLinkage Linkage) {
+ // Find a specific Record type to capture.
+ auto [APIName, SymKind] = parseSymbol(Name, Flags);
+ Name = APIName;
+ switch (SymKind) {
+ case SymbolKind::GlobalSymbol:
+ return addGlobal(Name, Linkage, GV, Flags);
+ case SymbolKind::ObjectiveCClass:
+ return addObjCInterface(Name, Linkage);
+ case SymbolKind::ObjectiveCClassEHType:
+ return addObjCInterface(Name, Linkage, /*HasEHType=*/true);
+ case SymbolKind::ObjectiveCInstanceVariable: {
+ auto [Super, IVar] = Name.split('.');
+ // Attempt to find super class.
+ ObjCContainerRecord *Container = findContainer(/*isIVar=*/false, Super);
+ // If not found, create extension since there is no mapped class symbol.
+ if (Container == nullptr)
+ Container = addObjCCategory(Super, {});
+ return addObjCIVar(Container, IVar, Linkage);
+ }
+ }
+
+ llvm_unreachable("unexpected symbol kind when adding to Record Slice");
+}
+
+ObjCContainerRecord *RecordsSlice::findContainer(bool IsIVar,
+ StringRef Name) const {
+ StringRef Super = IsIVar ? Name.split('.').first : Name;
+ ObjCContainerRecord *Container = findObjCInterface(Super);
+ // Ivars can only exist with extensions, if they did not come from
+ // class.
+ if (Container == nullptr)
+ Container = findObjCCategory(Super, "");
+ return Container;
+}
+
+template <typename R, typename C = RecordMap<R>, typename K = StringRef>
+R *findRecord(K Key, const C &Container) {
+ const auto *Record = Container.find(Key);
+ if (Record == Container.end())
+ return nullptr;
+ return Record->second.get();
+}
+
+GlobalRecord *RecordsSlice::findGlobal(StringRef Name,
+ GlobalRecord::Kind GV) const {
+ auto *Record = findRecord<GlobalRecord>(Name, Globals);
+ if (!Record)
+ return nullptr;
+
+ switch (GV) {
+ case GlobalRecord::Kind::Variable: {
+ if (!Record->isVariable())
+ return nullptr;
+ break;
+ }
+ case GlobalRecord::Kind::Function: {
+ if (!Record->isFunction())
+ return nullptr;
+ break;
+ }
+ case GlobalRecord::Kind::Unknown:
+ return Record;
+ }
+
+ return Record;
+}
+
+ObjCInterfaceRecord *RecordsSlice::findObjCInterface(StringRef Name) const {
+ return findRecord<ObjCInterfaceRecord>(Name, Classes);
+}
+
+ObjCCategoryRecord *RecordsSlice::findObjCCategory(StringRef ClassToExtend,
+ StringRef Category) const {
+ return findRecord<ObjCCategoryRecord>(std::make_pair(ClassToExtend, Category),
+ Categories);
+}
+
+ObjCIVarRecord *ObjCContainerRecord::findObjCIVar(StringRef IVar) const {
+ return findRecord<ObjCIVarRecord>(IVar, IVars);
+}
+
+ObjCIVarRecord *RecordsSlice::findObjCIVar(bool IsScopedName,
+ StringRef Name) const {
+ // If scoped name, the name of the container is known.
+ if (IsScopedName) {
+ // IVar does not exist if there is not a container assigned to it.
+ auto *Container = findContainer(/*IsIVar=*/true, Name);
+ if (!Container)
+ return nullptr;
+
+ StringRef IVar = Name.substr(Name.find_first_of('.') + 1);
+ return Container->findObjCIVar(IVar);
+ }
+
+ // Otherwise traverse through containers and attempt to find IVar.
+ auto getIVar = [Name](auto &Records) -> ObjCIVarRecord * {
+ for (const auto &[_, Container] : Records) {
+ if (auto *IVarR = Container->findObjCIVar(Name))
+ return IVarR;
+ }
+ return nullptr;
+ };
+
+ if (auto *IVarRecord = getIVar(Classes))
+ return IVarRecord;
+
+ return getIVar(Categories);
+}
+
+GlobalRecord *RecordsSlice::addGlobal(StringRef Name, RecordLinkage Linkage,
+ GlobalRecord::Kind GV,
+ SymbolFlags Flags) {
+ if (GV == GlobalRecord::Kind::Function)
+ Flags |= SymbolFlags::Text;
+ else if (GV == GlobalRecord::Kind::Variable)
+ Flags |= SymbolFlags::Data;
+
+ Name = copyString(Name);
+ auto Result = Globals.insert({Name, nullptr});
+ if (Result.second)
+ Result.first->second =
+ std::make_unique<GlobalRecord>(Name, Linkage, Flags, GV);
+ else
+ updateLinkage(Result.first->second.get(), Linkage);
+ return Result.first->second.get();
+}
+
+ObjCInterfaceRecord *RecordsSlice::addObjCInterface(StringRef Name,
+ RecordLinkage Linkage,
+ bool HasEHType) {
+ Name = copyString(Name);
+ auto Result = Classes.insert({Name, nullptr});
+ if (Result.second) {
+ Result.first->second =
+ std::make_unique<ObjCInterfaceRecord>(Name, Linkage, HasEHType);
+ } else {
+ // ObjC classes represent multiple symbols that could have competing
+ // linkages, in those cases assign the largest one.
+ if (Linkage >= RecordLinkage::Rexported)
+ updateLinkage(Result.first->second.get(), Linkage);
+ }
+
+ return Result.first->second.get();
+}
+
+bool ObjCInterfaceRecord::addObjCCategory(ObjCCategoryRecord *Record) {
+ auto Result = Categories.insert({Name, Record});
+ return Result.second;
+}
+
+ObjCCategoryRecord *RecordsSlice::addObjCCategory(StringRef ClassToExtend,
+ StringRef Category) {
+ Category = copyString(Category);
+
+ // Add owning record first into record slice.
+ auto Result =
+ Categories.insert({std::make_pair(ClassToExtend, Category), nullptr});
+ if (Result.second)
+ Result.first->second =
+ std::make_unique<ObjCCategoryRecord>(ClassToExtend, Category);
+
+ // Then add reference to it in in the class.
+ if (auto *ObjCClass = findObjCInterface(ClassToExtend))
+ ObjCClass->addObjCCategory(Result.first->second.get());
+
+ return Result.first->second.get();
+}
+
+ObjCIVarRecord *ObjCContainerRecord::addObjCIVar(StringRef IVar,
+ RecordLinkage Linkage) {
+ auto Result = IVars.insert({IVar, nullptr});
+ if (Result.second)
+ Result.first->second = std::make_unique<ObjCIVarRecord>(Name, Linkage);
+ return Result.first->second.get();
+}
+
+ObjCIVarRecord *RecordsSlice::addObjCIVar(ObjCContainerRecord *Container,
+ StringRef Name,
+ RecordLinkage Linkage) {
+ Name = copyString(Name);
+ ObjCIVarRecord *Record = Container->addObjCIVar(Name, Linkage);
+ updateLinkage(Record, Linkage);
+ return Record;
+}
+
+StringRef RecordsSlice::copyString(StringRef String) {
+ if (String.empty())
+ return {};
+
+ if (StringAllocator.identifyObject(String.data()))
+ return String;
+
+ void *Ptr = StringAllocator.Allocate(String.size(), 1);
+ memcpy(Ptr, String.data(), String.size());
+ return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
+}
+
+RecordsSlice::BinaryAttrs &RecordsSlice::getBinaryAttrs() {
+ if (!hasBinaryAttrs())
+ BA = std::make_unique<BinaryAttrs>();
+ return *BA;
+}
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/Symbol.cpp b/contrib/llvm-project/llvm/lib/TextAPI/Symbol.cpp
index 20fa6362716a..fd395436051d 100644
--- a/contrib/llvm-project/llvm/lib/TextAPI/Symbol.cpp
+++ b/contrib/llvm-project/llvm/lib/TextAPI/Symbol.cpp
@@ -72,5 +72,31 @@ bool Symbol::operator==(const Symbol &O) const {
std::tie(O.Name, O.Kind, O.Targets, RHSFlags);
}
+SimpleSymbol parseSymbol(StringRef SymName, const SymbolFlags Flags) {
+ if (SymName.starts_with(ObjC1ClassNamePrefix))
+ return {SymName.drop_front(ObjC1ClassNamePrefix.size()),
+ SymbolKind::ObjectiveCClass};
+ if (SymName.starts_with(ObjC2ClassNamePrefix))
+ return {SymName.drop_front(ObjC2ClassNamePrefix.size()),
+ SymbolKind::ObjectiveCClass};
+ if (SymName.starts_with(ObjC2MetaClassNamePrefix))
+ return {SymName.drop_front(ObjC2MetaClassNamePrefix.size()),
+ SymbolKind::ObjectiveCClass};
+ if (SymName.starts_with(ObjC2EHTypePrefix)) {
+ // When classes without ehtype are used in try/catch blocks
+ // a weak-defined symbol is exported. In those cases, treat these as a
+ // global instead.
+ if ((Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined)
+ return {SymName, SymbolKind::GlobalSymbol};
+ return {SymName.drop_front(ObjC2EHTypePrefix.size()),
+ SymbolKind::ObjectiveCClassEHType};
+ }
+
+ if (SymName.starts_with(ObjC2IVarPrefix))
+ return {SymName.drop_front(ObjC2IVarPrefix.size()),
+ SymbolKind::ObjectiveCInstanceVariable};
+ return {SymName, SymbolKind::GlobalSymbol};
+}
+
} // end namespace MachO.
} // end namespace llvm.
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/SymbolSet.cpp b/contrib/llvm-project/llvm/lib/TextAPI/SymbolSet.cpp
index 157e13749729..5b9882dadcdf 100644
--- a/contrib/llvm-project/llvm/lib/TextAPI/SymbolSet.cpp
+++ b/contrib/llvm-project/llvm/lib/TextAPI/SymbolSet.cpp
@@ -29,8 +29,5 @@ Symbol *SymbolSet::addGlobal(SymbolKind Kind, StringRef Name, SymbolFlags Flags,
}
const Symbol *SymbolSet::findSymbol(SymbolKind Kind, StringRef Name) const {
- auto It = Symbols.find({Kind, Name});
- if (It != Symbols.end())
- return It->second;
- return nullptr;
+ return Symbols.lookup({Kind, Name});
}
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/Target.cpp b/contrib/llvm-project/llvm/lib/TextAPI/Target.cpp
index e20842498331..a50abeeca194 100644
--- a/contrib/llvm-project/llvm/lib/TextAPI/Target.cpp
+++ b/contrib/llvm-project/llvm/lib/TextAPI/Target.cpp
@@ -21,20 +21,14 @@ Expected<Target> Target::create(StringRef TargetValue) {
auto PlatformStr = Result.second;
PlatformType Platform;
Platform = StringSwitch<PlatformType>(PlatformStr)
- .Case("macos", PLATFORM_MACOS)
- .Case("ios", PLATFORM_IOS)
- .Case("tvos", PLATFORM_TVOS)
- .Case("watchos", PLATFORM_WATCHOS)
- .Case("bridgeos", PLATFORM_BRIDGEOS)
- .Case("maccatalyst", PLATFORM_MACCATALYST)
- .Case("ios-simulator", PLATFORM_IOSSIMULATOR)
- .Case("tvos-simulator", PLATFORM_TVOSSIMULATOR)
- .Case("watchos-simulator", PLATFORM_WATCHOSSIMULATOR)
- .Case("driverkit", PLATFORM_DRIVERKIT)
+#define PLATFORM(platform, id, name, build_name, target, tapi_target, \
+ marketing) \
+ .Case(#tapi_target, PLATFORM_##platform)
+#include "llvm/BinaryFormat/MachO.def"
.Default(PLATFORM_UNKNOWN);
if (Platform == PLATFORM_UNKNOWN) {
- if (PlatformStr.startswith("<") && PlatformStr.endswith(">")) {
+ if (PlatformStr.starts_with("<") && PlatformStr.ends_with(">")) {
PlatformStr = PlatformStr.drop_front().drop_back();
unsigned long long RawValue;
if (!PlatformStr.getAsInteger(10, RawValue))
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/TextAPIError.cpp b/contrib/llvm-project/llvm/lib/TextAPI/TextAPIError.cpp
new file mode 100644
index 000000000000..23954a9e3466
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/TextAPI/TextAPIError.cpp
@@ -0,0 +1,39 @@
+//===- TextAPIError.cpp - Tapi Error ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Implements TAPI Error.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TextAPI/TextAPIError.h"
+
+using namespace llvm;
+using namespace llvm::MachO;
+
+char TextAPIError::ID = 0;
+
+void TextAPIError::log(raw_ostream &OS) const {
+ switch (EC) {
+ case TextAPIErrorCode::NoSuchArchitecture:
+ OS << "no such architecture";
+ break;
+ case TextAPIErrorCode::InvalidInputFormat:
+ OS << "invalid input format";
+ break;
+ default:
+ llvm_unreachable("unhandled TextAPIErrorCode");
+ }
+ if (!Msg.empty())
+ OS << ": " << Msg;
+ OS << "\n";
+}
+
+std::error_code TextAPIError::convertToErrorCode() const {
+ llvm_unreachable("convertToErrorCode is not supported.");
+}
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/TextStub.cpp b/contrib/llvm-project/llvm/lib/TextAPI/TextStub.cpp
index 78de3ebf3f3a..9fa1459e9557 100644
--- a/contrib/llvm-project/llvm/lib/TextAPI/TextStub.cpp
+++ b/contrib/llvm-project/llvm/lib/TextAPI/TextStub.cpp
@@ -360,6 +360,8 @@ template <> struct ScalarBitSetTraits<TBDFlags> {
IO.bitSetCase(Flags, "not_app_extension_safe",
TBDFlags::NotApplicationExtensionSafe);
IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
+ IO.bitSetCase(Flags, "not_for_dyld_shared_cache",
+ TBDFlags::OSLibNotForSharedCache);
}
};
@@ -367,39 +369,12 @@ template <> struct ScalarTraits<Target> {
static void output(const Target &Value, void *, raw_ostream &OS) {
OS << Value.Arch << "-";
switch (Value.Platform) {
- default:
- OS << "unknown";
- break;
- case PLATFORM_MACOS:
- OS << "macos";
- break;
- case PLATFORM_IOS:
- OS << "ios";
- break;
- case PLATFORM_TVOS:
- OS << "tvos";
- break;
- case PLATFORM_WATCHOS:
- OS << "watchos";
- break;
- case PLATFORM_BRIDGEOS:
- OS << "bridgeos";
- break;
- case PLATFORM_MACCATALYST:
- OS << "maccatalyst";
- break;
- case PLATFORM_IOSSIMULATOR:
- OS << "ios-simulator";
- break;
- case PLATFORM_TVOSSIMULATOR:
- OS << "tvos-simulator";
- break;
- case PLATFORM_WATCHOSSIMULATOR:
- OS << "watchos-simulator";
- break;
- case PLATFORM_DRIVERKIT:
- OS << "driverkit";
- break;
+#define PLATFORM(platform, id, name, build_name, target, tapi_target, \
+ marketing) \
+ case PLATFORM_##platform: \
+ OS << #tapi_target; \
+ break;
+#include "llvm/BinaryFormat/MachO.def"
}
}
@@ -620,6 +595,11 @@ template <> struct MappingTraits<const InterfaceFile *> {
!(Flags & TBDFlags::NotApplicationExtensionSafe));
}
+ // For older file formats, the segment where the symbol
+ // comes from is unknown, treat all symbols as Data
+ // in these cases.
+ const auto Flags = SymbolFlags::Data;
+
for (const auto &Section : Exports) {
const auto Targets =
synthesizeTargets(Section.Architectures, Platforms);
@@ -634,33 +614,34 @@ template <> struct MappingTraits<const InterfaceFile *> {
for (const auto &Symbol : Section.Symbols) {
if (Ctx->FileKind != FileType::TBD_V3 &&
- Symbol.value.startswith("_OBJC_EHTYPE_$_"))
+ Symbol.value.starts_with(ObjC2EHTypePrefix))
File->addSymbol(SymbolKind::ObjectiveCClassEHType,
- Symbol.value.drop_front(15), Targets);
+ Symbol.value.drop_front(15), Targets, Flags);
else
- File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets);
+ File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets, Flags);
}
for (auto &Symbol : Section.Classes) {
auto Name = Symbol.value;
if (Ctx->FileKind != FileType::TBD_V3)
Name = Name.drop_front();
- File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets);
+ File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets, Flags);
}
for (auto &Symbol : Section.ClassEHs)
- File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets);
+ File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets,
+ Flags);
for (auto &Symbol : Section.IVars) {
auto Name = Symbol.value;
if (Ctx->FileKind != FileType::TBD_V3)
Name = Name.drop_front();
- File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
- Targets);
+ File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets,
+ Flags);
}
for (auto &Symbol : Section.WeakDefSymbols)
File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
- SymbolFlags::WeakDefined);
+ SymbolFlags::WeakDefined | Flags);
for (auto &Symbol : Section.TLVSymbols)
File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
- SymbolFlags::ThreadLocalValue);
+ SymbolFlags::ThreadLocalValue | Flags);
}
for (const auto &Section : Undefineds) {
@@ -668,34 +649,35 @@ template <> struct MappingTraits<const InterfaceFile *> {
synthesizeTargets(Section.Architectures, Platforms);
for (auto &Symbol : Section.Symbols) {
if (Ctx->FileKind != FileType::TBD_V3 &&
- Symbol.value.startswith("_OBJC_EHTYPE_$_"))
+ Symbol.value.starts_with(ObjC2EHTypePrefix))
File->addSymbol(SymbolKind::ObjectiveCClassEHType,
Symbol.value.drop_front(15), Targets,
- SymbolFlags::Undefined);
+ SymbolFlags::Undefined | Flags);
else
File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
- SymbolFlags::Undefined);
+ SymbolFlags::Undefined | Flags);
}
for (auto &Symbol : Section.Classes) {
auto Name = Symbol.value;
if (Ctx->FileKind != FileType::TBD_V3)
Name = Name.drop_front();
File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets,
- SymbolFlags::Undefined);
+ SymbolFlags::Undefined | Flags);
}
for (auto &Symbol : Section.ClassEHs)
File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets,
- SymbolFlags::Undefined);
+ SymbolFlags::Undefined | Flags);
for (auto &Symbol : Section.IVars) {
auto Name = Symbol.value;
if (Ctx->FileKind != FileType::TBD_V3)
Name = Name.drop_front();
File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets,
- SymbolFlags::Undefined);
+ SymbolFlags::Undefined | Flags);
}
for (auto &Symbol : Section.WeakRefSymbols)
File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
- SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
+ SymbolFlags::Undefined | SymbolFlags::WeakReferenced |
+ Flags);
}
return File;
@@ -787,7 +769,7 @@ template <> struct MappingTraits<const InterfaceFile *> {
NormalizedTBD_V4(IO &IO, const InterfaceFile *&File) {
auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
assert(Ctx);
- TBDVersion = Ctx->FileKind >> 1;
+ TBDVersion = Ctx->FileKind >> 4;
Targets.insert(Targets.begin(), File->targets().begin(),
File->targets().end());
InstallName = File->getInstallName();
@@ -802,6 +784,9 @@ template <> struct MappingTraits<const InterfaceFile *> {
if (!File->isTwoLevelNamespace())
Flags |= TBDFlags::FlatNamespace;
+ if (File->isOSLibNotForSharedCache())
+ Flags |= TBDFlags::OSLibNotForSharedCache;
+
{
std::map<std::string, TargetList> valueToTargetList;
for (const auto &it : File->umbrellas())
@@ -892,6 +877,8 @@ template <> struct MappingTraits<const InterfaceFile *> {
File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
File->setApplicationExtensionSafe(
!(Flags & TBDFlags::NotApplicationExtensionSafe));
+ File->setOSLibNotForSharedCache(
+ (Flags & TBDFlags::OSLibNotForSharedCache));
for (const auto &CurrentSection : AllowableClients) {
for (const auto &lib : CurrentSection.Values)
@@ -906,7 +893,12 @@ template <> struct MappingTraits<const InterfaceFile *> {
}
auto handleSymbols = [File](const SectionList &CurrentSections,
- SymbolFlags Flag = SymbolFlags::None) {
+ SymbolFlags InputFlag = SymbolFlags::None) {
+ // For older file formats, the segment where the symbol
+ // comes from is unknown, treat all symbols as Data
+ // in these cases.
+ const SymbolFlags Flag = InputFlag | SymbolFlags::Data;
+
for (const auto &CurrentSection : CurrentSections) {
for (auto &sym : CurrentSection.Symbols)
File->addSymbol(SymbolKind::GlobalSymbol, sym,
@@ -924,9 +916,10 @@ template <> struct MappingTraits<const InterfaceFile *> {
File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, sym,
CurrentSection.Targets, Flag);
- SymbolFlags SymFlag = (Flag == SymbolFlags::Undefined)
- ? SymbolFlags::WeakReferenced
- : SymbolFlags::WeakDefined;
+ SymbolFlags SymFlag =
+ ((Flag & SymbolFlags::Undefined) == SymbolFlags::Undefined)
+ ? SymbolFlags::WeakReferenced
+ : SymbolFlags::WeakDefined;
for (auto &sym : CurrentSection.WeakSymbols) {
File->addSymbol(SymbolKind::GlobalSymbol, sym,
CurrentSection.Targets, Flag | SymFlag);
@@ -1078,38 +1071,35 @@ static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
File->ErrorMessage = ("malformed file\n" + Message).str();
}
-namespace {
-
-Expected<FileType> canReadFileType(MemoryBufferRef InputBuffer) {
+Expected<FileType> TextAPIReader::canRead(MemoryBufferRef InputBuffer) {
auto TAPIFile = InputBuffer.getBuffer().trim();
- if (TAPIFile.startswith("{") && TAPIFile.endswith("}"))
+ if (TAPIFile.starts_with("{") && TAPIFile.ends_with("}"))
return FileType::TBD_V5;
- if (!TAPIFile.endswith("..."))
+ if (!TAPIFile.ends_with("..."))
return createStringError(std::errc::not_supported, "unsupported file type");
- if (TAPIFile.startswith("--- !tapi-tbd\n"))
+ if (TAPIFile.starts_with("--- !tapi-tbd\n"))
return FileType::TBD_V4;
- if (TAPIFile.startswith("--- !tapi-tbd-v3\n"))
+ if (TAPIFile.starts_with("--- !tapi-tbd-v3\n"))
return FileType::TBD_V3;
- if (TAPIFile.startswith("--- !tapi-tbd-v2\n"))
+ if (TAPIFile.starts_with("--- !tapi-tbd-v2\n"))
return FileType::TBD_V2;
- if (TAPIFile.startswith("--- !tapi-tbd-v1\n") ||
- TAPIFile.startswith("---\narchs:"))
+ if (TAPIFile.starts_with("--- !tapi-tbd-v1\n") ||
+ TAPIFile.starts_with("---\narchs:"))
return FileType::TBD_V1;
return createStringError(std::errc::not_supported, "unsupported file type");
}
-} // namespace
Expected<std::unique_ptr<InterfaceFile>>
TextAPIReader::get(MemoryBufferRef InputBuffer) {
TextAPIContext Ctx;
Ctx.Path = std::string(InputBuffer.getBufferIdentifier());
- if (auto FTOrErr = canReadFileType(InputBuffer))
+ if (auto FTOrErr = canRead(InputBuffer))
Ctx.FileKind = *FTOrErr;
else
return FTOrErr.takeError();
@@ -1119,6 +1109,8 @@ TextAPIReader::get(MemoryBufferRef InputBuffer) {
auto FileOrErr = getInterfaceFileFromJSON(InputBuffer.getBuffer());
if (!FileOrErr)
return FileOrErr.takeError();
+
+ (*FileOrErr)->setPath(Ctx.Path);
return std::move(*FileOrErr);
}
yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
@@ -1143,14 +1135,18 @@ TextAPIReader::get(MemoryBufferRef InputBuffer) {
}
Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File,
- bool Compact) {
+ const FileType FileKind, bool Compact) {
TextAPIContext Ctx;
Ctx.Path = std::string(File.getPath());
- Ctx.FileKind = File.getFileType();
+
+ // Prefer parameter for format if passed, otherwise fallback to the File
+ // FileType.
+ Ctx.FileKind =
+ (FileKind == FileType::Invalid) ? File.getFileType() : FileKind;
// Write out in JSON format.
if (Ctx.FileKind >= FileType::TBD_V5) {
- return serializeInterfaceFileToJSON(OS, File, Compact);
+ return serializeInterfaceFileToJSON(OS, File, Ctx.FileKind, Compact);
}
llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
@@ -1158,7 +1154,7 @@ Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File,
std::vector<const InterfaceFile *> Files;
Files.emplace_back(&File);
- for (auto Document : File.documents())
+ for (const auto &Document : File.documents())
Files.emplace_back(Document.get());
// Stream out yaml.
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/TextStubCommon.h b/contrib/llvm-project/llvm/lib/TextAPI/TextStubCommon.h
index d4dcd3af447a..360910c48d4f 100644
--- a/contrib/llvm-project/llvm/lib/TextAPI/TextStubCommon.h
+++ b/contrib/llvm-project/llvm/lib/TextAPI/TextStubCommon.h
@@ -28,7 +28,9 @@ enum TBDFlags : unsigned {
FlatNamespace = 1U << 0,
NotApplicationExtensionSafe = 1U << 1,
InstallAPI = 1U << 2,
- LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
+ SimulatorSupport = 1U << 3,
+ OSLibNotForSharedCache = 1U << 4,
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OSLibNotForSharedCache),
};
// clang-format on
@@ -47,7 +49,7 @@ Expected<std::unique_ptr<InterfaceFile>>
getInterfaceFileFromJSON(StringRef JSON);
Error serializeInterfaceFileToJSON(raw_ostream &OS, const InterfaceFile &File,
- bool Compact);
+ const FileType FileKind, bool Compact);
} // namespace MachO
namespace yaml {
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/TextStubV5.cpp b/contrib/llvm-project/llvm/lib/TextAPI/TextStubV5.cpp
index 5b3d69b8d94a..2f82bc03480b 100644
--- a/contrib/llvm-project/llvm/lib/TextAPI/TextStubV5.cpp
+++ b/contrib/llvm-project/llvm/lib/TextAPI/TextStubV5.cpp
@@ -27,7 +27,7 @@ All library level keys, accept target values and are defaulted if not specified.
"target_info": [ # Required: target information
{
"target": "x86_64-macos",
- "min_deployment": "10.14" # Required: minimum OS deployment version
+ "min_deployment": "10.14" # Optional: minOS defaults to 0
},
{
"target": "arm64-macos",
@@ -283,17 +283,16 @@ Expected<TargetList> getTargetsSection(const Object *Section) {
getRequiredValue<StringRef>(TBDKey::Target, Obj, &Object::getString);
if (!TargetStr)
return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
- auto VersionStr = getRequiredValue<StringRef>(TBDKey::Deployment, Obj,
- &Object::getString);
- if (!VersionStr)
- return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Deployment));
- VersionTuple Version;
- if (Version.tryParse(*VersionStr))
- return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Deployment));
auto TargetOrErr = Target::create(*TargetStr);
if (!TargetOrErr)
return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
+
+ auto VersionStr = Obj->getString(Keys[TBDKey::Deployment]);
+ VersionTuple Version;
+ if (VersionStr && Version.tryParse(*VersionStr))
+ return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Deployment));
TargetOrErr->MinDeployment = Version;
+
// Convert to LLVM::Triple to accurately compute minOS + platform + arch
// pairing.
IFTargets.push_back(
@@ -548,11 +547,11 @@ Expected<PackedVersion> getPackedVersion(const Object *File, TBDKey Key) {
Expected<TBDFlags> getFlags(const Object *File) {
TBDFlags Flags = TBDFlags::None;
const Array *Section = File->getArray(Keys[TBDKey::Flags]);
- if (!Section)
+ if (!Section || Section->empty())
return Flags;
for (auto &Val : *Section) {
- // TODO: Just take first for now.
+ // FIXME: Flags currently apply to all target triples.
const auto *Obj = Val.getAsObject();
if (!Obj)
return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Flags));
@@ -564,6 +563,9 @@ Expected<TBDFlags> getFlags(const Object *File) {
.Case("flat_namespace", TBDFlags::FlatNamespace)
.Case("not_app_extension_safe",
TBDFlags::NotApplicationExtensionSafe)
+ .Case("sim_support", TBDFlags::SimulatorSupport)
+ .Case("not_for_dyld_shared_cache",
+ TBDFlags::OSLibNotForSharedCache)
.Default(TBDFlags::None);
Flags |= TBDFlag;
});
@@ -654,6 +656,8 @@ Expected<IFPtr> parseToInterfaceFile(const Object *File) {
F->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
F->setApplicationExtensionSafe(
!(Flags & TBDFlags::NotApplicationExtensionSafe));
+ F->setSimulatorSupport((Flags & TBDFlags::SimulatorSupport));
+ F->setOSLibNotForSharedCache((Flags & TBDFlags::OSLibNotForSharedCache));
for (auto &T : Targets)
F->addTarget(T);
for (auto &[Lib, Targets] : Clients)
@@ -753,9 +757,9 @@ std::vector<std::string> serializeTargets(const AggregateT Targets,
if (Targets.size() == ActiveTargets.size())
return TargetsStr;
- llvm::for_each(Targets, [&TargetsStr](const MachO::Target &Target) {
+ for (const MachO::Target &Target : Targets)
TargetsStr.emplace_back(getFormattedStr(Target));
- });
+
return TargetsStr;
}
@@ -763,7 +767,8 @@ Array serializeTargetInfo(const TargetList &ActiveTargets) {
Array Targets;
for (const auto Targ : ActiveTargets) {
Object TargetInfo;
- TargetInfo[Keys[TBDKey::Deployment]] = Targ.MinDeployment.getAsString();
+ if (!Targ.MinDeployment.empty())
+ TargetInfo[Keys[TBDKey::Deployment]] = Targ.MinDeployment.getAsString();
TargetInfo[Keys[TBDKey::Target]] = getFormattedStr(Targ);
Targets.emplace_back(std::move(TargetInfo));
}
@@ -920,6 +925,10 @@ Array serializeFlags(const InterfaceFile *File) {
Flags.emplace_back("flat_namespace");
if (!File->isApplicationExtensionSafe())
Flags.emplace_back("not_app_extension_safe");
+ if (File->hasSimulatorSupport())
+ Flags.emplace_back("sim_support");
+ if (File->isOSLibNotForSharedCache())
+ Flags.emplace_back("not_for_dyld_shared_cache");
return serializeScalar(TBDKey::Attributes, std::move(Flags));
}
@@ -983,9 +992,8 @@ Expected<Object> serializeIF(const InterfaceFile *File) {
return std::move(Library);
}
-Expected<Object> getJSON(const InterfaceFile *File) {
- assert(File->getFileType() == FileType::TBD_V5 &&
- "unexpected json file format version");
+Expected<Object> getJSON(const InterfaceFile *File, const FileType FileKind) {
+ assert(FileKind == FileType::TBD_V5 && "unexpected json file format version");
Object Root;
auto MainLibOrErr = serializeIF(File);
@@ -1009,8 +1017,9 @@ Expected<Object> getJSON(const InterfaceFile *File) {
Error MachO::serializeInterfaceFileToJSON(raw_ostream &OS,
const InterfaceFile &File,
+ const FileType FileKind,
bool Compact) {
- auto TextFile = getJSON(&File);
+ auto TextFile = getJSON(&File, FileKind);
if (!TextFile)
return TextFile.takeError();
if (Compact)