Skip to content

Backward deployment shim for swift_allocate{Metadata,WitnessTable}Pack() #65884

New issue

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

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

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions include/swift/Frontend/BackDeploymentLibs.def
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@
//===----------------------------------------------------------------------===//

#ifndef BACK_DEPLOYMENT_LIB
# error "Must define BACK_DEPLOYMENT_LIB(Version, Filter, Library)"
# error "Must define BACK_DEPLOYMENT_LIB(Version, Filter, Library, ForceLoad)"
#endif

BACK_DEPLOYMENT_LIB((5, 0), all, "swiftCompatibility50")
BACK_DEPLOYMENT_LIB((5, 1), all, "swiftCompatibility51")
BACK_DEPLOYMENT_LIB((5, 0), executable, "swiftCompatibilityDynamicReplacements")
BACK_DEPLOYMENT_LIB((5, 4), all, "swiftCompatibilityConcurrency")
BACK_DEPLOYMENT_LIB((5, 6), all, "swiftCompatibility56")
BACK_DEPLOYMENT_LIB((5, 0), all, "swiftCompatibility50", true)
BACK_DEPLOYMENT_LIB((5, 1), all, "swiftCompatibility51", true)
BACK_DEPLOYMENT_LIB((5, 0), executable, "swiftCompatibilityDynamicReplacements", true)
BACK_DEPLOYMENT_LIB((5, 4), all, "swiftCompatibilityConcurrency", true)
BACK_DEPLOYMENT_LIB((5, 6), all, "swiftCompatibility56", true)
BACK_DEPLOYMENT_LIB((5, 8), all, "swiftCompatibilityPacks", false)

#undef BACK_DEPLOYMENT_LIB
27 changes: 16 additions & 11 deletions lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ using namespace swift;
/// Print information about a
static void printCompatibilityLibrary(
llvm::VersionTuple runtimeVersion, llvm::VersionTuple maxVersion,
StringRef filter, StringRef libraryName, bool &printedAny,
llvm::raw_ostream &out) {
StringRef filter, StringRef libraryName, bool forceLoad,
bool &printedAny, llvm::raw_ostream &out) {
if (runtimeVersion > maxVersion)
return;

Expand All @@ -33,16 +33,21 @@ static void printCompatibilityLibrary(
}

out << "\n";
out << " {\n";
out << " {";

out << " \"libraryName\": \"";
out << "\n \"libraryName\": \"";
swift::writeEscaped(libraryName, out);
out << "\",\n";
out << "\",";

out << " \"filter\": \"";
out << "\n \"filter\": \"";
swift::writeEscaped(filter, out);
out << "\"\n";
out << " }";
out << "\"";

if (!forceLoad) {
out << ",\n \"forceLoad\": false";
}

out << "\n }";

printedAny = true;
}
Expand Down Expand Up @@ -132,10 +137,10 @@ void targetinfo::printTripleInfo(const llvm::Triple &triple,
// Compatibility libraries that need to be linked.
out << " \"compatibilityLibraries\": [";
bool printedAnyCompatibilityLibrary = false;
#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName) \
printCompatibilityLibrary( \
#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName, ForceLoad) \
printCompatibilityLibrary( \
*runtimeVersion, llvm::VersionTuple Version, #Filter, LibraryName, \
printedAnyCompatibilityLibrary, out);
ForceLoad, printedAnyCompatibilityLibrary, out);
#include "swift/Frontend/BackDeploymentLibs.def"

if (printedAnyCompatibilityLibrary) {
Expand Down
15 changes: 10 additions & 5 deletions lib/Driver/DarwinToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
runtimeCompatibilityVersion = llvm::VersionTuple(5, 5);
} else if (value.equals("5.6")) {
runtimeCompatibilityVersion = llvm::VersionTuple(5, 6);
} else if (value.equals("5.8")) {
runtimeCompatibilityVersion = llvm::VersionTuple(5, 8);
} else if (value.equals("none")) {
runtimeCompatibilityVersion = None;
} else {
Expand All @@ -419,7 +421,8 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
if (runtimeCompatibilityVersion) {
auto addBackDeployLib = [&](llvm::VersionTuple version,
BackDeployLibFilter filter,
StringRef libraryName) {
StringRef libraryName,
bool forceLoad) {
if (*runtimeCompatibilityVersion > version)
return;

Expand All @@ -431,14 +434,16 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
llvm::sys::path::append(BackDeployLib, "lib" + libraryName + ".a");

if (llvm::sys::fs::exists(BackDeployLib)) {
Arguments.push_back("-force_load");
if (forceLoad)
Arguments.push_back("-force_load");
Arguments.push_back(context.Args.MakeArgString(BackDeployLib));
}
};

#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName) \
addBackDeployLib( \
llvm::VersionTuple Version, BackDeployLibFilter::Filter, LibraryName);
#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName, ForceLoad) \
addBackDeployLib( \
llvm::VersionTuple Version, BackDeployLibFilter::Filter, \
LibraryName, ForceLoad);
#include "swift/Frontend/BackDeploymentLibs.def"
}

Expand Down
2 changes: 2 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2607,6 +2607,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
runtimeCompatibilityVersion = llvm::VersionTuple(5, 5);
} else if (version.equals("5.6")) {
runtimeCompatibilityVersion = llvm::VersionTuple(5, 6);
} else if (version.equals("5.8")) {
runtimeCompatibilityVersion = llvm::VersionTuple(5, 8);
} else {
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
versionArg->getAsString(Args), version);
Expand Down
9 changes: 5 additions & 4 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,8 @@ void IRGenModule::emitSourceFile(SourceFile &SF) {
// harmless aside from code size.
if (!IRGen.Opts.UseJIT) {
auto addBackDeployLib = [&](llvm::VersionTuple version,
StringRef libraryName) {
StringRef libraryName,
bool forceLoad) {
Optional<llvm::VersionTuple> compatibilityVersion;
if (libraryName == "swiftCompatibilityDynamicReplacements") {
compatibilityVersion = IRGen.Opts.
Expand All @@ -532,11 +533,11 @@ void IRGenModule::emitSourceFile(SourceFile &SF) {

this->addLinkLibrary(LinkLibrary(libraryName,
LibraryKind::Library,
/*forceLoad*/ true));
forceLoad));
};

#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName) \
addBackDeployLib(llvm::VersionTuple Version, LibraryName);
#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName, ForceLoad) \
addBackDeployLib(llvm::VersionTuple Version, LibraryName, ForceLoad);
#include "swift/Frontend/BackDeploymentLibs.def"
}
}
Expand Down
2 changes: 2 additions & 0 deletions stdlib/toolchain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ if(SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT)
add_subdirectory(CompatibilityDynamicReplacements)
add_subdirectory(CompatibilityConcurrency)
add_subdirectory(CompatibilityThreading)
add_subdirectory(CompatibilityPacks)

# This is a convenience target to have the list
# of all the compatibility libraries needed to build
Expand All @@ -63,6 +64,7 @@ if(SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT)
target_link_libraries(HostCompatibilityLibs INTERFACE
swiftCompatibilityConcurrency${vsuffix}
swiftCompatibilityDynamicReplacements${vsuffix}
swiftCompatibilityPacks${vsuffix}
swiftCompatibility50${vsuffix}
swiftCompatibility51${vsuffix}
swiftCompatibility56${vsuffix})
Expand Down
44 changes: 44 additions & 0 deletions stdlib/toolchain/CompatibilityPacks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
set(library_name "swiftCompatibilityPacks")

include_directories("include/" "${SWIFT_STDLIB_SOURCE_DIR}")

set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)

add_compile_definitions(SWIFT_COMPATIBILITY_PACKS)
add_swift_target_library("${library_name}" STATIC
Metadata.cpp

TARGET_SDKS ${SWIFT_DARWIN_PLATFORMS}

C_COMPILE_FLAGS
${CXX_COMPILE_FLAGS}
"-D__STDC_WANT_LIB_EXT1__=1"
LINK_FLAGS ${CXX_LINK_FLAGS}
INCORPORATE_OBJECT_LIBRARIES swiftCompatibilityThreading
SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
DEPLOYMENT_VERSION_OSX ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_OSX}
DEPLOYMENT_VERSION_IOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_IOS}
DEPLOYMENT_VERSION_TVOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_TVOS}
DEPLOYMENT_VERSION_WATCHOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_WATCHOS}

MACCATALYST_BUILD_FLAVOR "zippered"

INSTALL_IN_COMPONENT compiler
INSTALL_WITH_SHARED)


# FIXME: We need a more flexible mechanism to add lipo targets generated by
# add_swift_target_library to the ALL target. Until then this hack is necessary
# to ensure these libraries build.
foreach(sdk ${SWIFT_SDKS})
set(target_name "${library_name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}")
if(NOT TARGET "${target_name}")
continue()
endif()

set_target_properties("${target_name}"
PROPERTIES
EXCLUDE_FROM_ALL FALSE)
endforeach()
164 changes: 164 additions & 0 deletions stdlib/toolchain/CompatibilityPacks/Metadata.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
//===--- Metadata.cpp -----------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Backward deployment of swift_allocateMetadataPack() and
// swift_allocateWitnessTablePack() runtime entry points.
//
//===----------------------------------------------------------------------===//

#include "../../public/runtime/MetadataCache.h"

using namespace swift;

/// Copy and paste a symbol that needs to exist.
void *MetadataAllocator::Allocate(size_t size, size_t alignment) {
return malloc(size);
}

/// Avoid depending on non-inline parts of llvm::hashing.
inline llvm::hash_code our_hash_integer_value(uint64_t value) {
const char *s = reinterpret_cast<const char *>(&value);
const uint64_t a = llvm::hashing::detail::fetch32(s);
return llvm::hashing::detail::hash_16_bytes(
(a << 3), llvm::hashing::detail::fetch32(s + 4));
}

static inline llvm::hash_code our_hash_combine(llvm::hash_code seed, llvm::hash_code v) {
return seed ^ (v + 0x9e3779b9 + (seed<<6) + (seed>>2));
}

/// Copy and paste from Metadata.cpp.

namespace {

template<typename PackType>
class PackCacheEntry {
public:
size_t Count;

const PackType * const * getElements() const {
return reinterpret_cast<const PackType * const *>(this + 1);
}

const PackType ** getElements() {
return reinterpret_cast<const PackType **>(this + 1);
}

struct Key {
const PackType *const *Data;
const size_t Count;

size_t getCount() const {
return Count;
}

const PackType *getElement(size_t index) const {
assert(index < Count);
return Data[index];
}

friend llvm::hash_code hash_value(const Key &key) {
llvm::hash_code hash = 0;
for (size_t i = 0; i != key.getCount(); ++i) {
hash = our_hash_combine(hash, our_hash_integer_value(
reinterpret_cast<uint64_t>(key.getElement(i))));
}
return hash;
}
};

PackCacheEntry(const Key &key);

intptr_t getKeyIntValueForDump() {
return 0; // No single meaningful value here.
}

bool matchesKey(const Key &key) const {
if (key.getCount() != Count)
return false;
for (unsigned i = 0; i != Count; ++i) {
if (key.getElement(i) != getElements()[i])
return false;
}
return true;
}

friend llvm::hash_code hash_value(const PackCacheEntry<PackType> &value) {
llvm::hash_code hash = 0;
for (size_t i = 0; i != value.Count; ++i) {
hash = our_hash_combine(hash, our_hash_integer_value(
reinterpret_cast<uint64_t>(value.getElements()[i])));
}
return hash;
}

static size_t getExtraAllocationSize(const Key &key) {
return getExtraAllocationSize(key.Count);
}

size_t getExtraAllocationSize() const {
return getExtraAllocationSize(Count);
}

static size_t getExtraAllocationSize(unsigned count) {
return count * sizeof(const Metadata * const *);
}
};

template<typename PackType>
PackCacheEntry<PackType>::PackCacheEntry(
const typename PackCacheEntry<PackType>::Key &key) {
Count = key.getCount();

for (unsigned i = 0; i < Count; ++i)
getElements()[i] = key.getElement(i);
}

} // end anonymous namespace

/// The uniquing structure for metadata packs.
static SimpleGlobalCache<PackCacheEntry<Metadata>,
MetadataPackTag> MetadataPacks;

SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
const Metadata * const *
swift_allocateMetadataPack(const Metadata * const *ptr, size_t count) {
if (MetadataPackPointer(reinterpret_cast<uintptr_t>(ptr)).getLifetime()
== PackLifetime::OnHeap)
return ptr;

PackCacheEntry<Metadata>::Key key{ptr, count};
auto bytes = MetadataPacks.getOrInsert(key).first->getElements();

MetadataPackPointer pack(bytes, PackLifetime::OnHeap);
assert(pack.getNumElements() == count);
return pack.getPointer();
}

/// The uniquing structure for witness table packs.
static SimpleGlobalCache<PackCacheEntry<WitnessTable>,
WitnessTablePackTag> WitnessTablePacks;

SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
const WitnessTable * const *
swift_allocateWitnessTablePack(const WitnessTable * const *ptr, size_t count) {
if (WitnessTablePackPointer(reinterpret_cast<uintptr_t>(ptr)).getLifetime()
== PackLifetime::OnHeap)
return ptr;

PackCacheEntry<WitnessTable>::Key key{ptr, count};
auto bytes = WitnessTablePacks.getOrInsert(key).first->getElements();

WitnessTablePackPointer pack(bytes, PackLifetime::OnHeap);
assert(pack.getNumElements() == count);
return pack.getPointer();
}
7 changes: 7 additions & 0 deletions test/Driver/compatibility_packs.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: %target-swift-frontend -print-target-info -runtime-compatibility-version 5.8 | %FileCheck %s

// REQUIRES: OS=macosx

// CHECK: "libraryName": "swiftCompatibilityPacks",
// CHECK-NEXT: "filter": "all",
// CHECK-NEXT: "forceLoad": false
3 changes: 0 additions & 3 deletions test/Interpreter/variadic_generic_captures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@

// REQUIRES: executable_test

// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: back_deployment_runtime

import StdlibUnittest

var types = TestSuite("VariadicGenericCaptures")
Expand Down