Skip to content

Move cherry-picks from stable/20190619 into swift/master #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 31, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions llvm/include/llvm/TextAPI/MachO/Architecture.h
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
#define LLVM_TEXTAPI_MACHO_ARCHITECTURE_H

#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm {
@@ -39,6 +40,9 @@ StringRef getArchitectureName(Architecture Arch);
/// Convert an architecture slice to a CPU Type and Subtype pair.
std::pair<uint32_t, uint32_t> getCPUTypeFromArchitecture(Architecture Arch);

/// Convert a target to an architecture slice.
Architecture mapToArchitecture(const llvm::Triple &Target);

raw_ostream &operator<<(raw_ostream &OS, Architecture Arch);

} // end namespace MachO.
4 changes: 4 additions & 0 deletions llvm/include/llvm/TextAPI/MachO/ArchitectureSet.h
Original file line number Diff line number Diff line change
@@ -59,6 +59,10 @@ class ArchitectureSet {

ArchSetType rawValue() const { return ArchSet; }

bool hasX86() const {
return has(AK_i386) || has(AK_x86_64) || has(AK_x86_64h);
}

template <typename Ty>
class arch_iterator
: public std::iterator<std::forward_iterator_tag, Architecture, size_t> {
142 changes: 84 additions & 58 deletions llvm/include/llvm/TextAPI/MachO/InterfaceFile.h
Original file line number Diff line number Diff line change
@@ -26,21 +26,13 @@
#include "llvm/TextAPI/MachO/Architecture.h"
#include "llvm/TextAPI/MachO/ArchitectureSet.h"
#include "llvm/TextAPI/MachO/PackedVersion.h"
#include "llvm/TextAPI/MachO/Platform.h"
#include "llvm/TextAPI/MachO/Symbol.h"
#include "llvm/TextAPI/MachO/Target.h"

namespace llvm {
namespace MachO {

/// Defines the list of MachO platforms.
enum class PlatformKind : unsigned {
unknown,
macOS = MachO::PLATFORM_MACOS,
iOS = MachO::PLATFORM_IOS,
tvOS = MachO::PLATFORM_TVOS,
watchOS = MachO::PLATFORM_WATCHOS,
bridgeOS = MachO::PLATFORM_BRIDGEOS,
};

/// Defines a list of Objective-C constraints.
enum class ObjCConstraintType : unsigned {
/// No constraint.
@@ -89,29 +81,42 @@ class InterfaceFileRef {

InterfaceFileRef(StringRef InstallName) : InstallName(InstallName) {}

InterfaceFileRef(StringRef InstallName, ArchitectureSet Archs)
: InstallName(InstallName), Architectures(Archs) {}
InterfaceFileRef(StringRef InstallName, const TargetList Targets)
: InstallName(InstallName), Targets(std::move(Targets)) {}

StringRef getInstallName() const { return InstallName; };
void addArchitectures(ArchitectureSet Archs) { Architectures |= Archs; }
ArchitectureSet getArchitectures() const { return Architectures; }
bool hasArchitecture(Architecture Arch) const {
return Architectures.has(Arch);

void addTarget(const Target &Target);
template <typename RangeT> void addTargets(RangeT &&Targets) {
for (const auto &Target : Targets)
addTarget(Target(Target));
}

using const_target_iterator = TargetList::const_iterator;
using const_target_range = llvm::iterator_range<const_target_iterator>;
const_target_range targets() const { return {Targets}; }

ArchitectureSet getArchitectures() const {
return mapToArchitectureSet(Targets);
}

PlatformSet getPlatforms() const { return mapToPlatformSet(Targets); }

bool operator==(const InterfaceFileRef &O) const {
return std::tie(InstallName, Architectures) ==
std::tie(O.InstallName, O.Architectures);
return std::tie(InstallName, Targets) == std::tie(O.InstallName, O.Targets);
}

bool operator!=(const InterfaceFileRef &O) const {
return std::tie(InstallName, Targets) != std::tie(O.InstallName, O.Targets);
}

bool operator<(const InterfaceFileRef &O) const {
return std::tie(InstallName, Architectures) <
std::tie(O.InstallName, O.Architectures);
return std::tie(InstallName, Targets) < std::tie(O.InstallName, O.Targets);
}

private:
std::string InstallName;
ArchitectureSet Architectures;
TargetList Targets;
};

} // end namespace MachO.
@@ -170,27 +175,43 @@ class InterfaceFile {
/// \return The file type.
FileType getFileType() const { return FileKind; }

/// Set the platform.
void setPlatform(PlatformKind Platform_) { Platform = Platform_; }
/// Get the architectures.
///
/// \return The applicable architectures.
ArchitectureSet getArchitectures() const {
return mapToArchitectureSet(Targets);
}

/// Get the platform.
PlatformKind getPlatform() const { return Platform; }
/// Get the platforms.
///
/// \return The applicable platforms.
PlatformSet getPlatforms() const { return mapToPlatformSet(Targets); }

/// Specify the set of supported architectures by this file.
void setArchitectures(ArchitectureSet Architectures_) {
Architectures = Architectures_;
}
/// Set and add target.
///
/// \param Target the target to add into.
void addTarget(const Target &Target);

/// Add the set of supported architectures by this file.
void addArchitectures(ArchitectureSet Architectures_) {
Architectures |= Architectures_;
/// Set and add targets.
///
/// Add the subset of llvm::triples that is supported by Tapi
///
/// \param Targets the collection of targets.
template <typename RangeT> void addTargets(RangeT &&Targets) {
for (const auto &Target_ : Targets)
addTarget(Target(Target_));
}

/// Add supported architecture by this file..
void addArch(Architecture Arch) { Architectures.set(Arch); }
using const_target_iterator = TargetList::const_iterator;
using const_target_range = llvm::iterator_range<const_target_iterator>;
const_target_range targets() const { return {Targets}; }

/// Get the set of supported architectures.
ArchitectureSet getArchitectures() const { return Architectures; }
using const_filtered_target_iterator =
llvm::filter_iterator<const_target_iterator,
std::function<bool(const Target &)>>;
using const_filtered_target_range =
llvm::iterator_range<const_filtered_target_iterator>;
const_filtered_target_range targets(ArchitectureSet Archs) const;

/// Set the install name of the library.
void setInstallName(StringRef InstallName_) { InstallName = InstallName_; }
@@ -244,11 +265,18 @@ class InterfaceFile {
/// Check if this file was generated during InstallAPI.
bool isInstallAPI() const { return IsInstallAPI; }

/// Set the parent umbrella framework.
void setParentUmbrella(StringRef Parent) { ParentUmbrella = Parent; }
/// Set the parent umbrella frameworks.
/// \param Target_ The target applicable to Parent
/// \param Parent The name of Parent
void addParentUmbrella(const Target &Target_, StringRef Parent);
const std::vector<std::pair<Target, std::string>> &umbrellas() const {
return ParentUmbrellas;
}

/// Get the parent umbrella framework.
StringRef getParentUmbrella() const { return ParentUmbrella; }
const std::vector<std::pair<Target, std::string>> getParentUmbrellas() const {
return ParentUmbrellas;
}

/// Add an allowable client.
///
@@ -258,8 +286,8 @@ class InterfaceFile {
/// linker refuses to link this library.
///
/// \param Name The name of the client that is allowed to link this library.
/// \param Architectures The set of architecture for which this applies.
void addAllowableClient(StringRef Name, ArchitectureSet Architectures);
/// \param Target The target triple for which this applies.
void addAllowableClient(StringRef InstallName, const Target &Target);

/// Get the list of allowable clients.
///
@@ -271,9 +299,8 @@ class InterfaceFile {
/// Add a re-exported library.
///
/// \param InstallName The name of the library to re-export.
/// \param Architectures The set of architecture for which this applies.
void addReexportedLibrary(StringRef InstallName,
ArchitectureSet Architectures);
/// \param Target The target triple for which this applies.
void addReexportedLibrary(StringRef InstallName, const Target &Target);

/// Get the list of re-exported libraries.
///
@@ -282,27 +309,27 @@ class InterfaceFile {
return ReexportedLibraries;
}

/// Add an architecture/UUID pair.
/// Add an Target/UUID pair.
///
/// \param Arch The architecture for which this applies.
/// \param Target The target triple for which this applies.
/// \param UUID The UUID of the library for the specified architecture.
void addUUID(Architecture Arch, StringRef UUID);
void addUUID(const Target &Target, StringRef UUID);

/// Add an architecture/UUID pair.
/// Add an Target/UUID pair.
///
/// \param Arch The architecture for which this applies.
/// \param Target The target triple for which this applies.
/// \param UUID The UUID of the library for the specified architecture.
void addUUID(Architecture Arch, uint8_t UUID[16]);
void addUUID(const Target &Target, uint8_t UUID[16]);

/// Get the list of architecture/UUID pairs.
/// Get the list of Target/UUID pairs.
///
/// \return Returns a list of architecture/UUID pairs.
const std::vector<std::pair<Architecture, std::string>> &uuids() const {
/// \return Returns a list of Target/UUID pairs.
const std::vector<std::pair<Target, std::string>> &uuids() const {
return UUIDs;
}

/// Add a symbol to the symbols list or extend an existing one.
void addSymbol(SymbolKind Kind, StringRef Name, ArchitectureSet Architectures,
void addSymbol(SymbolKind Kind, StringRef Name, const TargetList &Targets,
SymbolFlags Flags = SymbolFlags::None);

using SymbolMapType = DenseMap<SymbolsMapKey, Symbol *>;
@@ -411,10 +438,9 @@ class InterfaceFile {
return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
}

TargetList Targets;
std::string Path;
FileType FileKind;
PlatformKind Platform;
ArchitectureSet Architectures;
std::string InstallName;
PackedVersion CurrentVersion;
PackedVersion CompatibilityVersion;
@@ -423,10 +449,10 @@ class InterfaceFile {
bool IsAppExtensionSafe{false};
bool IsInstallAPI{false};
ObjCConstraintType ObjcConstraint = ObjCConstraintType::None;
std::string ParentUmbrella;
std::vector<std::pair<Target, std::string>> ParentUmbrellas;
std::vector<InterfaceFileRef> AllowableClients;
std::vector<InterfaceFileRef> ReexportedLibraries;
std::vector<std::pair<Architecture, std::string>> UUIDs;
std::vector<std::pair<Target, std::string>> UUIDs;
SymbolMapType Symbols;
};

40 changes: 40 additions & 0 deletions llvm/include/llvm/TextAPI/MachO/Platform.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===- llvm/TextAPI/MachO/Platform.h - Platform -----------------*- 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
//
//===----------------------------------------------------------------------===//
//
// Defines the Platforms supported by Tapi and helpers.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TEXTAPI_MACHO_PLATFORM_H
#define LLVM_TEXTAPI_MACHO_PLATFORM_H

#include "llvm/ADT/SmallSet.h"
#include "llvm/BinaryFormat/MachO.h"

namespace llvm {
namespace MachO {

/// Defines the list of MachO platforms.
enum class PlatformKind : unsigned {
unknown,
macOS = MachO::PLATFORM_MACOS,
iOS = MachO::PLATFORM_IOS,
tvOS = MachO::PLATFORM_TVOS,
watchOS = MachO::PLATFORM_WATCHOS,
bridgeOS = MachO::PLATFORM_BRIDGEOS
};

using PlatformSet = SmallSet<PlatformKind, 3>;

PlatformKind mapToPlatformKind(const Triple &Target);
PlatformSet mapToPlatformSet(ArrayRef<Triple> Targets);
StringRef getPlatformName(PlatformKind Platform);

} // end namespace MachO.
} // end namespace llvm.

#endif // LLVM_TEXTAPI_MACHO_PLATFORM_H
26 changes: 20 additions & 6 deletions llvm/include/llvm/TextAPI/MachO/Symbol.h
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/MachO/ArchitectureSet.h"
#include "llvm/TextAPI/MachO/Target.h"

namespace llvm {
namespace MachO {
@@ -49,16 +50,18 @@ enum class SymbolKind : uint8_t {
ObjectiveCInstanceVariable,
};

using TargetList = SmallVector<Target, 20>;
class Symbol {
public:
constexpr Symbol(SymbolKind Kind, StringRef Name,
ArchitectureSet Architectures, SymbolFlags Flags)
: Name(Name), Architectures(Architectures), Kind(Kind), Flags(Flags) {}
Symbol(SymbolKind Kind, StringRef Name, TargetList Targets, SymbolFlags Flags)
: Name(Name), Targets(std::move(Targets)), Kind(Kind), Flags(Flags) {}

void addTarget(Target target) { Targets.emplace_back(target); }
SymbolKind getKind() const { return Kind; }
StringRef getName() const { return Name; }
ArchitectureSet getArchitectures() const { return Architectures; }
void addArchitectures(ArchitectureSet Archs) { Architectures |= Archs; }
ArchitectureSet getArchitectures() const {
return mapToArchitectureSet(Targets);
}
SymbolFlags getFlags() const { return Flags; }

bool isWeakDefined() const {
@@ -78,14 +81,25 @@ class Symbol {
return (Flags & SymbolFlags::Undefined) == SymbolFlags::Undefined;
}

using const_target_iterator = TargetList::const_iterator;
using const_target_range = llvm::iterator_range<const_target_iterator>;
const_target_range targets() const { return {Targets}; }

using const_filtered_target_iterator =
llvm::filter_iterator<const_target_iterator,
std::function<bool(const Target &)>>;
using const_filtered_target_range =
llvm::iterator_range<const_filtered_target_iterator>;
const_filtered_target_range targets(ArchitectureSet architectures) const;

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void dump(raw_ostream &OS) const;
void dump() const { dump(llvm::errs()); }
#endif

private:
StringRef Name;
ArchitectureSet Architectures;
TargetList Targets;
SymbolKind Kind;
SymbolFlags Flags;
};
66 changes: 66 additions & 0 deletions llvm/include/llvm/TextAPI/MachO/Target.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===- llvm/TextAPI/Target.h - TAPI Target ----------------------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TEXTAPI_MACHO_TARGET_H
#define LLVM_TEXTAPI_MACHO_TARGET_H

#include "llvm/ADT/Triple.h"
#include "llvm/Support/Error.h"
#include "llvm/TextAPI/MachO/Architecture.h"
#include "llvm/TextAPI/MachO/ArchitectureSet.h"
#include "llvm/TextAPI/MachO/Platform.h"

namespace llvm {
namespace MachO {

// This is similar to a llvm Triple, but the triple doesn't have all the
// information we need. For example there is no enum value for x86_64h. The
// only way to get that information is to parse the triple string.
class Target {
public:
Target() = default;
Target(Architecture Arch, PlatformKind Platform)
: Arch(Arch), Platform(Platform) {}
explicit Target(const llvm::Triple &Triple)
: Arch(mapToArchitecture(Triple)), Platform(mapToPlatformKind(Triple)) {}

operator std::string() const;

Architecture Arch;
PlatformKind Platform;
};

inline bool operator==(const Target &LHS, const Target &RHS) {
return std::tie(LHS.Arch, LHS.Platform) == std::tie(RHS.Arch, RHS.Platform);
}

inline bool operator!=(const Target &LHS, const Target &RHS) {
return std::tie(LHS.Arch, LHS.Platform) != std::tie(RHS.Arch, RHS.Platform);
}

inline bool operator<(const Target &LHS, const Target &RHS) {
return std::tie(LHS.Arch, LHS.Platform) < std::tie(RHS.Arch, RHS.Platform);
}

inline bool operator==(const Target &LHS, const Architecture &RHS) {
return LHS.Arch == RHS;
}

inline bool operator!=(const Target &LHS, const Architecture &RHS) {
return LHS.Arch != RHS;
}

PlatformSet mapToPlatformSet(ArrayRef<Target> Targets);
ArchitectureSet mapToArchitectureSet(ArrayRef<Target> Targets);

raw_ostream &operator<<(raw_ostream &OS, const Target &Target);

} // namespace MachO
} // namespace llvm

#endif // LLVM_TEXTAPI_MACHO_TARGET_H
2 changes: 2 additions & 0 deletions llvm/lib/TextAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -5,7 +5,9 @@ add_llvm_library(LLVMTextAPI
MachO/ArchitectureSet.cpp
MachO/InterfaceFile.cpp
MachO/PackedVersion.cpp
MachO/Platform.cpp
MachO/Symbol.cpp
MachO/Target.cpp
MachO/TextStub.cpp
MachO/TextStubCommon.cpp

4 changes: 4 additions & 0 deletions llvm/lib/TextAPI/MachO/Architecture.cpp
Original file line number Diff line number Diff line change
@@ -68,6 +68,10 @@ std::pair<uint32_t, uint32_t> getCPUTypeFromArchitecture(Architecture Arch) {
return std::make_pair(0, 0);
}

Architecture mapToArchitecture(const Triple &Target) {
return getArchitectureFromName(Target.getArchName());
}

raw_ostream &operator<<(raw_ostream &OS, Architecture Arch) {
OS << getArchitectureName(Arch);
return OS;
80 changes: 61 additions & 19 deletions llvm/lib/TextAPI/MachO/InterfaceFile.cpp
Original file line number Diff line number Diff line change
@@ -27,54 +27,96 @@ typename C::iterator addEntry(C &Container, StringRef InstallName) {

return Container.emplace(I, InstallName);
}

template <typename C>
typename C::iterator addEntry(C &Container, const Target &Target_) {
auto Iter =
lower_bound(Container, Target_, [](const Target &LHS, const Target &RHS) {
return LHS < RHS;
});
if ((Iter != std::end(Container)) && !(Target_ < *Iter))
return Iter;

return Container.insert(Iter, Target_);
}
} // end namespace detail.

void InterfaceFile::addAllowableClient(StringRef Name,
ArchitectureSet Architectures) {
auto Client = detail::addEntry(AllowableClients, Name);
Client->addArchitectures(Architectures);
void InterfaceFileRef::addTarget(const Target &Target) {
detail::addEntry(Targets, Target);
}

void InterfaceFile::addAllowableClient(StringRef InstallName,
const Target &Target) {
auto Client = detail::addEntry(AllowableClients, InstallName);
Client->addTarget(Target);
}

void InterfaceFile::addReexportedLibrary(StringRef InstallName,
ArchitectureSet Architectures) {
const Target &Target) {
auto Lib = detail::addEntry(ReexportedLibraries, InstallName);
Lib->addArchitectures(Architectures);
Lib->addTarget(Target);
}

void InterfaceFile::addUUID(Architecture Arch, StringRef UUID) {
auto I = partition_point(UUIDs,
[=](const std::pair<Architecture, std::string> &O) {
return O.first < Arch;
});
void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
auto Iter = lower_bound(ParentUmbrellas, Target_,
[](const std::pair<Target, std::string> &LHS,
Target RHS) { return LHS.first < RHS; });

if (I != UUIDs.end() && Arch == I->first) {
I->second = UUID;
if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
Iter->second = Parent;
return;
}

UUIDs.emplace(I, Arch, UUID);
ParentUmbrellas.emplace(Iter, Target_, Parent);
return;
}

void InterfaceFile::addUUID(Architecture Arch, uint8_t UUID[16]) {
void InterfaceFile::addUUID(const Target &Target_, StringRef UUID) {
auto Iter = lower_bound(UUIDs, Target_,
[](const std::pair<Target, std::string> &LHS,
Target RHS) { return LHS.first < RHS; });

if ((Iter != UUIDs.end()) && !(Target_ < Iter->first)) {
Iter->second = UUID;
return;
}

UUIDs.emplace(Iter, Target_, UUID);
return;
}

void InterfaceFile::addUUID(const Target &Target, uint8_t UUID[16]) {
std::stringstream Stream;
for (unsigned i = 0; i < 16; ++i) {
if (i == 4 || i == 6 || i == 8 || i == 10)
Stream << '-';
Stream << std::setfill('0') << std::setw(2) << std::uppercase << std::hex
<< static_cast<int>(UUID[i]);
}
addUUID(Arch, Stream.str());
addUUID(Target, Stream.str());
}

void InterfaceFile::addTarget(const Target &Target) {
detail::addEntry(Targets, Target);
}

InterfaceFile::const_filtered_target_range
InterfaceFile::targets(ArchitectureSet Archs) const {
std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
return Archs.has(Target_.Arch);
};
return make_filter_range(Targets, fn);
}

void InterfaceFile::addSymbol(SymbolKind Kind, StringRef Name,
ArchitectureSet Archs, SymbolFlags Flags) {
const TargetList &Targets, SymbolFlags Flags) {
Name = copyString(Name);
auto result = Symbols.try_emplace(SymbolsMapKey{Kind, Name}, nullptr);
if (result.second)
result.first->second = new (Allocator) Symbol{Kind, Name, Archs, Flags};
result.first->second = new (Allocator) Symbol{Kind, Name, Targets, Flags};
else
result.first->second->addArchitectures(Archs);
for (const auto &Target : Targets)
result.first->second->addTarget(Target);
}

} // end namespace MachO.
62 changes: 62 additions & 0 deletions llvm/lib/TextAPI/MachO/Platform.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===- llvm/TextAPI/MachO/Platform.cpp - Platform ---------------*- 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
//
//===----------------------------------------------------------------------===//
//
// Implementations of Platform Helper functions.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/TextAPI/MachO/Platform.h"

namespace llvm {
namespace MachO {

PlatformKind mapToPlatformKind(const Triple &Target) {
switch (Target.getOS()) {
default:
return PlatformKind::unknown;
case Triple::MacOSX:
return PlatformKind::macOS;
case Triple::IOS:
return PlatformKind::iOS;
case Triple::TvOS:
return PlatformKind::tvOS;
case Triple::WatchOS:
return PlatformKind::watchOS;
// TODO: add bridgeOS once in llvm::Triple
}
}

PlatformSet mapToPlatformSet(ArrayRef<Triple> Targets) {
PlatformSet Result;
for (const auto &Target : Targets)
Result.insert(mapToPlatformKind(Target));
return Result;
}

StringRef getPlatformName(PlatformKind Platform) {
switch (Platform) {
case PlatformKind::unknown:
return "unknown";
case PlatformKind::macOS:
return "macOS";
case PlatformKind::iOS:
return "iOS";
case PlatformKind::tvOS:
return "tvOS";
case PlatformKind::watchOS:
return "watchOS";
case PlatformKind::bridgeOS:
return "bridgeOS";
}
llvm_unreachable("Unknown llvm.MachO.PlatformKind enum");
}

} // end namespace MachO.
} // end namespace llvm.
9 changes: 9 additions & 0 deletions llvm/lib/TextAPI/MachO/Symbol.cpp
Original file line number Diff line number Diff line change
@@ -45,5 +45,14 @@ LLVM_DUMP_METHOD void Symbol::dump(raw_ostream &OS) const {
}
#endif

Symbol::const_filtered_target_range
Symbol::targets(ArchitectureSet Architectures) const {
std::function<bool(const Target &)> FN =
[Architectures](const Target &Target) {
return Architectures.has(Target.Arch);
};
return make_filter_range(Targets, FN);
}

} // end namespace MachO.
} // end namespace llvm.
45 changes: 45 additions & 0 deletions llvm/lib/TextAPI/MachO/Target.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//===- tapi/Core/Target.cpp - Target ----------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/MachO/Target.h"

namespace llvm {
namespace MachO {

Target::operator std::string() const {
return (getArchitectureName(Arch) + " (" + getPlatformName(Platform) + ")")
.str();
}

raw_ostream &operator<<(raw_ostream &OS, const Target &Target) {
OS << std::string(Target);
return OS;
}

PlatformSet mapToPlatformSet(ArrayRef<Target> Targets) {
PlatformSet Result;
for (const auto &Target : Targets)
Result.insert(Target.Platform);
return Result;
}

ArchitectureSet mapToArchitectureSet(ArrayRef<Target> Targets) {
ArchitectureSet Result;
for (const auto &Target : Targets)
Result.set(Target.Arch);
return Result;
}

} // end namespace MachO.
} // end namespace llvm.
86 changes: 52 additions & 34 deletions llvm/lib/TextAPI/MachO/TextStub.cpp
Original file line number Diff line number Diff line change
@@ -246,7 +246,7 @@ template <> struct MappingTraits<const InterfaceFile *> {
NormalizedTBD(IO &IO, const InterfaceFile *&File) {
Architectures = File->getArchitectures();
UUIDs = File->uuids();
Platform = File->getPlatform();
Platforms = File->getPlatforms();
InstallName = File->getInstallName();
CurrentVersion = PackedVersion(File->getCurrentVersion());
CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
@@ -263,7 +263,10 @@ template <> struct MappingTraits<const InterfaceFile *> {
if (File->isInstallAPI())
Flags |= TBDFlags::InstallAPI;

ParentUmbrella = File->getParentUmbrella();
for (const auto &Iter : File->umbrellas()) {
ParentUmbrella = Iter.second;
break;
}

std::set<ArchitectureSet> ArchSet;
for (const auto &Library : File->allowableClients())
@@ -396,23 +399,34 @@ template <> struct MappingTraits<const InterfaceFile *> {
}
}

TargetList synthesizeTargets(ArchitectureSet Architectures,
const PlatformSet &Platforms) {
TargetList Targets;

for (auto Platform : Platforms) {
for (const auto &&Architecture : Architectures)
Targets.emplace_back(Architecture, Platform);
}
return Targets;
}

const InterfaceFile *denormalize(IO &IO) {
auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
assert(Ctx);

auto *File = new InterfaceFile;
File->setPath(Ctx->Path);
File->setFileType(Ctx->FileKind);
File->addTargets(synthesizeTargets(Architectures, Platforms));
for (auto &ID : UUIDs)
File->addUUID(ID.first, ID.second);
File->setPlatform(Platform);
File->setArchitectures(Architectures);
File->setInstallName(InstallName);
File->setCurrentVersion(CurrentVersion);
File->setCompatibilityVersion(CompatibilityVersion);
File->setSwiftABIVersion(SwiftABIVersion);
File->setObjCConstraint(ObjCConstraint);
File->setParentUmbrella(ParentUmbrella);
for (const auto &Target : File->targets())
File->addParentUmbrella(Target, ParentUmbrella);

if (Ctx->FileKind == FileType::TBD_V1) {
File->setTwoLevelNamespace();
@@ -425,76 +439,80 @@ template <> struct MappingTraits<const InterfaceFile *> {
}

for (const auto &Section : Exports) {
for (const auto &Library : Section.AllowableClients)
File->addAllowableClient(Library, Section.Architectures);
for (const auto &Library : Section.ReexportedLibraries)
File->addReexportedLibrary(Library, Section.Architectures);
const auto Targets =
synthesizeTargets(Section.Architectures, Platforms);

for (const auto &Lib : Section.AllowableClients)
for (const auto &Target : Targets)
File->addAllowableClient(Lib, Target);

for (const auto &Lib : Section.ReexportedLibraries)
for (const auto &Target : Targets)
File->addReexportedLibrary(Lib, Target);

for (const auto &Symbol : Section.Symbols) {
if (Ctx->FileKind != FileType::TBD_V3 &&
Symbol.value.startswith("_OBJC_EHTYPE_$_"))
File->addSymbol(SymbolKind::ObjectiveCClassEHType,
Symbol.value.drop_front(15), Section.Architectures);
Symbol.value.drop_front(15), Targets);
else
File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
Section.Architectures);
File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets);
}
for (auto &Symbol : Section.Classes) {
auto Name = Symbol.value;
if (Ctx->FileKind != FileType::TBD_V3)
Name = Name.drop_front();
File->addSymbol(SymbolKind::ObjectiveCClass, Name,
Section.Architectures);
File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets);
}
for (auto &Symbol : Section.ClassEHs)
File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol,
Section.Architectures);
File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets);
for (auto &Symbol : Section.IVars) {
auto Name = Symbol.value;
if (Ctx->FileKind != FileType::TBD_V3)
Name = Name.drop_front();
File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
Section.Architectures);
Targets);
}
for (auto &Symbol : Section.WeakDefSymbols)
File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
Section.Architectures, SymbolFlags::WeakDefined);
File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
SymbolFlags::WeakDefined);
for (auto &Symbol : Section.TLVSymbols)
File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
Section.Architectures, SymbolFlags::ThreadLocalValue);
File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
SymbolFlags::ThreadLocalValue);
}

for (const auto &Section : Undefineds) {
const auto Targets =
synthesizeTargets(Section.Architectures, Platforms);
for (auto &Symbol : Section.Symbols) {
if (Ctx->FileKind != FileType::TBD_V3 &&
Symbol.value.startswith("_OBJC_EHTYPE_$_"))
File->addSymbol(SymbolKind::ObjectiveCClassEHType,
Symbol.value.drop_front(15), Section.Architectures,
Symbol.value.drop_front(15), Targets,
SymbolFlags::Undefined);
else
File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
Section.Architectures, SymbolFlags::Undefined);
File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
SymbolFlags::Undefined);
}
for (auto &Symbol : Section.Classes) {
auto Name = Symbol.value;
if (Ctx->FileKind != FileType::TBD_V3)
Name = Name.drop_front();
File->addSymbol(SymbolKind::ObjectiveCClass, Name,
Section.Architectures, SymbolFlags::Undefined);
File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets,
SymbolFlags::Undefined);
}
for (auto &Symbol : Section.ClassEHs)
File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol,
Section.Architectures, SymbolFlags::Undefined);
File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets,
SymbolFlags::Undefined);
for (auto &Symbol : Section.IVars) {
auto Name = Symbol.value;
if (Ctx->FileKind != FileType::TBD_V3)
Name = Name.drop_front();
File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
Section.Architectures, SymbolFlags::Undefined);
File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets,
SymbolFlags::Undefined);
}
for (auto &Symbol : Section.WeakRefSymbols)
File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
Section.Architectures,
File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
}

@@ -513,7 +531,7 @@ template <> struct MappingTraits<const InterfaceFile *> {

std::vector<Architecture> Architectures;
std::vector<UUID> UUIDs;
PlatformKind Platform{PlatformKind::unknown};
PlatformSet Platforms;
StringRef InstallName;
PackedVersion CurrentVersion;
PackedVersion CompatibilityVersion;
@@ -567,7 +585,7 @@ template <> struct MappingTraits<const InterfaceFile *> {
IO.mapRequired("archs", Keys->Architectures);
if (Ctx->FileKind != FileType::TBD_V1)
IO.mapOptional("uuids", Keys->UUIDs);
IO.mapRequired("platform", Keys->Platform);
IO.mapRequired("platform", Keys->Platforms);
if (Ctx->FileKind != FileType::TBD_V1)
IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
IO.mapRequired("install-name", Keys->InstallName);
39 changes: 23 additions & 16 deletions llvm/lib/TextAPI/MachO/TextStubCommon.cpp
Original file line number Diff line number Diff line change
@@ -41,9 +41,10 @@ void ScalarEnumerationTraits<ObjCConstraintType>::enumeration(
IO.enumCase(Constraint, "gc", ObjCConstraintType::GC);
}

void ScalarTraits<PlatformKind>::output(const PlatformKind &Value, void *,
raw_ostream &OS) {
switch (Value) {
void ScalarTraits<PlatformSet>::output(const PlatformSet &Values, void *IO,
raw_ostream &OS) {
assert(Values.size() == 1U);
switch (*Values.begin()) {
default:
llvm_unreachable("unexpected platform");
break;
@@ -64,21 +65,26 @@ void ScalarTraits<PlatformKind>::output(const PlatformKind &Value, void *,
break;
}
}
StringRef ScalarTraits<PlatformKind>::input(StringRef Scalar, void *,
PlatformKind &Value) {
Value = StringSwitch<PlatformKind>(Scalar)
.Case("macosx", PlatformKind::macOS)
.Case("ios", PlatformKind::iOS)
.Case("watchos", PlatformKind::watchOS)
.Case("tvos", PlatformKind::tvOS)
.Case("bridgeos", PlatformKind::bridgeOS)
.Default(PlatformKind::unknown);

if (Value == PlatformKind::unknown)

StringRef ScalarTraits<PlatformSet>::input(StringRef Scalar, void *IO,
PlatformSet &Values) {
auto Platform = StringSwitch<PlatformKind>(Scalar)
.Case("unknown", PlatformKind::unknown)
.Case("macosx", PlatformKind::macOS)
.Case("ios", PlatformKind::iOS)
.Case("watchos", PlatformKind::watchOS)
.Case("tvos", PlatformKind::tvOS)
.Case("bridgeos", PlatformKind::bridgeOS)
.Default(PlatformKind::unknown);

if (Platform == PlatformKind::unknown)
return "unknown platform";

Values.insert(Platform);
return {};
}
QuotingType ScalarTraits<PlatformKind>::mustQuote(StringRef) {

QuotingType ScalarTraits<PlatformSet>::mustQuote(StringRef) {
return QuotingType::None;
}

@@ -166,10 +172,11 @@ StringRef ScalarTraits<UUID>::input(StringRef Scalar, void *, UUID &Value) {
auto UUID = Split.second.trim();
if (UUID.empty())
return "invalid uuid string pair";
Value.first = getArchitectureFromName(Arch);
Value.second = UUID;
Value.first = Target{getArchitectureFromName(Arch), PlatformKind::unknown};
return {};
}

QuotingType ScalarTraits<UUID>::mustQuote(StringRef) {
return QuotingType::Single;
}
8 changes: 4 additions & 4 deletions llvm/lib/TextAPI/MachO/TextStubCommon.h
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@
#include "llvm/TextAPI/MachO/InterfaceFile.h"
#include "llvm/TextAPI/MachO/PackedVersion.h"

using UUID = std::pair<llvm::MachO::Architecture, std::string>;
using UUID = std::pair<llvm::MachO::Target, std::string>;

LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, FlowStringRef)
LLVM_YAML_STRONG_TYPEDEF(uint8_t, SwiftVersion)
@@ -41,9 +41,9 @@ template <> struct ScalarEnumerationTraits<MachO::ObjCConstraintType> {
static void enumeration(IO &, MachO::ObjCConstraintType &);
};

template <> struct ScalarTraits<MachO::PlatformKind> {
static void output(const MachO::PlatformKind &, void *, raw_ostream &);
static StringRef input(StringRef, void *, MachO::PlatformKind &);
template <> struct ScalarTraits<MachO::PlatformSet> {
static void output(const MachO::PlatformSet &, void *, raw_ostream &);
static StringRef input(StringRef, void *, MachO::PlatformSet &);
static QuotingType mustQuote(StringRef);
};

64 changes: 45 additions & 19 deletions llvm/unittests/TextAPI/TextStubV1Tests.cpp
Original file line number Diff line number Diff line change
@@ -87,8 +87,13 @@ TEST(TBDv1, ReadFile) {
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V1, File->getFileType());
auto Archs = AK_armv7 | AK_armv7s | AK_armv7k | AK_arm64;
auto Platform = PlatformKind::iOS;
TargetList Targets;
for (auto &&arch : Archs)
Targets.emplace_back(Target(arch, Platform));
EXPECT_EQ(Archs, File->getArchitectures());
EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion());
EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
@@ -97,8 +102,8 @@ TEST(TBDv1, ReadFile) {
EXPECT_TRUE(File->isTwoLevelNamespace());
EXPECT_TRUE(File->isApplicationExtensionSafe());
EXPECT_FALSE(File->isInstallAPI());
InterfaceFileRef client("clientA", Archs);
InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Archs);
InterfaceFileRef client("clientA", Targets);
InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Targets);
EXPECT_EQ(1U, File->allowableClients().size());
EXPECT_EQ(client, File->allowableClients().front());
EXPECT_EQ(1U, File->reexportedLibraries().size());
@@ -117,6 +122,10 @@ TEST(TBDv1, ReadFile) {
EXPECT_EQ(sizeof(TBDv1Symbols) / sizeof(ExportedSymbol), Exports.size());
EXPECT_TRUE(
std::equal(Exports.begin(), Exports.end(), std::begin(TBDv1Symbols)));

File->addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", {Targets[1]});
File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1",
{Targets[1]});
}

TEST(TBDv1, ReadFile2) {
@@ -131,8 +140,13 @@ TEST(TBDv1, ReadFile2) {
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V1, File->getFileType());
auto Archs = AK_armv7 | AK_armv7s | AK_armv7k | AK_arm64;
auto Platform = PlatformKind::iOS;
TargetList Targets;
for (auto &&arch : Archs)
Targets.emplace_back(Target(arch, Platform));
EXPECT_EQ(Archs, File->getArchitectures());
EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
@@ -171,25 +185,27 @@ TEST(TBDv1, WriteFile) {
"...\n";

InterfaceFile File;
TargetList Targets;
for (auto &&arch : AK_i386 | AK_x86_64)
Targets.emplace_back(Target(arch, PlatformKind::macOS));
File.setPath("libfoo.dylib");
File.setInstallName("/usr/lib/libfoo.dylib");
File.setFileType(FileType::TBD_V1);
File.setArchitectures(AK_i386 | AK_x86_64);
File.setPlatform(PlatformKind::macOS);
File.addTargets(Targets);
File.setCurrentVersion(PackedVersion(1, 2, 3));
File.setSwiftABIVersion(5);
File.setObjCConstraint(ObjCConstraintType::Retain_Release);
File.addAllowableClient("clientA", AK_x86_64);
File.addReexportedLibrary("/usr/lib/libfoo.dylib", AK_x86_64);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", AK_i386);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", AK_i386,
File.addAllowableClient("clientA", Targets[1]);
File.addReexportedLibrary("/usr/lib/libfoo.dylib", Targets[1]);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", {Targets[0]});
File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", {Targets[0]},
SymbolFlags::WeakDefined);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", AK_i386,
File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", {Targets[0]},
SymbolFlags::ThreadLocalValue);
File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", AK_x86_64);
File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", AK_x86_64);
File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[1]});
File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", {Targets[1]});
File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1",
AK_x86_64);
{Targets[1]});

SmallString<4096> Buffer;
raw_svector_ostream OS(Buffer);
@@ -208,9 +224,11 @@ TEST(TBDv1, Platform_macOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_macos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::macOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V1, File->getFileType());
EXPECT_EQ(PlatformKind::macOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}
#endif // _WIN32

@@ -224,9 +242,11 @@ TEST(TBDv1, Platform_iOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_ios, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::iOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V1, File->getFileType());
EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv1, Platform_watchOS) {
@@ -239,9 +259,11 @@ TEST(TBDv1, Platform_watchOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_watchos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::watchOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V1, File->getFileType());
EXPECT_EQ(PlatformKind::watchOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv1, Platform_tvOS) {
@@ -254,9 +276,11 @@ TEST(TBDv1, Platform_tvOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_tvos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::tvOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V1, File->getFileType());
EXPECT_EQ(PlatformKind::tvOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv1, Platform_bridgeOS) {
@@ -269,9 +293,11 @@ TEST(TBDv1, Platform_bridgeOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_bridgeos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::bridgeOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V1, File->getFileType());
EXPECT_EQ(PlatformKind::bridgeOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv1, Swift_1_0) {
67 changes: 44 additions & 23 deletions llvm/unittests/TextAPI/TextStubV2Tests.cpp
Original file line number Diff line number Diff line change
@@ -89,8 +89,13 @@ TEST(TBDv2, ReadFile) {
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V2, File->getFileType());
auto Archs = AK_armv7 | AK_armv7s | AK_armv7k | AK_arm64;
auto Platform = PlatformKind::iOS;
TargetList Targets;
for (auto &&arch : Archs)
Targets.emplace_back(Target(arch, Platform));
EXPECT_EQ(Archs, File->getArchitectures());
EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion());
EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
@@ -99,8 +104,8 @@ TEST(TBDv2, ReadFile) {
EXPECT_TRUE(File->isTwoLevelNamespace());
EXPECT_TRUE(File->isApplicationExtensionSafe());
EXPECT_TRUE(File->isInstallAPI());
InterfaceFileRef client("clientA", Archs);
InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Archs);
InterfaceFileRef client("clientA", Targets);
InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Targets);
EXPECT_EQ(1U, File->allowableClients().size());
EXPECT_EQ(client, File->allowableClients().front());
EXPECT_EQ(1U, File->reexportedLibraries().size());
@@ -155,8 +160,13 @@ TEST(TBDv2, ReadFile2) {
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V2, File->getFileType());
auto Archs = AK_armv7 | AK_armv7s | AK_armv7k | AK_arm64;
auto Platform = PlatformKind::iOS;
TargetList Targets;
for (auto &&arch : Archs)
Targets.emplace_back(Target(arch, Platform));
EXPECT_EQ(Archs, File->getArchitectures());
EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
@@ -194,27 +204,29 @@ TEST(TBDv2, WriteFile) {
"...\n";

InterfaceFile File;
TargetList Targets;
for (auto &&arch : AK_i386 | AK_x86_64)
Targets.emplace_back(Target(arch, PlatformKind::macOS));
File.setPath("libfoo.dylib");
File.setInstallName("/usr/lib/libfoo.dylib");
File.setFileType(FileType::TBD_V2);
File.setArchitectures(AK_i386 | AK_x86_64);
File.setPlatform(PlatformKind::macOS);
File.addTargets(Targets);
File.setCurrentVersion(PackedVersion(1, 2, 3));
File.setTwoLevelNamespace();
File.setApplicationExtensionSafe();
File.setSwiftABIVersion(5);
File.setObjCConstraint(ObjCConstraintType::Retain_Release);
File.addAllowableClient("clientA", AK_x86_64);
File.addReexportedLibrary("/usr/lib/libfoo.dylib", AK_x86_64);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", AK_i386);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", AK_i386,
File.addAllowableClient("clientA", Targets[1]);
File.addReexportedLibrary("/usr/lib/libfoo.dylib", Targets[1]);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", {Targets[0]});
File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", {Targets[0]},
SymbolFlags::WeakDefined);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", AK_i386,
File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", {Targets[0]},
SymbolFlags::ThreadLocalValue);
File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", AK_x86_64);
File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", AK_x86_64);
File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[1]});
File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", {Targets[1]});
File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1",
AK_x86_64);
{Targets[1]});

SmallString<4096> Buffer;
raw_svector_ostream OS(Buffer);
@@ -235,8 +247,10 @@ TEST(TBDv2, Platform_macOS) {
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_macos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto File = std::move(Result.get());
auto Platform = PlatformKind::macOS;
EXPECT_EQ(FileType::TBD_V2, File->getFileType());
EXPECT_EQ(PlatformKind::macOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv2, Platform_iOS) {
@@ -249,9 +263,11 @@ TEST(TBDv2, Platform_iOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_ios, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::iOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V2, File->getFileType());
EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv2, Platform_watchOS) {
@@ -264,9 +280,11 @@ TEST(TBDv2, Platform_watchOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_watchos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::watchOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V2, File->getFileType());
EXPECT_EQ(PlatformKind::watchOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv2, Platform_tvOS) {
@@ -279,9 +297,11 @@ TEST(TBDv2, Platform_tvOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_tvos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::tvOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V2, File->getFileType());
EXPECT_EQ(PlatformKind::tvOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv2, Platform_bridgeOS) {
@@ -294,9 +314,11 @@ TEST(TBDv2, Platform_bridgeOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_bridgeos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::bridgeOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V2, File->getFileType());
EXPECT_EQ(PlatformKind::bridgeOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv2, Swift_1_0) {
@@ -418,17 +440,16 @@ TEST(TBDv2, UnknownArchitecture) {
"platform: macosx\n"
"install-name: Test.dylib\n"
"...\n";

auto Result = TextAPIReader::get(
MemoryBufferRef(tbd_v2_file_unknown_architecture, "Test.tbd"));
EXPECT_TRUE(!!Result);
}

TEST(TBDv2, UnknownPlatform) {
static const char tbd_v2_file_unknown_platform[] = "--- !tapi-tbd-v2\n"
"archs: [ i386 ]\n"
"platform: newOS\n"
"...\n";
"archs: [ i386 ]\n"
"platform: newOS\n"
"...\n";

auto Result = TextAPIReader::get(
MemoryBufferRef(tbd_v2_file_unknown_platform, "Test.tbd"));
63 changes: 41 additions & 22 deletions llvm/unittests/TextAPI/TextStubV3Tests.cpp
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ struct ExportedSymbol {
bool ThreadLocalValue;
};
using ExportedSymbolSeq = std::vector<ExportedSymbol>;
using UUIDs = std::vector<std::pair<Architecture, std::string>>;
using UUIDs = std::vector<std::pair<Target, std::string>>;

inline bool operator<(const ExportedSymbol &lhs, const ExportedSymbol &rhs) {
return std::tie(lhs.Kind, lhs.Name) < std::tie(rhs.Kind, rhs.Name);
@@ -93,11 +93,18 @@ TEST(TBDv3, ReadFile) {
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V3, File->getFileType());
auto Archs = AK_armv7 | AK_arm64;
auto Platform = PlatformKind::iOS;
TargetList Targets;
for (auto &&arch : Archs)
Targets.emplace_back(Target(arch, Platform));
EXPECT_EQ(Archs, File->getArchitectures());
UUIDs uuids = {{AK_armv7, "00000000-0000-0000-0000-000000000000"},
{AK_arm64, "11111111-1111-1111-1111-111111111111"}};
EXPECT_EQ(uuids, File->uuids());
EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
UUIDs Uuids = {{Target(AK_armv7, PlatformKind::unknown),
"00000000-0000-0000-0000-000000000000"},
{Target(AK_arm64, PlatformKind::unknown),
"11111111-1111-1111-1111-111111111111"}};
EXPECT_EQ(Uuids, File->uuids());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion());
EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
@@ -106,8 +113,8 @@ TEST(TBDv3, ReadFile) {
EXPECT_TRUE(File->isTwoLevelNamespace());
EXPECT_TRUE(File->isApplicationExtensionSafe());
EXPECT_TRUE(File->isInstallAPI());
InterfaceFileRef client("clientA", Archs);
InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Archs);
InterfaceFileRef client("clientA", Targets);
InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Targets);
EXPECT_EQ(1U, File->allowableClients().size());
EXPECT_EQ(client, File->allowableClients().front());
EXPECT_EQ(1U, File->reexportedLibraries().size());
@@ -151,27 +158,29 @@ TEST(TBDv3, WriteFile) {
"...\n";

InterfaceFile File;
TargetList Targets;
for (auto &&arch : AK_i386 | AK_x86_64)
Targets.emplace_back(Target(arch, PlatformKind::macOS));
File.setPath("libfoo.dylib");
File.setInstallName("/usr/lib/libfoo.dylib");
File.setFileType(FileType::TBD_V3);
File.setArchitectures(AK_i386 | AK_x86_64);
File.setPlatform(PlatformKind::macOS);
File.addTargets(Targets);
File.setCurrentVersion(PackedVersion(1, 2, 3));
File.setTwoLevelNamespace();
File.setApplicationExtensionSafe();
File.setSwiftABIVersion(5);
File.setObjCConstraint(ObjCConstraintType::Retain_Release);
File.addAllowableClient("clientA", AK_x86_64);
File.addReexportedLibrary("/usr/lib/libfoo.dylib", AK_x86_64);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", AK_i386);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", AK_i386,
File.addAllowableClient("clientA", Targets[1]);
File.addReexportedLibrary("/usr/lib/libfoo.dylib", Targets[1]);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", {Targets[0]});
File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", {Targets[0]},
SymbolFlags::WeakDefined);
File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", AK_i386,
File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", {Targets[0]},
SymbolFlags::ThreadLocalValue);
File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", AK_x86_64);
File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", AK_x86_64);
File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[1]});
File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", {Targets[1]});
File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1",
AK_x86_64);
{Targets[1]});

SmallString<4096> Buffer;
raw_svector_ostream OS(Buffer);
@@ -190,9 +199,11 @@ TEST(TBDv3, Platform_macOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_macos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::macOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V3, File->getFileType());
EXPECT_EQ(PlatformKind::macOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv3, Platform_iOS) {
@@ -205,9 +216,11 @@ TEST(TBDv3, Platform_iOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_ios, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::iOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V3, File->getFileType());
EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv3, Platform_watchOS) {
@@ -220,9 +233,11 @@ TEST(TBDv3, Platform_watchOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_watchos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::watchOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V3, File->getFileType());
EXPECT_EQ(PlatformKind::watchOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv3, Platform_tvOS) {
@@ -236,8 +251,10 @@ TEST(TBDv3, Platform_tvOS) {
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_tvos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto File = std::move(Result.get());
auto Platform = PlatformKind::tvOS;
EXPECT_EQ(FileType::TBD_V3, File->getFileType());
EXPECT_EQ(PlatformKind::tvOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv3, Platform_bridgeOS) {
@@ -250,9 +267,11 @@ TEST(TBDv3, Platform_bridgeOS) {
auto Result =
TextAPIReader::get(MemoryBufferRef(tbd_v1_platform_bridgeos, "Test.tbd"));
EXPECT_TRUE(!!Result);
auto Platform = PlatformKind::bridgeOS;
auto File = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V3, File->getFileType());
EXPECT_EQ(PlatformKind::bridgeOS, File->getPlatform());
EXPECT_EQ(File->getPlatforms().size(), 1U);
EXPECT_EQ(Platform, *File->getPlatforms().begin());
}

TEST(TBDv3, Swift_1_0) {