diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
commit | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch) | |
tree | 599ab169a01f1c86eda9adc774edaedde2f2db5b /lib/TextAPI | |
parent | 1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff) |
Notes
Diffstat (limited to 'lib/TextAPI')
-rw-r--r-- | lib/TextAPI/ELF/ELFStub.cpp | 7 | ||||
-rw-r--r-- | lib/TextAPI/ELF/TBEHandler.cpp | 7 | ||||
-rw-r--r-- | lib/TextAPI/MachO/Architecture.cpp | 77 | ||||
-rw-r--r-- | lib/TextAPI/MachO/ArchitectureSet.cpp | 69 | ||||
-rw-r--r-- | lib/TextAPI/MachO/InterfaceFile.cpp | 81 | ||||
-rw-r--r-- | lib/TextAPI/MachO/PackedVersion.cpp | 113 | ||||
-rw-r--r-- | lib/TextAPI/MachO/Symbol.cpp | 49 | ||||
-rw-r--r-- | lib/TextAPI/MachO/TextAPIContext.h | 33 | ||||
-rw-r--r-- | lib/TextAPI/MachO/TextStub.cpp | 660 | ||||
-rw-r--r-- | lib/TextAPI/MachO/TextStubCommon.cpp | 178 | ||||
-rw-r--r-- | lib/TextAPI/MachO/TextStubCommon.h | 81 |
11 files changed, 1347 insertions, 8 deletions
diff --git a/lib/TextAPI/ELF/ELFStub.cpp b/lib/TextAPI/ELF/ELFStub.cpp index 248a078a2404..f8463497093b 100644 --- a/lib/TextAPI/ELF/ELFStub.cpp +++ b/lib/TextAPI/ELF/ELFStub.cpp @@ -1,9 +1,8 @@ //===- ELFStub.cpp --------------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===-----------------------------------------------------------------------===/ diff --git a/lib/TextAPI/ELF/TBEHandler.cpp b/lib/TextAPI/ELF/TBEHandler.cpp index b621829d9358..cb597d8896e8 100644 --- a/lib/TextAPI/ELF/TBEHandler.cpp +++ b/lib/TextAPI/ELF/TBEHandler.cpp @@ -1,9 +1,8 @@ //===- TBEHandler.cpp -----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===-----------------------------------------------------------------------===/ diff --git a/lib/TextAPI/MachO/Architecture.cpp b/lib/TextAPI/MachO/Architecture.cpp new file mode 100644 index 000000000000..a66a982fa153 --- /dev/null +++ b/lib/TextAPI/MachO/Architecture.cpp @@ -0,0 +1,77 @@ +//===- Architecture.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implements the architecture helper functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TextAPI/MachO/Architecture.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/BinaryFormat/MachO.h" + +namespace llvm { +namespace MachO { + +Architecture getArchitectureFromCpuType(uint32_t CPUType, uint32_t CPUSubType) { +#define ARCHINFO(Arch, Type, Subtype) \ + if (CPUType == (Type) && \ + (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) == (Subtype)) \ + return AK_##Arch; +#include "llvm/TextAPI/MachO/Architecture.def" +#undef ARCHINFO + + return AK_unknown; +} + +Architecture getArchitectureFromName(StringRef Name) { + return StringSwitch<Architecture>(Name) +#define ARCHINFO(Arch, Type, Subtype) .Case(#Arch, AK_##Arch) +#include "llvm/TextAPI/MachO/Architecture.def" +#undef ARCHINFO + .Default(AK_unknown); +} + +StringRef getArchitectureName(Architecture Arch) { + switch (Arch) { +#define ARCHINFO(Arch, Type, Subtype) \ + case AK_##Arch: \ + return #Arch; +#include "llvm/TextAPI/MachO/Architecture.def" +#undef ARCHINFO + case AK_unknown: + return "unknown"; + } + + // Appease some compilers that cannot figure out that this is a fully covered + // switch statement. + return "unknown"; +} + +std::pair<uint32_t, uint32_t> getCPUTypeFromArchitecture(Architecture Arch) { + switch (Arch) { +#define ARCHINFO(Arch, Type, Subtype) \ + case AK_##Arch: \ + return std::make_pair(Type, Subtype); +#include "llvm/TextAPI/MachO/Architecture.def" +#undef ARCHINFO + case AK_unknown: + return std::make_pair(0, 0); + } + + // Appease some compilers that cannot figure out that this is a fully covered + // switch statement. + return std::make_pair(0, 0); +} + +raw_ostream &operator<<(raw_ostream &OS, Architecture Arch) { + OS << getArchitectureName(Arch); + return OS; +} + +} // end namespace MachO. +} // end namespace llvm. diff --git a/lib/TextAPI/MachO/ArchitectureSet.cpp b/lib/TextAPI/MachO/ArchitectureSet.cpp new file mode 100644 index 000000000000..c589671199b7 --- /dev/null +++ b/lib/TextAPI/MachO/ArchitectureSet.cpp @@ -0,0 +1,69 @@ +//===- ArchitectureSet.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implements the architecture set. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TextAPI/MachO/ArchitectureSet.h" + +namespace llvm { +namespace MachO { + +ArchitectureSet::ArchitectureSet(const std::vector<Architecture> &Archs) + : ArchitectureSet() { + for (auto Arch : Archs) { + if (Arch == AK_unknown) + continue; + set(Arch); + } +} + +size_t ArchitectureSet::count() const { + // popcnt + size_t Cnt = 0; + for (unsigned i = 0; i < sizeof(ArchSetType) * 8; ++i) + if (ArchSet & (1U << i)) + ++Cnt; + return Cnt; +} + +ArchitectureSet::operator std::string() const { + if (empty()) + return "[(empty)]"; + + std::string result; + auto size = count(); + for (auto arch : *this) { + result.append(getArchitectureName(arch)); + size -= 1; + if (size) + result.append(" "); + } + return result; +} + +ArchitectureSet::operator std::vector<Architecture>() const { + std::vector<Architecture> archs; + for (auto arch : *this) { + if (arch == AK_unknown) + continue; + archs.emplace_back(arch); + } + return archs; +} + +void ArchitectureSet::print(raw_ostream &os) const { os << std::string(*this); } + +raw_ostream &operator<<(raw_ostream &os, ArchitectureSet set) { + set.print(os); + return os; +} + +} // end namespace MachO. +} // end namespace llvm. diff --git a/lib/TextAPI/MachO/InterfaceFile.cpp b/lib/TextAPI/MachO/InterfaceFile.cpp new file mode 100644 index 000000000000..54ba8cc31267 --- /dev/null +++ b/lib/TextAPI/MachO/InterfaceFile.cpp @@ -0,0 +1,81 @@ +//===- InterfaceFile.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implements the Interface File. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TextAPI/MachO/InterfaceFile.h" +#include <iomanip> +#include <sstream> + +namespace llvm { +namespace MachO { +namespace detail { +template <typename C> +typename C::iterator addEntry(C &Container, StringRef InstallName) { + auto I = partition_point(Container, [=](const InterfaceFileRef &O) { + return O.getInstallName() < InstallName; + }); + if (I != Container.end() && I->getInstallName() == InstallName) + return I; + + return Container.emplace(I, InstallName); +} +} // end namespace detail. + +void InterfaceFile::addAllowableClient(StringRef Name, + ArchitectureSet Architectures) { + auto Client = detail::addEntry(AllowableClients, Name); + Client->addArchitectures(Architectures); +} + +void InterfaceFile::addReexportedLibrary(StringRef InstallName, + ArchitectureSet Architectures) { + auto Lib = detail::addEntry(ReexportedLibraries, InstallName); + Lib->addArchitectures(Architectures); +} + +void InterfaceFile::addUUID(Architecture Arch, StringRef UUID) { + auto I = partition_point(UUIDs, + [=](const std::pair<Architecture, std::string> &O) { + return O.first < Arch; + }); + + if (I != UUIDs.end() && Arch == I->first) { + I->second = UUID; + return; + } + + UUIDs.emplace(I, Arch, UUID); + return; +} + +void InterfaceFile::addUUID(Architecture Arch, 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()); +} + +void InterfaceFile::addSymbol(SymbolKind Kind, StringRef Name, + ArchitectureSet Archs, 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}; + else + result.first->second->addArchitectures(Archs); +} + +} // end namespace MachO. +} // end namespace llvm. diff --git a/lib/TextAPI/MachO/PackedVersion.cpp b/lib/TextAPI/MachO/PackedVersion.cpp new file mode 100644 index 000000000000..8405aba90ed6 --- /dev/null +++ b/lib/TextAPI/MachO/PackedVersion.cpp @@ -0,0 +1,113 @@ +//===- PackedVersion.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implements the Mach-O packed version. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TextAPI/MachO/PackedVersion.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace MachO { + +bool PackedVersion::parse32(StringRef Str) { + Version = 0; + + if (Str.empty()) + return false; + + SmallVector<StringRef, 3> Parts; + SplitString(Str, Parts, "."); + + if (Parts.size() > 3) + return false; + + unsigned long long Num; + if (getAsUnsignedInteger(Parts[0], 10, Num)) + return false; + + if (Num > UINT16_MAX) + return false; + + Version = Num << 16; + + for (unsigned i = 1, ShiftNum = 8; i < Parts.size(); ++i, ShiftNum -= 8) { + if (getAsUnsignedInteger(Parts[i], 10, Num)) + return false; + + if (Num > UINT8_MAX) + return false; + + Version |= (Num << ShiftNum); + } + + return true; +} + +std::pair<bool, bool> PackedVersion::parse64(StringRef Str) { + bool Truncated = false; + Version = 0; + + if (Str.empty()) + return std::make_pair(false, Truncated); + + SmallVector<StringRef, 5> Parts; + SplitString(Str, Parts, "."); + + if (Parts.size() > 5) + return std::make_pair(false, Truncated); + + unsigned long long Num; + if (getAsUnsignedInteger(Parts[0], 10, Num)) + return std::make_pair(false, Truncated); + + if (Num > 0xFFFFFFULL) + return std::make_pair(false, Truncated); + + if (Num > 0xFFFFULL) { + Num = 0xFFFFULL; + Truncated = true; + } + Version = Num << 16; + + for (unsigned i = 1, ShiftNum = 8; i < Parts.size() && i < 3; + ++i, ShiftNum -= 8) { + if (getAsUnsignedInteger(Parts[i], 10, Num)) + return std::make_pair(false, Truncated); + + if (Num > 0x3FFULL) + return std::make_pair(false, Truncated); + + if (Num > 0xFFULL) { + Num = 0xFFULL; + Truncated = true; + } + Version |= (Num << ShiftNum); + } + + if (Parts.size() > 3) + Truncated = true; + + return std::make_pair(true, Truncated); +} + +void PackedVersion::print(raw_ostream &OS) const { + OS << format("%d", getMajor()); + if (getMinor() || getSubminor()) + OS << format(".%d", getMinor()); + if (getSubminor()) + OS << format(".%d", getSubminor()); +} + +} // end namespace MachO. +} // end namespace llvm. diff --git a/lib/TextAPI/MachO/Symbol.cpp b/lib/TextAPI/MachO/Symbol.cpp new file mode 100644 index 000000000000..731b264f6082 --- /dev/null +++ b/lib/TextAPI/MachO/Symbol.cpp @@ -0,0 +1,49 @@ +//===- Symbol.cpp ---------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implements the Symbol. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TextAPI/MachO/Symbol.h" +#include <string> + +namespace llvm { +namespace MachO { + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void Symbol::dump(raw_ostream &OS) const { + std::string Result; + if (isUndefined()) + Result += "(undef) "; + if (isWeakDefined()) + Result += "(weak-def) "; + if (isWeakReferenced()) + Result += "(weak-ref) "; + if (isThreadLocalValue()) + Result += "(tlv) "; + switch (Kind) { + case SymbolKind::GlobalSymbol: + Result += Name.str(); + break; + case SymbolKind::ObjectiveCClass: + Result += "(ObjC Class) " + Name.str(); + break; + case SymbolKind::ObjectiveCClassEHType: + Result += "(ObjC Class EH) " + Name.str(); + break; + case SymbolKind::ObjectiveCInstanceVariable: + Result += "(ObjC IVar) " + Name.str(); + break; + } + OS << Result; +} +#endif + +} // end namespace MachO. +} // end namespace llvm. diff --git a/lib/TextAPI/MachO/TextAPIContext.h b/lib/TextAPI/MachO/TextAPIContext.h new file mode 100644 index 000000000000..3df40f09f7f7 --- /dev/null +++ b/lib/TextAPI/MachO/TextAPIContext.h @@ -0,0 +1,33 @@ +//===- TextAPIContext.h ---------------------------------------------------===// +// +// 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 YAML Context for the TextAPI Reader/Writer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TEXTAPI_MACHO_CONTEXT_H +#define LLVM_TEXTAPI_MACHO_CONTEXT_H + +#include "llvm/Support/MemoryBuffer.h" +#include <string> + +namespace llvm { +namespace MachO { + +enum FileType : unsigned; + +struct TextAPIContext { + std::string ErrorMessage; + std::string Path; + FileType FileKind; +}; + +} // end namespace MachO. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_MACHO_CONTEXT_H diff --git a/lib/TextAPI/MachO/TextStub.cpp b/lib/TextAPI/MachO/TextStub.cpp new file mode 100644 index 000000000000..799ebdc883ab --- /dev/null +++ b/lib/TextAPI/MachO/TextStub.cpp @@ -0,0 +1,660 @@ +//===- TextStub.cpp -------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implements the text stub file reader/writer. +// +//===----------------------------------------------------------------------===// + +#include "TextAPIContext.h" +#include "TextStubCommon.h" +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TextAPI/MachO/Architecture.h" +#include "llvm/TextAPI/MachO/ArchitectureSet.h" +#include "llvm/TextAPI/MachO/InterfaceFile.h" +#include "llvm/TextAPI/MachO/PackedVersion.h" +#include "llvm/TextAPI/MachO/TextAPIReader.h" +#include "llvm/TextAPI/MachO/TextAPIWriter.h" +#include <algorithm> +#include <set> + +// clang-format off +/* + + YAML Format specification. + + The TBD v1 format only support two level address libraries and is per + definition application extension safe. + +--- # the tag !tapi-tbd-v1 is optional and + # shouldn't be emitted to support older linker. +archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are + # supported by this file. +platform: ios # Specifies the platform (macosx, ios, etc) +install-name: /u/l/libfoo.dylib # +current-version: 1.2.3 # Optional: defaults to 1.0 +compatibility-version: 1.0 # Optional: defaults to 1.0 +swift-version: 0 # Optional: defaults to 0 +objc-constraint: none # Optional: defaults to none +exports: # List of export sections +... + +Each export section is defined as following: + + - archs: [ arm64 ] # the list of architecture slices + allowed-clients: [ client ] # Optional: List of clients + re-exports: [ ] # Optional: List of re-exports + symbols: [ _sym ] # Optional: List of symbols + objc-classes: [] # Optional: List of Objective-C classes + objc-ivars: [] # Optional: List of Objective C Instance + # Variables + weak-def-symbols: [] # Optional: List of weak defined symbols + thread-local-symbols: [] # Optional: List of thread local symbols +*/ + +/* + + YAML Format specification. + +--- !tapi-tbd-v2 +archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are + # supported by this file. +uuids: [ armv7:... ] # Optional: List of architecture and UUID pairs. +platform: ios # Specifies the platform (macosx, ios, etc) +flags: [] # Optional: +install-name: /u/l/libfoo.dylib # +current-version: 1.2.3 # Optional: defaults to 1.0 +compatibility-version: 1.0 # Optional: defaults to 1.0 +swift-version: 0 # Optional: defaults to 0 +objc-constraint: retain_release # Optional: defaults to retain_release +parent-umbrella: # Optional: +exports: # List of export sections +... +undefineds: # List of undefineds sections +... + +Each export section is defined as following: + +- archs: [ arm64 ] # the list of architecture slices + allowed-clients: [ client ] # Optional: List of clients + re-exports: [ ] # Optional: List of re-exports + symbols: [ _sym ] # Optional: List of symbols + objc-classes: [] # Optional: List of Objective-C classes + objc-ivars: [] # Optional: List of Objective C Instance + # Variables + weak-def-symbols: [] # Optional: List of weak defined symbols + thread-local-symbols: [] # Optional: List of thread local symbols + +Each undefineds section is defined as following: +- archs: [ arm64 ] # the list of architecture slices + symbols: [ _sym ] # Optional: List of symbols + objc-classes: [] # Optional: List of Objective-C classes + objc-ivars: [] # Optional: List of Objective C Instance Variables + weak-ref-symbols: [] # Optional: List of weak defined symbols +*/ + +/* + + YAML Format specification. + +--- !tapi-tbd-v3 +archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are + # supported by this file. +uuids: [ armv7:... ] # Optional: List of architecture and UUID pairs. +platform: ios # Specifies the platform (macosx, ios, etc) +flags: [] # Optional: +install-name: /u/l/libfoo.dylib # +current-version: 1.2.3 # Optional: defaults to 1.0 +compatibility-version: 1.0 # Optional: defaults to 1.0 +swift-abi-version: 0 # Optional: defaults to 0 +objc-constraint: retain_release # Optional: defaults to retain_release +parent-umbrella: # Optional: +exports: # List of export sections +... +undefineds: # List of undefineds sections +... + +Each export section is defined as following: + +- archs: [ arm64 ] # the list of architecture slices + allowed-clients: [ client ] # Optional: List of clients + re-exports: [ ] # Optional: List of re-exports + symbols: [ _sym ] # Optional: List of symbols + objc-classes: [] # Optional: List of Objective-C classes + objc-eh-types: [] # Optional: List of Objective-C classes + # with EH + objc-ivars: [] # Optional: List of Objective C Instance + # Variables + weak-def-symbols: [] # Optional: List of weak defined symbols + thread-local-symbols: [] # Optional: List of thread local symbols + +Each undefineds section is defined as following: +- archs: [ arm64 ] # the list of architecture slices + symbols: [ _sym ] # Optional: List of symbols + objc-classes: [] # Optional: List of Objective-C classes + objc-eh-types: [] # Optional: List of Objective-C classes + # with EH + objc-ivars: [] # Optional: List of Objective C Instance Variables + weak-ref-symbols: [] # Optional: List of weak defined symbols +*/ +// clang-format on + +using namespace llvm; +using namespace llvm::yaml; +using namespace llvm::MachO; + +namespace { +struct ExportSection { + std::vector<Architecture> Architectures; + std::vector<FlowStringRef> AllowableClients; + std::vector<FlowStringRef> ReexportedLibraries; + std::vector<FlowStringRef> Symbols; + std::vector<FlowStringRef> Classes; + std::vector<FlowStringRef> ClassEHs; + std::vector<FlowStringRef> IVars; + std::vector<FlowStringRef> WeakDefSymbols; + std::vector<FlowStringRef> TLVSymbols; +}; + +struct UndefinedSection { + std::vector<Architecture> Architectures; + std::vector<FlowStringRef> Symbols; + std::vector<FlowStringRef> Classes; + std::vector<FlowStringRef> ClassEHs; + std::vector<FlowStringRef> IVars; + std::vector<FlowStringRef> WeakRefSymbols; +}; + +// clang-format off +enum TBDFlags : unsigned { + None = 0U, + FlatNamespace = 1U << 0, + NotApplicationExtensionSafe = 1U << 1, + InstallAPI = 1U << 2, + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI), +}; +// clang-format on +} // end anonymous namespace. + +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture) +LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection) +LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection) + +namespace llvm { +namespace yaml { + +template <> struct MappingTraits<ExportSection> { + static void mapping(IO &IO, ExportSection &Section) { + const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext()); + assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) && + "File type is not set in YAML context"); + + IO.mapRequired("archs", Section.Architectures); + if (Ctx->FileKind == FileType::TBD_V1) + IO.mapOptional("allowed-clients", Section.AllowableClients); + else + IO.mapOptional("allowable-clients", Section.AllowableClients); + IO.mapOptional("re-exports", Section.ReexportedLibraries); + IO.mapOptional("symbols", Section.Symbols); + IO.mapOptional("objc-classes", Section.Classes); + if (Ctx->FileKind == FileType::TBD_V3) + IO.mapOptional("objc-eh-types", Section.ClassEHs); + IO.mapOptional("objc-ivars", Section.IVars); + IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols); + IO.mapOptional("thread-local-symbols", Section.TLVSymbols); + } +}; + +template <> struct MappingTraits<UndefinedSection> { + static void mapping(IO &IO, UndefinedSection &Section) { + const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext()); + assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) && + "File type is not set in YAML context"); + + IO.mapRequired("archs", Section.Architectures); + IO.mapOptional("symbols", Section.Symbols); + IO.mapOptional("objc-classes", Section.Classes); + if (Ctx->FileKind == FileType::TBD_V3) + IO.mapOptional("objc-eh-types", Section.ClassEHs); + IO.mapOptional("objc-ivars", Section.IVars); + IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols); + } +}; + +template <> struct ScalarBitSetTraits<TBDFlags> { + static void bitset(IO &IO, TBDFlags &Flags) { + IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace); + IO.bitSetCase(Flags, "not_app_extension_safe", + TBDFlags::NotApplicationExtensionSafe); + IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI); + } +}; + +template <> struct MappingTraits<const InterfaceFile *> { + struct NormalizedTBD { + explicit NormalizedTBD(IO &IO) {} + NormalizedTBD(IO &IO, const InterfaceFile *&File) { + Architectures = File->getArchitectures(); + UUIDs = File->uuids(); + Platform = File->getPlatform(); + InstallName = File->getInstallName(); + CurrentVersion = PackedVersion(File->getCurrentVersion()); + CompatibilityVersion = PackedVersion(File->getCompatibilityVersion()); + SwiftABIVersion = File->getSwiftABIVersion(); + ObjCConstraint = File->getObjCConstraint(); + + Flags = TBDFlags::None; + if (!File->isApplicationExtensionSafe()) + Flags |= TBDFlags::NotApplicationExtensionSafe; + + if (!File->isTwoLevelNamespace()) + Flags |= TBDFlags::FlatNamespace; + + if (File->isInstallAPI()) + Flags |= TBDFlags::InstallAPI; + + ParentUmbrella = File->getParentUmbrella(); + + std::set<ArchitectureSet> ArchSet; + for (const auto &Library : File->allowableClients()) + ArchSet.insert(Library.getArchitectures()); + + for (const auto &Library : File->reexportedLibraries()) + ArchSet.insert(Library.getArchitectures()); + + std::map<const Symbol *, ArchitectureSet> SymbolToArchSet; + for (const auto *Symbol : File->exports()) { + auto Architectures = Symbol->getArchitectures(); + SymbolToArchSet[Symbol] = Architectures; + ArchSet.insert(Architectures); + } + + for (auto Architectures : ArchSet) { + ExportSection Section; + Section.Architectures = Architectures; + + for (const auto &Library : File->allowableClients()) + if (Library.getArchitectures() == Architectures) + Section.AllowableClients.emplace_back(Library.getInstallName()); + + for (const auto &Library : File->reexportedLibraries()) + if (Library.getArchitectures() == Architectures) + Section.ReexportedLibraries.emplace_back(Library.getInstallName()); + + for (const auto &SymArch : SymbolToArchSet) { + if (SymArch.second != Architectures) + continue; + + const auto *Symbol = SymArch.first; + switch (Symbol->getKind()) { + case SymbolKind::GlobalSymbol: + if (Symbol->isWeakDefined()) + Section.WeakDefSymbols.emplace_back(Symbol->getName()); + else if (Symbol->isThreadLocalValue()) + Section.TLVSymbols.emplace_back(Symbol->getName()); + else + Section.Symbols.emplace_back(Symbol->getName()); + break; + case SymbolKind::ObjectiveCClass: + if (File->getFileType() != FileType::TBD_V3) + Section.Classes.emplace_back( + copyString("_" + Symbol->getName().str())); + else + Section.Classes.emplace_back(Symbol->getName()); + break; + case SymbolKind::ObjectiveCClassEHType: + if (File->getFileType() != FileType::TBD_V3) + Section.Symbols.emplace_back( + copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str())); + else + Section.ClassEHs.emplace_back(Symbol->getName()); + break; + case SymbolKind::ObjectiveCInstanceVariable: + if (File->getFileType() != FileType::TBD_V3) + Section.IVars.emplace_back( + copyString("_" + Symbol->getName().str())); + else + Section.IVars.emplace_back(Symbol->getName()); + break; + } + } + llvm::sort(Section.Symbols.begin(), Section.Symbols.end()); + llvm::sort(Section.Classes.begin(), Section.Classes.end()); + llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end()); + llvm::sort(Section.IVars.begin(), Section.IVars.end()); + llvm::sort(Section.WeakDefSymbols.begin(), + Section.WeakDefSymbols.end()); + llvm::sort(Section.TLVSymbols.begin(), Section.TLVSymbols.end()); + Exports.emplace_back(std::move(Section)); + } + + ArchSet.clear(); + SymbolToArchSet.clear(); + + for (const auto *Symbol : File->undefineds()) { + auto Architectures = Symbol->getArchitectures(); + SymbolToArchSet[Symbol] = Architectures; + ArchSet.insert(Architectures); + } + + for (auto Architectures : ArchSet) { + UndefinedSection Section; + Section.Architectures = Architectures; + + for (const auto &SymArch : SymbolToArchSet) { + if (SymArch.second != Architectures) + continue; + + const auto *Symbol = SymArch.first; + switch (Symbol->getKind()) { + case SymbolKind::GlobalSymbol: + if (Symbol->isWeakReferenced()) + Section.WeakRefSymbols.emplace_back(Symbol->getName()); + else + Section.Symbols.emplace_back(Symbol->getName()); + break; + case SymbolKind::ObjectiveCClass: + if (File->getFileType() != FileType::TBD_V3) + Section.Classes.emplace_back( + copyString("_" + Symbol->getName().str())); + else + Section.Classes.emplace_back(Symbol->getName()); + break; + case SymbolKind::ObjectiveCClassEHType: + if (File->getFileType() != FileType::TBD_V3) + Section.Symbols.emplace_back( + copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str())); + else + Section.ClassEHs.emplace_back(Symbol->getName()); + break; + case SymbolKind::ObjectiveCInstanceVariable: + if (File->getFileType() != FileType::TBD_V3) + Section.IVars.emplace_back( + copyString("_" + Symbol->getName().str())); + else + Section.IVars.emplace_back(Symbol->getName()); + break; + } + } + llvm::sort(Section.Symbols.begin(), Section.Symbols.end()); + llvm::sort(Section.Classes.begin(), Section.Classes.end()); + llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end()); + llvm::sort(Section.IVars.begin(), Section.IVars.end()); + llvm::sort(Section.WeakRefSymbols.begin(), + Section.WeakRefSymbols.end()); + Undefineds.emplace_back(std::move(Section)); + } + } + + 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); + 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); + + if (Ctx->FileKind == FileType::TBD_V1) { + File->setTwoLevelNamespace(); + File->setApplicationExtensionSafe(); + } else { + File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace)); + File->setApplicationExtensionSafe( + !(Flags & TBDFlags::NotApplicationExtensionSafe)); + File->setInstallAPI(Flags & TBDFlags::InstallAPI); + } + + 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); + + 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); + else + File->addSymbol(SymbolKind::GlobalSymbol, Symbol, + Section.Architectures); + } + 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); + } + for (auto &Symbol : Section.ClassEHs) + File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, + Section.Architectures); + 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); + } + for (auto &Symbol : Section.WeakDefSymbols) + File->addSymbol(SymbolKind::GlobalSymbol, Symbol, + Section.Architectures, SymbolFlags::WeakDefined); + for (auto &Symbol : Section.TLVSymbols) + File->addSymbol(SymbolKind::GlobalSymbol, Symbol, + Section.Architectures, SymbolFlags::ThreadLocalValue); + } + + for (const auto &Section : Undefineds) { + 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, + SymbolFlags::Undefined); + else + File->addSymbol(SymbolKind::GlobalSymbol, Symbol, + Section.Architectures, 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); + } + for (auto &Symbol : Section.ClassEHs) + File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, + Section.Architectures, 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); + } + for (auto &Symbol : Section.WeakRefSymbols) + File->addSymbol(SymbolKind::GlobalSymbol, Symbol, + Section.Architectures, + SymbolFlags::Undefined | SymbolFlags::WeakReferenced); + } + + return File; + } + + llvm::BumpPtrAllocator Allocator; + StringRef copyString(StringRef String) { + if (String.empty()) + return {}; + + void *Ptr = Allocator.Allocate(String.size(), 1); + memcpy(Ptr, String.data(), String.size()); + return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); + } + + std::vector<Architecture> Architectures; + std::vector<UUID> UUIDs; + PlatformKind Platform{PlatformKind::unknown}; + StringRef InstallName; + PackedVersion CurrentVersion; + PackedVersion CompatibilityVersion; + SwiftVersion SwiftABIVersion{0}; + ObjCConstraintType ObjCConstraint{ObjCConstraintType::None}; + TBDFlags Flags{TBDFlags::None}; + StringRef ParentUmbrella; + std::vector<ExportSection> Exports; + std::vector<UndefinedSection> Undefineds; + }; + + static void mapping(IO &IO, const InterfaceFile *&File) { + auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext()); + assert((!Ctx || !IO.outputting() || + (Ctx && Ctx->FileKind != FileType::Invalid)) && + "File type is not set in YAML context"); + MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File); + + // prope file type when reading. + if (!IO.outputting()) { + if (IO.mapTag("!tapi-tbd-v2", false)) + Ctx->FileKind = FileType::TBD_V2; + else if (IO.mapTag("!tapi-tbd-v3", false)) + Ctx->FileKind = FileType::TBD_V2; + else if (IO.mapTag("!tapi-tbd-v1", false) || + IO.mapTag("tag:yaml.org,2002:map", false)) + Ctx->FileKind = FileType::TBD_V1; + else { + IO.setError("unsupported file type"); + return; + } + } + + // Set file tyoe when writing. + if (IO.outputting()) { + switch (Ctx->FileKind) { + default: + llvm_unreachable("unexpected file type"); + case FileType::TBD_V1: + // Don't write the tag into the .tbd file for TBD v1. + break; + case FileType::TBD_V2: + IO.mapTag("!tapi-tbd-v2", true); + break; + case FileType::TBD_V3: + IO.mapTag("!tapi-tbd-v3", true); + break; + } + } + + IO.mapRequired("archs", Keys->Architectures); + if (Ctx->FileKind != FileType::TBD_V1) + IO.mapOptional("uuids", Keys->UUIDs); + IO.mapRequired("platform", Keys->Platform); + if (Ctx->FileKind != FileType::TBD_V1) + IO.mapOptional("flags", Keys->Flags, TBDFlags::None); + IO.mapRequired("install-name", Keys->InstallName); + IO.mapOptional("current-version", Keys->CurrentVersion, + PackedVersion(1, 0, 0)); + IO.mapOptional("compatibility-version", Keys->CompatibilityVersion, + PackedVersion(1, 0, 0)); + if (Ctx->FileKind != FileType::TBD_V3) + IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0)); + else + IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, + SwiftVersion(0)); + IO.mapOptional("objc-constraint", Keys->ObjCConstraint, + (Ctx->FileKind == FileType::TBD_V1) + ? ObjCConstraintType::None + : ObjCConstraintType::Retain_Release); + if (Ctx->FileKind != FileType::TBD_V1) + IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef()); + IO.mapOptional("exports", Keys->Exports); + if (Ctx->FileKind != FileType::TBD_V1) + IO.mapOptional("undefineds", Keys->Undefineds); + } +}; + +template <> +struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> { + static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) { + return Seq.size(); + } + static const InterfaceFile *& + element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) { + if (Index >= Seq.size()) + Seq.resize(Index + 1); + return Seq[Index]; + } +}; + +} // end namespace yaml. + +namespace MachO { +static void DiagHandler(const SMDiagnostic &Diag, void *Context) { + auto *File = static_cast<TextAPIContext *>(Context); + SmallString<1024> Message; + raw_svector_ostream S(Message); + + SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path, + Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(), + Diag.getMessage(), Diag.getLineContents(), + Diag.getRanges(), Diag.getFixIts()); + + NewDiag.print(nullptr, S); + File->ErrorMessage = ("malformed file\n" + Message).str(); +} + +Expected<std::unique_ptr<InterfaceFile>> +TextAPIReader::get(std::unique_ptr<MemoryBuffer> InputBuffer) { + TextAPIContext Ctx; + Ctx.Path = InputBuffer->getBufferIdentifier(); + yaml::Input YAMLIn(InputBuffer->getBuffer(), &Ctx, DiagHandler, &Ctx); + + // Fill vector with interface file objects created by parsing the YAML file. + std::vector<const InterfaceFile *> Files; + YAMLIn >> Files; + + auto File = std::unique_ptr<InterfaceFile>( + const_cast<InterfaceFile *>(Files.front())); + + if (YAMLIn.error()) + return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error()); + + return std::move(File); +} + +Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) { + TextAPIContext Ctx; + Ctx.Path = File.getPath(); + Ctx.FileKind = File.getFileType(); + llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80); + + std::vector<const InterfaceFile *> Files; + Files.emplace_back(&File); + + // Stream out yaml. + YAMLOut << Files; + + return Error::success(); +} + +} // end namespace MachO. +} // end namespace llvm. diff --git a/lib/TextAPI/MachO/TextStubCommon.cpp b/lib/TextAPI/MachO/TextStubCommon.cpp new file mode 100644 index 000000000000..00382cd24573 --- /dev/null +++ b/lib/TextAPI/MachO/TextStubCommon.cpp @@ -0,0 +1,178 @@ +//===- TextStubCommon.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implememts common Text Stub YAML mappings. +// +//===----------------------------------------------------------------------===// + +#include "TextStubCommon.h" +#include "TextAPIContext.h" + +using namespace llvm::MachO; + +namespace llvm { +namespace yaml { + +void ScalarTraits<FlowStringRef>::output(const FlowStringRef &Value, void *Ctx, + raw_ostream &OS) { + ScalarTraits<StringRef>::output(Value, Ctx, OS); +} +StringRef ScalarTraits<FlowStringRef>::input(StringRef Value, void *Ctx, + FlowStringRef &Out) { + return ScalarTraits<StringRef>::input(Value, Ctx, Out.value); +} +QuotingType ScalarTraits<FlowStringRef>::mustQuote(StringRef Name) { + return ScalarTraits<StringRef>::mustQuote(Name); +} + +void ScalarEnumerationTraits<ObjCConstraintType>::enumeration( + IO &IO, ObjCConstraintType &Constraint) { + IO.enumCase(Constraint, "none", ObjCConstraintType::None); + IO.enumCase(Constraint, "retain_release", ObjCConstraintType::Retain_Release); + IO.enumCase(Constraint, "retain_release_for_simulator", + ObjCConstraintType::Retain_Release_For_Simulator); + IO.enumCase(Constraint, "retain_release_or_gc", + ObjCConstraintType::Retain_Release_Or_GC); + IO.enumCase(Constraint, "gc", ObjCConstraintType::GC); +} + +void ScalarTraits<PlatformKind>::output(const PlatformKind &Value, void *, + raw_ostream &OS) { + switch (Value) { + default: + llvm_unreachable("unexpected platform"); + break; + case PlatformKind::macOS: + OS << "macosx"; + break; + case PlatformKind::iOS: + OS << "ios"; + break; + case PlatformKind::watchOS: + OS << "watchos"; + break; + case PlatformKind::tvOS: + OS << "tvos"; + break; + case PlatformKind::bridgeOS: + OS << "bridgeos"; + 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) + return "unknown platform"; + return {}; +} +QuotingType ScalarTraits<PlatformKind>::mustQuote(StringRef) { + return QuotingType::None; +} + +void ScalarBitSetTraits<ArchitectureSet>::bitset(IO &IO, + ArchitectureSet &Archs) { +#define ARCHINFO(arch, type, subtype) \ + IO.bitSetCase(Archs, #arch, 1U << static_cast<int>(AK_##arch)); +#include "llvm/TextAPI/MachO/Architecture.def" +#undef ARCHINFO +} + +void ScalarTraits<Architecture>::output(const Architecture &Value, void *, + raw_ostream &OS) { + OS << Value; +} +StringRef ScalarTraits<Architecture>::input(StringRef Scalar, void *, + Architecture &Value) { + Value = getArchitectureFromName(Scalar); + return {}; +} +QuotingType ScalarTraits<Architecture>::mustQuote(StringRef) { + return QuotingType::None; +} + +void ScalarTraits<PackedVersion>::output(const PackedVersion &Value, void *, + raw_ostream &OS) { + OS << Value; +} +StringRef ScalarTraits<PackedVersion>::input(StringRef Scalar, void *, + PackedVersion &Value) { + if (!Value.parse32(Scalar)) + return "invalid packed version string."; + return {}; +} +QuotingType ScalarTraits<PackedVersion>::mustQuote(StringRef) { + return QuotingType::None; +} + +void ScalarTraits<SwiftVersion>::output(const SwiftVersion &Value, void *, + raw_ostream &OS) { + switch (Value) { + case 1: + OS << "1.0"; + break; + case 2: + OS << "1.1"; + break; + case 3: + OS << "2.0"; + break; + case 4: + OS << "3.0"; + break; + default: + OS << (unsigned)Value; + break; + } +} +StringRef ScalarTraits<SwiftVersion>::input(StringRef Scalar, void *, + SwiftVersion &Value) { + Value = StringSwitch<SwiftVersion>(Scalar) + .Case("1.0", 1) + .Case("1.1", 2) + .Case("2.0", 3) + .Case("3.0", 4) + .Default(0); + if (Value != SwiftVersion(0)) + return {}; + + if (Scalar.getAsInteger(10, Value)) + return "invalid Swift ABI version."; + + return StringRef(); +} +QuotingType ScalarTraits<SwiftVersion>::mustQuote(StringRef) { + return QuotingType::None; +} + +void ScalarTraits<UUID>::output(const UUID &Value, void *, raw_ostream &OS) { + OS << Value.first << ": " << Value.second; +} +StringRef ScalarTraits<UUID>::input(StringRef Scalar, void *, UUID &Value) { + auto Split = Scalar.split(':'); + auto Arch = Split.first.trim(); + auto UUID = Split.second.trim(); + if (UUID.empty()) + return "invalid uuid string pair"; + Value.first = getArchitectureFromName(Arch); + Value.second = UUID; + return {}; +} +QuotingType ScalarTraits<UUID>::mustQuote(StringRef) { + return QuotingType::Single; +} + +} // end namespace yaml. +} // end namespace llvm. diff --git a/lib/TextAPI/MachO/TextStubCommon.h b/lib/TextAPI/MachO/TextStubCommon.h new file mode 100644 index 000000000000..c4dd1075b1c8 --- /dev/null +++ b/lib/TextAPI/MachO/TextStubCommon.h @@ -0,0 +1,81 @@ +//===- TextStubCommon.h ---------------------------------------------------===// +// +// 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 common Text Stub YAML mappings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TEXTAPI_TEXT_STUB_COMMON_H +#define LLVM_TEXTAPI_TEXT_STUB_COMMON_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/TextAPI/MachO/Architecture.h" +#include "llvm/TextAPI/MachO/ArchitectureSet.h" +#include "llvm/TextAPI/MachO/InterfaceFile.h" +#include "llvm/TextAPI/MachO/PackedVersion.h" + +using UUID = std::pair<llvm::MachO::Architecture, std::string>; + +LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, FlowStringRef) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, SwiftVersion) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(UUID) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowStringRef) + +namespace llvm { +namespace yaml { + +template <> struct ScalarTraits<FlowStringRef> { + static void output(const FlowStringRef &, void *, raw_ostream &); + static StringRef input(StringRef, void *, FlowStringRef &); + static QuotingType mustQuote(StringRef); +}; + +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 &); + static QuotingType mustQuote(StringRef); +}; + +template <> struct ScalarBitSetTraits<MachO::ArchitectureSet> { + static void bitset(IO &, MachO::ArchitectureSet &); +}; + +template <> struct ScalarTraits<MachO::Architecture> { + static void output(const MachO::Architecture &, void *, raw_ostream &); + static StringRef input(StringRef, void *, MachO::Architecture &); + static QuotingType mustQuote(StringRef); +}; + +template <> struct ScalarTraits<MachO::PackedVersion> { + static void output(const MachO::PackedVersion &, void *, raw_ostream &); + static StringRef input(StringRef, void *, MachO::PackedVersion &); + static QuotingType mustQuote(StringRef); +}; + +template <> struct ScalarTraits<SwiftVersion> { + static void output(const SwiftVersion &, void *, raw_ostream &); + static StringRef input(StringRef, void *, SwiftVersion &); + static QuotingType mustQuote(StringRef); +}; + +template <> struct ScalarTraits<UUID> { + static void output(const UUID &, void *, raw_ostream &); + static StringRef input(StringRef, void *, UUID &); + static QuotingType mustQuote(StringRef); +}; + +} // end namespace yaml. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_TEXT_STUB_COMMON_H |