| //===- tapi/Core/TextStub_v3.cpp - Text Stub v3 -----------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// \brief Implements the text stub file (TBD v3) reader/writer. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "TextStub_v3.h" |
| #include "ArchitectureSupport.h" |
| #include "InterfaceFile.h" |
| #include "Registry.h" |
| #include "YAML.h" |
| #include "YAMLReaderWriter.h" |
| #include "LinkerInterfaceFile.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/YAMLTraits.h" |
| #include <set> |
| |
| using namespace llvm; |
| using namespace llvm::yaml; |
| using namespace TAPI_INTERNAL; |
| |
| namespace { |
| |
| struct ExportSection { |
| std::vector<Architecture> archs; |
| 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> archs; |
| std::vector<FlowStringRef> symbols; |
| std::vector<FlowStringRef> classes; |
| std::vector<FlowStringRef> classEHs; |
| std::vector<FlowStringRef> ivars; |
| std::vector<FlowStringRef> weakRefSymbols; |
| }; |
| |
| enum Flags : unsigned { |
| None = 0U, |
| FlatNamespace = 1U << 0, |
| NotApplicationExtensionSafe = 1U << 1, |
| InstallAPI = 1U << 2, |
| }; |
| |
| inline Flags operator|(const Flags a, const Flags b) { |
| return static_cast<Flags>(static_cast<unsigned>(a) | |
| static_cast<unsigned>(b)); |
| } |
| |
| inline Flags operator|=(Flags &a, const Flags b) { |
| a = static_cast<Flags>(static_cast<unsigned>(a) | static_cast<unsigned>(b)); |
| return a; |
| } |
| |
| } // 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 §ion) { |
| io.mapRequired("archs", section.archs); |
| io.mapOptional("allowable-clients", section.allowableClients); |
| io.mapOptional("re-exports", section.reexportedLibraries); |
| io.mapOptional("symbols", section.symbols); |
| io.mapOptional("objc-classes", section.classes); |
| 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 §ion) { |
| io.mapRequired("archs", section.archs); |
| io.mapOptional("symbols", section.symbols); |
| io.mapOptional("objc-classes", section.classes); |
| io.mapOptional("objc-eh-types", section.classEHs); |
| io.mapOptional("objc-ivars", section.ivars); |
| io.mapOptional("weak-ref-symbols", section.weakRefSymbols); |
| } |
| }; |
| |
| template <> struct ScalarBitSetTraits<Flags> { |
| static void bitset(IO &io, Flags &flags) { |
| io.bitSetCase(flags, "flat_namespace", Flags::FlatNamespace); |
| io.bitSetCase(flags, "not_app_extension_safe", |
| Flags::NotApplicationExtensionSafe); |
| io.bitSetCase(flags, "installapi", Flags::InstallAPI); |
| } |
| }; |
| |
| template <> struct MappingTraits<const InterfaceFile *> { |
| struct NormalizedTBD3 { |
| explicit NormalizedTBD3(IO &io) {} |
| NormalizedTBD3(IO &io, const InterfaceFile *&file) { |
| archs = file->getArchitectures(); |
| uuids = file->uuids(); |
| platform = file->getPlatform(); |
| installName = file->getInstallName(); |
| currentVersion = file->getCurrentVersion(); |
| compatibilityVersion = file->getCompatibilityVersion(); |
| swiftABIVersion = file->getSwiftABIVersion(); |
| objcConstraint = file->getObjCConstraint(); |
| |
| flags = Flags::None; |
| if (!file->isApplicationExtensionSafe()) |
| flags |= Flags::NotApplicationExtensionSafe; |
| |
| if (!file->isTwoLevelNamespace()) |
| flags |= Flags::FlatNamespace; |
| |
| if (file->isInstallAPI()) |
| flags |= Flags::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 archs = symbol->getArchitectures(); |
| symbolToArchSet[symbol] = archs; |
| archSet.insert(archs); |
| } |
| |
| for (auto archs : archSet) { |
| ExportSection section; |
| section.archs = archs; |
| |
| for (const auto &library : file->allowableClients()) |
| if (library.getArchitectures() == archs) |
| section.allowableClients.emplace_back(library.getInstallName()); |
| |
| for (const auto &library : file->reexportedLibraries()) |
| if (library.getArchitectures() == archs) |
| section.reexportedLibraries.emplace_back(library.getInstallName()); |
| |
| for (const auto &symArch : symbolToArchSet) { |
| if (symArch.second != archs) |
| 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: |
| section.classes.emplace_back(symbol->getName()); |
| break; |
| case SymbolKind::ObjectiveCClassEHType: |
| section.classEHs.emplace_back(symbol->getName()); |
| break; |
| case SymbolKind::ObjectiveCInstanceVariable: |
| section.ivars.emplace_back(symbol->getName()); |
| break; |
| } |
| } |
| TAPI_INTERNAL::sort(section.symbols); |
| TAPI_INTERNAL::sort(section.classes); |
| TAPI_INTERNAL::sort(section.classEHs); |
| TAPI_INTERNAL::sort(section.ivars); |
| TAPI_INTERNAL::sort(section.weakDefSymbols); |
| TAPI_INTERNAL::sort(section.tlvSymbols); |
| exports.emplace_back(std::move(section)); |
| } |
| |
| archSet.clear(); |
| symbolToArchSet.clear(); |
| |
| for (const auto *symbol : file->undefineds()) { |
| auto archs = symbol->getArchitectures(); |
| symbolToArchSet[symbol] = archs; |
| archSet.insert(archs); |
| } |
| |
| for (auto archs : archSet) { |
| UndefinedSection section; |
| section.archs = archs; |
| |
| for (const auto &symArch : symbolToArchSet) { |
| if (symArch.second != archs) |
| 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: |
| section.classes.emplace_back(symbol->getName()); |
| break; |
| case SymbolKind::ObjectiveCClassEHType: |
| section.classEHs.emplace_back(symbol->getName()); |
| break; |
| case SymbolKind::ObjectiveCInstanceVariable: |
| section.ivars.emplace_back(symbol->getName()); |
| break; |
| } |
| } |
| TAPI_INTERNAL::sort(section.symbols); |
| TAPI_INTERNAL::sort(section.classes); |
| TAPI_INTERNAL::sort(section.classEHs); |
| TAPI_INTERNAL::sort(section.ivars); |
| TAPI_INTERNAL::sort(section.weakRefSymbols); |
| undefineds.emplace_back(std::move(section)); |
| } |
| } |
| |
| const InterfaceFile *denormalize(IO &io) { |
| auto ctx = reinterpret_cast<YAMLContext *>(io.getContext()); |
| assert(ctx); |
| |
| auto *file = new InterfaceFile; |
| file->setPath(ctx->path); |
| file->setFileType(TAPI_INTERNAL::FileType::TBD_V3); |
| for (auto &id : uuids) |
| file->addUUID(id.first, id.second); |
| file->setArchitectures(archs); |
| file->setPlatform(mapToSim(platform, file->getArchitectures().hasX86())); |
| file->setInstallName(installName); |
| file->setCurrentVersion(currentVersion); |
| file->setCompatibilityVersion(compatibilityVersion); |
| file->setSwiftABIVersion(swiftABIVersion); |
| file->setObjCConstraint(objcConstraint); |
| file->setParentUmbrella(parentUmbrella); |
| |
| file->setTwoLevelNamespace(!(flags & Flags::FlatNamespace)); |
| file->setApplicationExtensionSafe( |
| !(flags & Flags::NotApplicationExtensionSafe)); |
| file->setInstallAPI(flags & Flags::InstallAPI); |
| |
| for (const auto §ion : exports) { |
| for (const auto &client : section.allowableClients) |
| file->addAllowableClient(client, section.archs); |
| for (const auto &lib : section.reexportedLibraries) |
| file->addReexportedLibrary(lib, section.archs); |
| |
| // Skip symbols if requested. |
| if (ctx->readFlags < ReadFlags::Symbols) |
| continue; |
| |
| for (auto &sym : section.symbols) |
| file->addSymbolImpl(SymbolKind::GlobalSymbol, sym, section.archs, |
| SymbolFlags::None, |
| /*copyStrings=*/false); |
| for (auto &sym : section.classes) |
| file->addSymbolImpl(SymbolKind::ObjectiveCClass, sym, section.archs, |
| SymbolFlags::None, |
| /*copyStrings=*/false); |
| for (auto &sym : section.classEHs) |
| file->addSymbolImpl(SymbolKind::ObjectiveCClassEHType, sym, |
| section.archs, SymbolFlags::None, |
| /*copyStrings=*/false); |
| for (auto &sym : section.ivars) |
| file->addSymbolImpl(SymbolKind::ObjectiveCInstanceVariable, sym, |
| section.archs, SymbolFlags::None, |
| /*copyStrings=*/false); |
| for (auto &sym : section.weakDefSymbols) |
| file->addSymbolImpl(SymbolKind::GlobalSymbol, sym, section.archs, |
| SymbolFlags::WeakDefined, |
| /*copyStrings=*/false); |
| for (auto &sym : section.tlvSymbols) |
| file->addSymbolImpl(SymbolKind::GlobalSymbol, sym, section.archs, |
| SymbolFlags::ThreadLocalValue, |
| /*copyStrings=*/false); |
| } |
| |
| // Skip symbols if requested. |
| if (ctx->readFlags < ReadFlags::Symbols) |
| return file; |
| |
| for (const auto §ion : undefineds) { |
| for (auto &sym : section.symbols) |
| file->addUndefinedSymbolImpl(SymbolKind::GlobalSymbol, sym, |
| section.archs, SymbolFlags::None, |
| /*copyStrings=*/false); |
| for (auto &sym : section.classes) |
| file->addUndefinedSymbolImpl(SymbolKind::ObjectiveCClass, sym, |
| section.archs, SymbolFlags::None, |
| /*copyStrings=*/false); |
| for (auto &sym : section.classEHs) |
| file->addUndefinedSymbolImpl(SymbolKind::ObjectiveCClassEHType, sym, |
| section.archs, SymbolFlags::None, |
| /*copyStrings=*/false); |
| for (auto &sym : section.ivars) |
| file->addUndefinedSymbolImpl(SymbolKind::ObjectiveCInstanceVariable, |
| sym, section.archs, SymbolFlags::None, |
| /*copyStrings=*/false); |
| for (auto &sym : section.weakRefSymbols) |
| file->addUndefinedSymbolImpl(SymbolKind::GlobalSymbol, sym, |
| section.archs, |
| SymbolFlags::WeakReferenced, |
| /*copyStrings=*/false); |
| } |
| |
| return file; |
| } |
| |
| std::vector<Architecture> archs; |
| std::vector<UUID> uuids; |
| Platform platform; |
| StringRef installName; |
| PackedVersion currentVersion; |
| PackedVersion compatibilityVersion; |
| uint8_t swiftABIVersion; |
| ObjCConstraint objcConstraint; |
| Flags flags; |
| StringRef parentUmbrella; |
| std::vector<ExportSection> exports; |
| std::vector<UndefinedSection> undefineds; |
| }; |
| |
| static void mappingTBD3(IO &io, const InterfaceFile *&file) { |
| MappingNormalization<NormalizedTBD3, const InterfaceFile *> keys(io, file); |
| io.mapTag("!tapi-tbd-v3", true); |
| io.mapRequired("archs", keys->archs); |
| io.mapOptional("uuids", keys->uuids); |
| io.mapRequired("platform", keys->platform); |
| io.mapOptional("flags", keys->flags, Flags::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)); |
| io.mapOptional("swift-abi-version", keys->swiftABIVersion, (uint8_t)0U); |
| io.mapOptional("objc-constraint", keys->objcConstraint, |
| ObjCConstraint::Retain_Release); |
| io.mapOptional("parent-umbrella", keys->parentUmbrella, StringRef()); |
| io.mapOptional("exports", keys->exports); |
| io.mapOptional("undefineds", keys->undefineds); |
| } |
| }; |
| |
| } // end namespace yaml. |
| } // end namespace llvm. |
| |
| TAPI_NAMESPACE_INTERNAL_BEGIN |
| |
| namespace stub { |
| namespace v3 { |
| |
| bool YAMLDocumentHandler::canRead(MemoryBufferRef memBufferRef, |
| FileType types) const { |
| if (!(types & FileType::TBD_V3)) |
| return false; |
| |
| auto str = memBufferRef.getBuffer().trim(); |
| if (!str.startswith("--- !tapi-tbd-v3\n") || !str.endswith("...")) |
| return false; |
| |
| return true; |
| } |
| |
| FileType YAMLDocumentHandler::getFileType(MemoryBufferRef memBufferRef) const { |
| if (canRead(memBufferRef)) |
| return FileType::TBD_V3; |
| |
| return FileType::Invalid; |
| } |
| |
| bool YAMLDocumentHandler::canWrite(const File *file) const { |
| auto *interface = dyn_cast<InterfaceFile>(file); |
| if (interface == nullptr) |
| return false; |
| |
| if (interface->getFileType() != FileType::TBD_V3) |
| return false; |
| |
| return true; |
| } |
| |
| bool YAMLDocumentHandler::handleDocument(IO &io, const File *&file) const { |
| if (io.outputting() && file->getFileType() != FileType::TBD_V3) |
| return false; |
| |
| if (!io.outputting() && !io.mapTag("!tapi-tbd-v3")) |
| return false; |
| |
| auto *ctx = reinterpret_cast<YAMLContext *>(io.getContext()); |
| ctx->fileType = FileType::TBD_V3; |
| |
| const auto *interface = dyn_cast_or_null<InterfaceFile>(file); |
| MappingTraits<const InterfaceFile *>::mappingTBD3(io, interface); |
| file = interface; |
| |
| return true; |
| } |
| |
| } // end namespace v3. |
| } // end namespace stub. |
| |
| TAPI_NAMESPACE_INTERNAL_END |