Skip to content

Commit 04d9fb3

Browse files
committed
[Compatibility] Backward Deploy Tuple Equatable conformance
Make a local fatalError
1 parent 36fbb17 commit 04d9fb3

File tree

10 files changed

+441
-9
lines changed

10 files changed

+441
-9
lines changed

lib/Driver/DarwinToolChains.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
339339
options::OPT_runtime_compatibility_version);
340340
if (value.equals("5.0")) {
341341
runtimeCompatibilityVersion = llvm::VersionTuple(5, 0);
342+
} else if (value.equals("5.1")) {
343+
runtimeCompatibilityVersion = llvm::VersionTuple(5, 1);
342344
} else if (value.equals("none")) {
343345
runtimeCompatibilityVersion = None;
344346
} else {
@@ -350,16 +352,22 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
350352
}
351353

352354
if (runtimeCompatibilityVersion) {
355+
SmallString<128> BackDeployLib;
356+
BackDeployLib.append(SharedResourceDirPath);
357+
353358
if (*runtimeCompatibilityVersion <= llvm::VersionTuple(5, 0)) {
354359
// Swift 5.0 compatibility library
355-
SmallString<128> BackDeployLib;
356-
BackDeployLib.append(SharedResourceDirPath);
357360
llvm::sys::path::append(BackDeployLib, "libswiftCompatibility50.a");
358-
359-
if (llvm::sys::fs::exists(BackDeployLib)) {
360-
Arguments.push_back("-force_load");
361-
Arguments.push_back(context.Args.MakeArgString(BackDeployLib));
362-
}
361+
}
362+
363+
if (*runtimeCompatibilityVersion <= llvm::VersionTuple(5, 1)) {
364+
// Swift 5.1 compatibility library
365+
llvm::sys::path::append(BackDeployLib, "libswiftCompatibility51.a");
366+
}
367+
368+
if (llvm::sys::fs::exists(BackDeployLib)) {
369+
Arguments.push_back("-force_load");
370+
Arguments.push_back(context.Args.MakeArgString(BackDeployLib));
363371
}
364372
}
365373

stdlib/toolchain/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,5 @@ endif()
5656

5757
add_subdirectory(legacy_layouts)
5858
add_subdirectory(Compatibility50)
59+
add_subdirectory(Compatibility51)
5960
add_subdirectory(CompatibilityDynamicReplacements)
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//===--- BuiltinProtocolWitnessTables.cpp ---------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Definitions of some builtin protocol witness tables for backward compat.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "Overrides.h"
18+
#include "swift/Runtime/BuiltinProtocolConformances.h"
19+
#include "swift/Runtime/Casting.h"
20+
#include "swift/Runtime/Debug.h"
21+
22+
using namespace swift;
23+
24+
static void _fatalError(uint32_t flags, const char *log) {
25+
swift_reportError(flags, log);
26+
abort();
27+
}
28+
29+
extern const ProtocolDescriptor
30+
PROTOCOL_DESCRIPTOR_SYM(SWIFT_EQUATABLE_MANGLING);
31+
32+
extern const ProtocolConformanceDescriptor
33+
BUILTIN_PROTOCOL_CONFORMANCE_DESCRIPTOR_SYM(VARIADIC_TUPLE_MANGLING,
34+
SWIFT_EQUATABLE_MANGLING);
35+
36+
SWIFT_RUNTIME_EXPORT
37+
const _WitnessTable<1> swift::
38+
BUILTIN_PROTOCOL_WITNESS_TABLE_SYM(VARIADIC_TUPLE_MANGLING,
39+
SWIFT_EQUATABLE_MANGLING) = {
40+
&BUILTIN_PROTOCOL_CONFORMANCE_DESCRIPTOR_SYM(VARIADIC_TUPLE_MANGLING,
41+
SWIFT_EQUATABLE_MANGLING),
42+
{
43+
reinterpret_cast<void *>(
44+
BUILTIN_PROTOCOL_WITNESS_SYM(VARIADIC_TUPLE_MANGLING,
45+
SWIFT_EQUATABLE_MANGLING,
46+
SWIFT_EQUAL_OPERATOR_MANGLING))
47+
}
48+
};
49+
50+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
51+
bool swift::
52+
BUILTIN_PROTOCOL_WITNESS_SYM(VARIADIC_TUPLE_MANGLING,
53+
SWIFT_EQUATABLE_MANGLING,
54+
SWIFT_EQUAL_OPERATOR_MANGLING)
55+
(OpaqueValue *tuple1, OpaqueValue *tuple2, SWIFT_CONTEXT Metadata *swiftSelf,
56+
Metadata *Self, void *witnessTable) {
57+
auto tuple = cast<TupleTypeMetadata>(Self);
58+
59+
// Loop through all elements, and check if both tuples element is equal.
60+
for (size_t i = 0; i != tuple->NumElements; i += 1) {
61+
auto elt = tuple->getElement(i);
62+
63+
// Ensure we actually have a conform to Equatable for this element type.
64+
auto equatable = &PROTOCOL_DESCRIPTOR_SYM(SWIFT_EQUATABLE_MANGLING);
65+
auto conformance = swift50override_conformsToProtocol(elt.Type, equatable,
66+
swift_conformsToProtocol);
67+
68+
// If we don't have a conformance then something somewhere messed up in
69+
// deciding that this tuple type was Equatable...??
70+
if (!conformance)
71+
_fatalError(0,
72+
"tuple element must be equatable when evaluating tuple equalness");
73+
74+
// Get the respective values from both tuples.
75+
auto val1 = reinterpret_cast<OpaqueValue *>(
76+
reinterpret_cast<char *>(tuple1) + elt.Offset);
77+
auto val2 = reinterpret_cast<OpaqueValue *>(
78+
reinterpret_cast<char *>(tuple2) + elt.Offset);
79+
80+
// Grab the specific witness for this element type.
81+
auto table = reinterpret_cast<void * const *>(conformance);
82+
auto witness = table[WitnessTableFirstRequirementOffset];
83+
using Fn = SWIFT_CC(swift) bool(OpaqueValue *, OpaqueValue *,
84+
SWIFT_CONTEXT const Metadata *,
85+
const Metadata *, const WitnessTable *);
86+
auto func = reinterpret_cast<Fn *>(witness);
87+
88+
// Call the witness
89+
auto result = func(val1, val2, elt.Type, elt.Type, conformance);
90+
91+
// If the values aren't equal, this tuple isn't equal. :)
92+
if (!result)
93+
return false;
94+
}
95+
96+
// Otherwise this tuple has value equality with all elements.
97+
return true;
98+
}

stdlib/toolchain/Compatibility50/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(library_name "swiftCompatibility50")
22

33
add_swift_target_library("${library_name}" STATIC
4+
BuiltinProtocolConformances.cpp
45
ProtocolConformance.cpp
56
Overrides.cpp
67

stdlib/toolchain/Compatibility50/ProtocolConformance.cpp

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2019 - 2020 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -20,6 +20,8 @@
2020
#include "Overrides.h"
2121
#include "../../public/runtime/Private.h"
2222
#include "swift/Basic/Lazy.h"
23+
#include "swift/Runtime/BuiltinProtocolConformances.h"
24+
#include "swift/Runtime/Casting.h"
2325
#include <dlfcn.h>
2426
#include <mach-o/dyld.h>
2527
#include <mach-o/getsect.h>
@@ -120,6 +122,39 @@ static const Metadata *_swift50override_class_getSuperclass(
120122
return nullptr;
121123
}
122124

125+
extern const ProtocolDescriptor
126+
PROTOCOL_DESCRIPTOR_SYM(SWIFT_EQUATABLE_MANGLING);
127+
128+
static bool tupleConformsToProtocol(const Metadata *type,
129+
const ProtocolDescriptor *protocol) {
130+
auto tuple = cast<TupleTypeMetadata>(type);
131+
132+
// At the moment, tuples can only conform to Equatable, so reject all other
133+
// protocols.
134+
if (protocol != &PROTOCOL_DESCRIPTOR_SYM(SWIFT_EQUATABLE_MANGLING))
135+
return false;
136+
137+
for (size_t i = 0; i != tuple->NumElements; i += 1) {
138+
auto elt = tuple->getElement(i);
139+
if (!swift50override_conformsToProtocol(elt.Type, protocol,
140+
swift_conformsToProtocol))
141+
return false;
142+
}
143+
144+
return true;
145+
}
146+
147+
static const WitnessTable *getTupleConformanceWitnessTable(
148+
const ProtocolDescriptor *protocol) {
149+
if (protocol == &PROTOCOL_DESCRIPTOR_SYM(SWIFT_EQUATABLE_MANGLING)) {
150+
return reinterpret_cast<const WitnessTable *>(
151+
&BUILTIN_PROTOCOL_WITNESS_TABLE_SYM(VARIADIC_TUPLE_MANGLING,
152+
SWIFT_EQUATABLE_MANGLING));
153+
}
154+
155+
return nullptr;
156+
}
157+
123158
const WitnessTable *
124159
swift::swift50override_conformsToProtocol(const Metadata *type,
125160
const ProtocolDescriptor *protocol,
@@ -139,6 +174,15 @@ swift::swift50override_conformsToProtocol(const Metadata *type,
139174
if (result)
140175
return result;
141176
} while ((type = _swift50override_class_getSuperclass(type)));
142-
177+
178+
// Swift 5.2 introduces tuple Equatable conformance, so ensure that Swift 5.0
179+
// runtime can handle this as well.
180+
if (auto tuple = dyn_cast<TupleTypeMetadata>(type)) {
181+
if (!tupleConformsToProtocol(type, protocol))
182+
return nullptr;
183+
184+
return getTupleConformanceWitnessTable(protocol);
185+
}
186+
143187
return nullptr;
144188
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//===--- BuiltinProtocolWitnessTables.cpp ---------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Definitions of some builtin protocol witness tables for backward compat.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "Overrides.h"
18+
#include "swift/Runtime/BuiltinProtocolConformances.h"
19+
#include "swift/Runtime/Casting.h"
20+
#include "swift/Runtime/Debug.h"
21+
22+
using namespace swift;
23+
24+
static void _fatalError(uint32_t flags, const char *log) {
25+
swift_reportError(flags, log);
26+
abort();
27+
}
28+
29+
extern const ProtocolDescriptor
30+
PROTOCOL_DESCRIPTOR_SYM(SWIFT_EQUATABLE_MANGLING);
31+
32+
extern const ProtocolConformanceDescriptor
33+
BUILTIN_PROTOCOL_CONFORMANCE_DESCRIPTOR_SYM(VARIADIC_TUPLE_MANGLING,
34+
SWIFT_EQUATABLE_MANGLING);
35+
36+
SWIFT_RUNTIME_EXPORT
37+
const _WitnessTable<1> swift::
38+
BUILTIN_PROTOCOL_WITNESS_TABLE_SYM(VARIADIC_TUPLE_MANGLING,
39+
SWIFT_EQUATABLE_MANGLING) = {
40+
&BUILTIN_PROTOCOL_CONFORMANCE_DESCRIPTOR_SYM(VARIADIC_TUPLE_MANGLING,
41+
SWIFT_EQUATABLE_MANGLING),
42+
{
43+
reinterpret_cast<void *>(
44+
BUILTIN_PROTOCOL_WITNESS_SYM(VARIADIC_TUPLE_MANGLING,
45+
SWIFT_EQUATABLE_MANGLING,
46+
SWIFT_EQUAL_OPERATOR_MANGLING))
47+
}
48+
};
49+
50+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
51+
bool swift::
52+
BUILTIN_PROTOCOL_WITNESS_SYM(VARIADIC_TUPLE_MANGLING,
53+
SWIFT_EQUATABLE_MANGLING,
54+
SWIFT_EQUAL_OPERATOR_MANGLING)
55+
(OpaqueValue *tuple1, OpaqueValue *tuple2, SWIFT_CONTEXT Metadata *swiftSelf,
56+
Metadata *Self, void *witnessTable) {
57+
auto tuple = cast<TupleTypeMetadata>(Self);
58+
59+
// Loop through all elements, and check if both tuples element is equal.
60+
for (size_t i = 0; i != tuple->NumElements; i += 1) {
61+
auto elt = tuple->getElement(i);
62+
63+
// Ensure we actually have a conform to Equatable for this element type.
64+
auto equatable = &PROTOCOL_DESCRIPTOR_SYM(SWIFT_EQUATABLE_MANGLING);
65+
auto conformance = swift51override_conformsToProtocol(elt.Type, equatable,
66+
swift_conformsToProtocol);
67+
68+
// If we don't have a conformance then something somewhere messed up in
69+
// deciding that this tuple type was Equatable...??
70+
if (!conformance)
71+
_fatalError(0,
72+
"tuple element must be equatable when evaluating tuple equalness");
73+
74+
// Get the respective values from both tuples.
75+
auto val1 = reinterpret_cast<OpaqueValue *>(
76+
reinterpret_cast<char *>(tuple1) + elt.Offset);
77+
auto val2 = reinterpret_cast<OpaqueValue *>(
78+
reinterpret_cast<char *>(tuple2) + elt.Offset);
79+
80+
// Grab the specific witness for this element type.
81+
auto table = reinterpret_cast<void * const *>(conformance);
82+
auto witness = table[WitnessTableFirstRequirementOffset];
83+
using Fn = SWIFT_CC(swift) bool(OpaqueValue *, OpaqueValue *,
84+
SWIFT_CONTEXT const Metadata *,
85+
const Metadata *, const WitnessTable *);
86+
auto func = reinterpret_cast<Fn *>(witness);
87+
88+
// Call the witness
89+
auto result = func(val1, val2, elt.Type, elt.Type, conformance);
90+
91+
// If the values aren't equal, this tuple isn't equal. :)
92+
if (!result)
93+
return false;
94+
}
95+
96+
// Otherwise this tuple has value equality with all elements.
97+
return true;
98+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
set(library_name "swiftCompatibility51")
2+
3+
add_swift_target_library("${library_name}" STATIC
4+
BuiltinProtocolConformances.cpp
5+
ProtocolConformance.cpp
6+
Overrides.cpp
7+
8+
TARGET_SDKS ${SWIFT_APPLE_PLATFORMS}
9+
10+
C_COMPILE_FLAGS ${CXX_COMPILE_FLAGS}
11+
LINK_FLAGS ${CXX_LINK_FLAGS}
12+
SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
13+
14+
INSTALL_IN_COMPONENT compiler
15+
INSTALL_WITH_SHARED)
16+
17+
18+
# FIXME: We need a more flexible mechanism to add lipo targets generated by
19+
# add_swift_target_library to the ALL target. Until then this hack is necessary
20+
# to ensure these libraries build.
21+
foreach(sdk ${SWIFT_SDKS})
22+
set(target_name "${library_name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}")
23+
if(NOT TARGET "${target_name}")
24+
continue()
25+
endif()
26+
27+
set_target_properties("${target_name}"
28+
PROPERTIES
29+
EXCLUDE_FROM_ALL FALSE)
30+
endforeach()
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===--- Overrides.cpp - Compat override table for Swift 5.0 runtime ------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file provides compatibility override hooks for Swift 5.1 runtimes.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "Overrides.h"
18+
#include "../../public/runtime/CompatibilityOverride.h"
19+
20+
using namespace swift;
21+
22+
struct OverrideSection {
23+
uintptr_t version;
24+
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
25+
Override_ ## name name;
26+
#include "../../public/runtime/CompatibilityOverride.def"
27+
};
28+
29+
OverrideSection Overrides
30+
__attribute__((used, section("__DATA,__swift_hooks"))) = {
31+
.version = 0,
32+
.conformsToProtocol = swift51override_conformsToProtocol,
33+
};
34+
35+
// Allow this library to get force-loaded by autolinking
36+
__attribute__((weak, visibility("hidden")))
37+
extern "C"
38+
char _swift_FORCE_LOAD_$_swiftCompatibility51 = 0;

0 commit comments

Comments
 (0)