diff --git a/llvm/include/llvm/TextAPI/MachO/Architecture.h b/llvm/include/llvm/TextAPI/MachO/Architecture.h --- a/llvm/include/llvm/TextAPI/MachO/Architecture.h +++ b/llvm/include/llvm/TextAPI/MachO/Architecture.h @@ -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 @@ /// Convert an architecture slice to a CPU Type and Subtype pair. std::pair 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. diff --git a/llvm/include/llvm/TextAPI/MachO/ArchitectureSet.h b/llvm/include/llvm/TextAPI/MachO/ArchitectureSet.h --- a/llvm/include/llvm/TextAPI/MachO/ArchitectureSet.h +++ b/llvm/include/llvm/TextAPI/MachO/ArchitectureSet.h @@ -59,6 +59,10 @@ ArchSetType rawValue() const { return ArchSet; } + bool hasX86() const { + return has(AK_i386) || has(AK_x86_64) || has(AK_x86_64h); + } + template class arch_iterator : public std::iterator { diff --git a/llvm/include/llvm/TextAPI/MachO/InterfaceFile.h b/llvm/include/llvm/TextAPI/MachO/InterfaceFile.h --- a/llvm/include/llvm/TextAPI/MachO/InterfaceFile.h +++ b/llvm/include/llvm/TextAPI/MachO/InterfaceFile.h @@ -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 @@ 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 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_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 @@ /// \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 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_range targets() const { return {Targets}; } - /// Get the set of supported architectures. - ArchitectureSet getArchitectures() const { return Architectures; } + using const_filtered_target_iterator = + llvm::filter_iterator>; + using const_filtered_target_range = + llvm::iterator_range; + 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 @@ /// 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> &umbrellas() const { + return ParentUmbrellas; + } /// Get the parent umbrella framework. - StringRef getParentUmbrella() const { return ParentUmbrella; } + const std::vector> getParentUmbrellas() const { + return ParentUmbrellas; + } /// Add an allowable client. /// @@ -258,8 +286,8 @@ /// 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 @@ /// 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 @@ 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> &uuids() const { + /// \return Returns a list of Target/UUID pairs. + const std::vector> &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, TargetList Targets, SymbolFlags Flags = SymbolFlags::None); using SymbolMapType = DenseMap; @@ -362,10 +389,9 @@ return StringRef(reinterpret_cast(Ptr), String.size()); } + TargetList Targets; std::string Path; FileType FileKind; - PlatformKind Platform; - ArchitectureSet Architectures; std::string InstallName; PackedVersion CurrentVersion; PackedVersion CompatibilityVersion; @@ -374,10 +400,10 @@ bool IsAppExtensionSafe{false}; bool IsInstallAPI{false}; ObjCConstraintType ObjcConstraint = ObjCConstraintType::None; - std::string ParentUmbrella; + std::vector> ParentUmbrellas; std::vector AllowableClients; std::vector ReexportedLibraries; - std::vector> UUIDs; + std::vector> UUIDs; SymbolMapType Symbols; }; diff --git a/llvm/include/llvm/TextAPI/MachO/Platform.h b/llvm/include/llvm/TextAPI/MachO/Platform.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/TextAPI/MachO/Platform.h @@ -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 mapToPlatformKind(const Triple &Target); +PlatformSet mapToPlatformSet(ArrayRef Targets); +StringRef getPlatformName(PlatformKind Platform); + +} // end namespace MachO. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_MACHO_PLATFORM_H \ No newline at end of file diff --git a/llvm/include/llvm/TextAPI/MachO/Symbol.h b/llvm/include/llvm/TextAPI/MachO/Symbol.h --- a/llvm/include/llvm/TextAPI/MachO/Symbol.h +++ b/llvm/include/llvm/TextAPI/MachO/Symbol.h @@ -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 @@ ObjectiveCInstanceVariable, }; +using TargetList = std::vector; 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,6 +81,17 @@ return (Flags & SymbolFlags::Undefined) == SymbolFlags::Undefined; } + using const_target_iterator = TargetList::const_iterator; + using const_target_range = llvm::iterator_range; + const_target_range targets() const { return {Targets}; } + + using const_filtered_target_iterator = + llvm::filter_iterator>; + using const_filtered_target_range = + llvm::iterator_range; + 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()); } @@ -85,7 +99,7 @@ private: StringRef Name; - ArchitectureSet Architectures; + TargetList Targets; SymbolKind Kind; SymbolFlags Flags; }; diff --git a/llvm/include/llvm/TextAPI/MachO/Target.h b/llvm/include/llvm/TextAPI/MachO/Target.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/TextAPI/MachO/Target.h @@ -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 Targets); +ArchitectureSet mapToArchitectureSet(ArrayRef Targets); + +raw_ostream &operator<<(raw_ostream &OS, const Target &Target); + +} // namespace MachO +} // namespace llvm + +#endif // LLVM_TEXTAPI_MACHO_TARGET_H diff --git a/llvm/lib/Object/TapiFile.cpp b/llvm/lib/Object/TapiFile.cpp --- a/llvm/lib/Object/TapiFile.cpp +++ b/llvm/lib/Object/TapiFile.cpp @@ -45,13 +45,13 @@ if (!Symbol->getArchitectures().has(Arch)) continue; - auto Platform = interface.getPlatform(); switch (Symbol->getKind()) { case SymbolKind::GlobalSymbol: Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol)); break; case SymbolKind::ObjectiveCClass: - if (Platform == PlatformKind::macOS && Arch == AK_i386) { + if (interface.getPlatforms().count(PlatformKind::macOS) && + Arch == AK_i386) { Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(), getFlags(Symbol)); } else { diff --git a/llvm/lib/TextAPI/CMakeLists.txt b/llvm/lib/TextAPI/CMakeLists.txt --- a/llvm/lib/TextAPI/CMakeLists.txt +++ b/llvm/lib/TextAPI/CMakeLists.txt @@ -5,7 +5,9 @@ MachO/ArchitectureSet.cpp MachO/InterfaceFile.cpp MachO/PackedVersion.cpp + MachO/Platform.cpp MachO/Symbol.cpp + MachO/Target.cpp MachO/TextStub.cpp MachO/TextStubCommon.cpp diff --git a/llvm/lib/TextAPI/MachO/Architecture.cpp b/llvm/lib/TextAPI/MachO/Architecture.cpp --- a/llvm/lib/TextAPI/MachO/Architecture.cpp +++ b/llvm/lib/TextAPI/MachO/Architecture.cpp @@ -68,6 +68,10 @@ 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; diff --git a/llvm/lib/TextAPI/MachO/InterfaceFile.cpp b/llvm/lib/TextAPI/MachO/InterfaceFile.cpp --- a/llvm/lib/TextAPI/MachO/InterfaceFile.cpp +++ b/llvm/lib/TextAPI/MachO/InterfaceFile.cpp @@ -27,36 +27,65 @@ return Container.emplace(I, InstallName); } + +template +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.emplace(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 &O) { - return O.first < Arch; - }); +void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) { + auto Iter = lower_bound(ParentUmbrellas, Target_, + [](const std::pair &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 &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) @@ -64,17 +93,30 @@ Stream << std::setfill('0') << std::setw(2) << std::uppercase << std::hex << static_cast(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 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) { + 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. diff --git a/llvm/lib/TextAPI/MachO/Platform.cpp b/llvm/lib/TextAPI/MachO/Platform.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/TextAPI/MachO/Platform.cpp @@ -0,0 +1,61 @@ +//===- 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 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"; + } +} + +} // end namespace MachO. +} // end namespace llvm. \ No newline at end of file diff --git a/llvm/lib/TextAPI/MachO/Symbol.cpp b/llvm/lib/TextAPI/MachO/Symbol.cpp --- a/llvm/lib/TextAPI/MachO/Symbol.cpp +++ b/llvm/lib/TextAPI/MachO/Symbol.cpp @@ -45,5 +45,14 @@ } #endif +Symbol::const_filtered_target_range +Symbol::targets(ArchitectureSet Architectures) const { + std::function FN = + [Architectures](const Target &Target) { + return Architectures.has(Target.Arch); + }; + return make_filter_range(Targets, FN); +} + } // end namespace MachO. } // end namespace llvm. diff --git a/llvm/lib/TextAPI/MachO/Target.cpp b/llvm/lib/TextAPI/MachO/Target.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/TextAPI/MachO/Target.cpp @@ -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 Targets) { + PlatformSet Result; + for (const auto &Target : Targets) + Result.insert(Target.Platform); + return Result; +} + +ArchitectureSet mapToArchitectureSet(ArrayRef Targets) { + ArchitectureSet Result; + for (const auto &Target : Targets) + Result.set(Target.Arch); + return Result; +} + +} // end namespace MachO. +} // end namespace llvm. \ No newline at end of file diff --git a/llvm/lib/TextAPI/MachO/TextStub.cpp b/llvm/lib/TextAPI/MachO/TextStub.cpp --- a/llvm/lib/TextAPI/MachO/TextStub.cpp +++ b/llvm/lib/TextAPI/MachO/TextStub.cpp @@ -246,7 +246,7 @@ 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 @@ if (File->isInstallAPI()) Flags |= TBDFlags::InstallAPI; - ParentUmbrella = File->getParentUmbrella(); + for (const auto &Iter : File->umbrellas()) { + ParentUmbrella = Iter.second; + break; + } std::set ArchSet; for (const auto &Library : File->allowableClients()) @@ -396,6 +399,17 @@ } } + 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(IO.getContext()); assert(Ctx); @@ -403,16 +417,16 @@ 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 @@ } 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 @@ std::vector Architectures; std::vector UUIDs; - PlatformKind Platform{PlatformKind::unknown}; + PlatformSet Platforms; StringRef InstallName; PackedVersion CurrentVersion; PackedVersion CompatibilityVersion; @@ -567,7 +585,7 @@ 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); diff --git a/llvm/lib/TextAPI/MachO/TextStubCommon.h b/llvm/lib/TextAPI/MachO/TextStubCommon.h --- a/llvm/lib/TextAPI/MachO/TextStubCommon.h +++ b/llvm/lib/TextAPI/MachO/TextStubCommon.h @@ -21,7 +21,7 @@ #include "llvm/TextAPI/MachO/InterfaceFile.h" #include "llvm/TextAPI/MachO/PackedVersion.h" -using UUID = std::pair; +using UUID = std::pair; LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, FlowStringRef) LLVM_YAML_STRONG_TYPEDEF(uint8_t, SwiftVersion) @@ -41,9 +41,9 @@ static void enumeration(IO &, MachO::ObjCConstraintType &); }; -template <> struct ScalarTraits { - static void output(const MachO::PlatformKind &, void *, raw_ostream &); - static StringRef input(StringRef, void *, MachO::PlatformKind &); +template <> struct ScalarTraits { + static void output(const MachO::PlatformSet &, void *, raw_ostream &); + static StringRef input(StringRef, void *, MachO::PlatformSet &); static QuotingType mustQuote(StringRef); }; diff --git a/llvm/lib/TextAPI/MachO/TextStubCommon.cpp b/llvm/lib/TextAPI/MachO/TextStubCommon.cpp --- a/llvm/lib/TextAPI/MachO/TextStubCommon.cpp +++ b/llvm/lib/TextAPI/MachO/TextStubCommon.cpp @@ -41,9 +41,10 @@ IO.enumCase(Constraint, "gc", ObjCConstraintType::GC); } -void ScalarTraits::output(const PlatformKind &Value, void *, - raw_ostream &OS) { - switch (Value) { +void ScalarTraits::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 @@ break; } } -StringRef ScalarTraits::input(StringRef Scalar, void *, - PlatformKind &Value) { - Value = StringSwitch(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::input(StringRef Scalar, void *IO, + PlatformSet &Values) { + auto Platform = StringSwitch(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::mustQuote(StringRef) { + +QuotingType ScalarTraits::mustQuote(StringRef) { return QuotingType::None; } @@ -166,10 +172,11 @@ 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::mustQuote(StringRef) { return QuotingType::Single; } diff --git a/llvm/tools/llvm-ifs/llvm-ifs.cpp b/llvm/tools/llvm-ifs/llvm-ifs.cpp --- a/llvm/tools/llvm-ifs/llvm-ifs.cpp +++ b/llvm/tools/llvm-ifs/llvm-ifs.cpp @@ -220,21 +220,6 @@ int writeTbdStub(const llvm::Triple &T, const std::set &Symbols, const StringRef Format, raw_ostream &Out) { - auto ArchOrError = - [](const llvm::Triple &T) -> llvm::Expected { - switch (T.getArch()) { - default: - return createStringError(errc::not_supported, "Invalid Architecture.\n"); - case llvm::Triple::ArchType::x86: - return AK_i386; - case llvm::Triple::ArchType::x86_64: - return AK_x86_64; - case llvm::Triple::ArchType::arm: - return AK_armv7; - case llvm::Triple::ArchType::aarch64: - return AK_arm64; - } - }(T); auto PlatformKindOrError = [](const llvm::Triple &T) -> llvm::Expected { @@ -256,19 +241,15 @@ return createStringError(errc::not_supported, "Invalid Platform.\n"); }(T); - if (!ArchOrError) - return -1; - if (!PlatformKindOrError) return -1; - Architecture Arch = ArchOrError.get(); PlatformKind Plat = PlatformKindOrError.get(); + TargetList Targets({Target(llvm::MachO::mapToArchitecture(T), Plat)}); InterfaceFile File; File.setFileType(FileType::TBD_V3); // Only supporting v3 for now. - File.setArchitectures(Arch); - File.setPlatform(Plat); + File.addTargets(Targets); for (const auto &Symbol : Symbols) { auto Name = Symbol.Name; @@ -286,9 +267,9 @@ break; } if (Symbol.Weak) - File.addSymbol(Kind, Name, Arch, SymbolFlags::WeakDefined); + File.addSymbol(Kind, Name, Targets, SymbolFlags::WeakDefined); else - File.addSymbol(Kind, Name, Arch); + File.addSymbol(Kind, Name, Targets); } SmallString<4096> Buffer; diff --git a/llvm/unittests/TextAPI/TextStubV1Tests.cpp b/llvm/unittests/TextAPI/TextStubV1Tests.cpp --- a/llvm/unittests/TextAPI/TextStubV1Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV1Tests.cpp @@ -87,8 +87,13 @@ 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 @@ 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 @@ 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.at(1)}); + File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1", + {Targets.at(1)}); } TEST(TBDv1, ReadFile2) { @@ -131,8 +140,13 @@ 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()); @@ -169,25 +183,27 @@ "...\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.at(1)); + File.addReexportedLibrary("/usr/lib/libfoo.dylib", Targets.at(1)); + File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", {Targets.at(0)}); + File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", {Targets.at(0)}, SymbolFlags::WeakDefined); - File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", AK_i386, + File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", {Targets.at(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.at(1)}); + File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", {Targets.at(1)}); File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1", - AK_x86_64); + {Targets.at(1)}); SmallString<4096> Buffer; raw_svector_ostream OS(Buffer); @@ -206,9 +222,11 @@ 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()); } TEST(TBDv1, Platform_iOS) { @@ -221,9 +239,11 @@ 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) { @@ -236,9 +256,11 @@ 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) { @@ -251,9 +273,11 @@ 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) { @@ -266,9 +290,11 @@ 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) { diff --git a/llvm/unittests/TextAPI/TextStubV2Tests.cpp b/llvm/unittests/TextAPI/TextStubV2Tests.cpp --- a/llvm/unittests/TextAPI/TextStubV2Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV2Tests.cpp @@ -89,8 +89,13 @@ 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 @@ 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 @@ 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()); @@ -192,27 +202,29 @@ "...\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.at(1)); + File.addReexportedLibrary("/usr/lib/libfoo.dylib", Targets.at(1)); + File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", {Targets.at(0)}); + File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", {Targets.at(0)}, SymbolFlags::WeakDefined); - File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", AK_i386, + File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", {Targets.at(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.at(1)}); + File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", {Targets.at(1)}); File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1", - AK_x86_64); + {Targets.at(1)}); SmallString<4096> Buffer; raw_svector_ostream OS(Buffer); @@ -232,8 +244,10 @@ 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) { @@ -246,9 +260,11 @@ 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) { @@ -261,9 +277,11 @@ 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) { @@ -276,9 +294,11 @@ 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) { @@ -291,9 +311,11 @@ 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) { @@ -415,7 +437,6 @@ "platform: macosx\n" "install-name: Test.dylib\n" "...\n"; - auto Result = TextAPIReader::get( MemoryBufferRef(tbd_v2_file_unknown_architecture, "Test.tbd")); EXPECT_TRUE(!!Result); @@ -423,9 +444,9 @@ 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")); diff --git a/llvm/unittests/TextAPI/TextStubV3Tests.cpp b/llvm/unittests/TextAPI/TextStubV3Tests.cpp --- a/llvm/unittests/TextAPI/TextStubV3Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV3Tests.cpp @@ -23,7 +23,7 @@ bool ThreadLocalValue; }; using ExportedSymbolSeq = std::vector; -using UUIDs = std::vector>; +using UUIDs = std::vector>; 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 @@ 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 @@ 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 @@ "...\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.at(1)); + File.addReexportedLibrary("/usr/lib/libfoo.dylib", Targets.at(1)); + File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", {Targets.at(0)}); + File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", {Targets.at(0)}, SymbolFlags::WeakDefined); - File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", AK_i386, + File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", {Targets.at(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.at(1)}); + File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", {Targets.at(1)}); File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1", - AK_x86_64); + {Targets.at(1)}); SmallString<4096> Buffer; raw_svector_ostream OS(Buffer); @@ -190,9 +199,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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) {