Skip to content

Commit 6463dcb

Browse files
authored
Merge pull request #79703 from slavapestov/span-backward-deployment
Build CompatibilitySpan shim
2 parents 2c8e337 + b0627e2 commit 6463dcb

20 files changed

+313
-26
lines changed

include/swift/AST/Attr.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,17 +2050,29 @@ class ProjectedValuePropertyAttr : public DeclAttribute {
20502050
class OriginallyDefinedInAttr: public DeclAttribute {
20512051
public:
20522052
OriginallyDefinedInAttr(SourceLoc AtLoc, SourceRange Range,
2053-
StringRef OriginalModuleName, PlatformKind Platform,
2053+
StringRef OriginalModuleName,
2054+
PlatformKind Platform,
2055+
const llvm::VersionTuple MovedVersion, bool Implicit);
2056+
2057+
OriginallyDefinedInAttr(SourceLoc AtLoc, SourceRange Range,
2058+
StringRef ManglingModuleName,
2059+
StringRef LinkerModuleName,
2060+
PlatformKind Platform,
20542061
const llvm::VersionTuple MovedVersion, bool Implicit)
20552062
: DeclAttribute(DeclAttrKind::OriginallyDefinedIn, AtLoc, Range,
20562063
Implicit),
2057-
OriginalModuleName(OriginalModuleName), Platform(Platform),
2064+
ManglingModuleName(ManglingModuleName),
2065+
LinkerModuleName(LinkerModuleName),
2066+
Platform(Platform),
20582067
MovedVersion(MovedVersion) {}
20592068

20602069
OriginallyDefinedInAttr *clone(ASTContext &C, bool implicit) const;
20612070

2062-
// The original module name.
2063-
const StringRef OriginalModuleName;
2071+
// The original module name for mangling.
2072+
const StringRef ManglingModuleName;
2073+
2074+
// The original module name for linker directives.
2075+
const StringRef LinkerModuleName;
20642076

20652077
/// The platform of the symbol.
20662078
const PlatformKind Platform;
@@ -2069,7 +2081,8 @@ class OriginallyDefinedInAttr: public DeclAttribute {
20692081
const llvm::VersionTuple MovedVersion;
20702082

20712083
struct ActiveVersion {
2072-
StringRef ModuleName;
2084+
StringRef ManglingModuleName;
2085+
StringRef LinkerModuleName;
20732086
PlatformKind Platform;
20742087
llvm::VersionTuple Version;
20752088
bool ForTargetVariant = false;
@@ -2085,7 +2098,8 @@ class OriginallyDefinedInAttr: public DeclAttribute {
20852098
/// Create a copy of this attribute.
20862099
OriginallyDefinedInAttr *clone(ASTContext &ctx) const {
20872100
return new (ctx) OriginallyDefinedInAttr(
2088-
AtLoc, Range, OriginalModuleName, Platform, MovedVersion, isImplicit());
2101+
AtLoc, Range, ManglingModuleName, LinkerModuleName,
2102+
Platform, MovedVersion, isImplicit());
20892103
}
20902104
};
20912105

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5214,7 +5214,8 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
52145214
void visitOriginallyDefinedInAttr(OriginallyDefinedInAttr *Attr,
52155215
Label label) {
52165216
printCommon(Attr, "originally_defined_in_attr", label);
5217-
printField(Attr->OriginalModuleName, Label::always("original_module"));
5217+
printField(Attr->ManglingModuleName, Label::always("mangling_module"));
5218+
printField(Attr->LinkerModuleName, Label::always("linker_module"));
52185219
printField(Attr->Platform, Label::always("platform"));
52195220
printFieldRaw([&](auto &out) { out << Attr->MovedVersion.getAsString(); },
52205221
Label::always("moved_version"));

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2781,7 +2781,7 @@ void ASTMangler::appendModule(const ModuleDecl *module,
27812781

27822782
// Try the special 'swift' substitution.
27832783
if (ModName == STDLIB_NAME) {
2784-
if (useModuleName.empty()) {
2784+
if (useModuleName.empty() || useModuleName == STDLIB_NAME) {
27852785
appendOperator("s");
27862786
} else if (!RespectOriginallyDefinedIn) {
27872787
appendOperator("s");

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5986,7 +5986,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
59865986
for (auto attr: D->getAttrs().getAttributes<OriginallyDefinedInAttr>()) {
59875987
Name = Mod->getASTContext()
59885988
.getIdentifier(const_cast<OriginallyDefinedInAttr*>(attr)
5989-
->OriginalModuleName);
5989+
->ManglingModuleName);
59905990
break;
59915991
}
59925992
}

lib/AST/Attr.cpp

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
10781078
}
10791079
break;
10801080
}
1081+
case DeclAttrKind::OriginallyDefinedIn: {
1082+
auto Attr = cast<OriginallyDefinedInAttr>(this);
1083+
auto Name = D->getDeclContext()->getParentModule()->getName().str();
1084+
if (Options.IsForSwiftInterface && Attr->ManglingModuleName == Name)
1085+
return false;
1086+
break;
1087+
}
10811088
default:
10821089
break;
10831090
}
@@ -1175,8 +1182,12 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
11751182
Printer.printAttrName("@_originallyDefinedIn");
11761183
Printer << "(module: ";
11771184
auto Attr = cast<OriginallyDefinedInAttr>(this);
1178-
Printer << "\"" << Attr->OriginalModuleName << "\", ";
1179-
Printer << platformString(Attr->Platform) << " " <<
1185+
Printer << "\"" << Attr->ManglingModuleName;
1186+
ASSERT(!Attr->ManglingModuleName.empty());
1187+
ASSERT(!Attr->LinkerModuleName.empty());
1188+
if (Attr->LinkerModuleName != Attr->ManglingModuleName)
1189+
Printer << ";" << Attr->LinkerModuleName;
1190+
Printer << "\", " << platformString(Attr->Platform) << " " <<
11801191
Attr->MovedVersion.getAsString();
11811192
Printer << ")";
11821193
break;
@@ -2235,12 +2246,39 @@ AvailableAttr *AvailableAttr::clone(ASTContext &C, bool implicit) const {
22352246
implicit ? SourceRange() : ObsoletedRange, implicit, isSPI());
22362247
}
22372248

2249+
static StringRef getManglingModuleName(StringRef OriginalModuleName) {
2250+
auto index = OriginalModuleName.find(";");
2251+
return index == StringRef::npos
2252+
? OriginalModuleName
2253+
: OriginalModuleName.slice(0, index);
2254+
}
2255+
2256+
static StringRef getLinkerModuleName(StringRef OriginalModuleName) {
2257+
auto index = OriginalModuleName.find(";");
2258+
return index == StringRef::npos
2259+
? OriginalModuleName
2260+
: OriginalModuleName.slice(index + 1, OriginalModuleName.size());
2261+
}
2262+
2263+
OriginallyDefinedInAttr::OriginallyDefinedInAttr(
2264+
SourceLoc AtLoc, SourceRange Range,
2265+
StringRef OriginalModuleName,
2266+
PlatformKind Platform,
2267+
const llvm::VersionTuple MovedVersion, bool Implicit)
2268+
: DeclAttribute(DeclAttrKind::OriginallyDefinedIn, AtLoc, Range,
2269+
Implicit),
2270+
ManglingModuleName(getManglingModuleName(OriginalModuleName)),
2271+
LinkerModuleName(getLinkerModuleName(OriginalModuleName)),
2272+
Platform(Platform),
2273+
MovedVersion(MovedVersion) {}
2274+
22382275
std::optional<OriginallyDefinedInAttr::ActiveVersion>
22392276
OriginallyDefinedInAttr::isActivePlatform(const ASTContext &ctx) const {
22402277
OriginallyDefinedInAttr::ActiveVersion Result;
22412278
Result.Platform = Platform;
22422279
Result.Version = MovedVersion;
2243-
Result.ModuleName = OriginalModuleName;
2280+
Result.ManglingModuleName = ManglingModuleName;
2281+
Result.LinkerModuleName = LinkerModuleName;
22442282
if (isPlatformActive(Platform, ctx.LangOpts, /*TargetVariant*/false)) {
22452283
return Result;
22462284
}
@@ -2260,7 +2298,7 @@ OriginallyDefinedInAttr *OriginallyDefinedInAttr::clone(ASTContext &C,
22602298
bool implicit) const {
22612299
return new (C) OriginallyDefinedInAttr(
22622300
implicit ? SourceLoc() : AtLoc, implicit ? SourceRange() : getRange(),
2263-
OriginalModuleName, Platform, MovedVersion, implicit);
2301+
ManglingModuleName, LinkerModuleName, Platform, MovedVersion, implicit);
22642302
}
22652303

22662304
bool AvailableAttr::isUnconditionallyUnavailable() const {

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,7 @@ StringRef Decl::getAlternateModuleName() const {
11011101
for (auto *Att: Attrs) {
11021102
if (auto *OD = dyn_cast<OriginallyDefinedInAttr>(Att)) {
11031103
if (!OD->isInvalid() && OD->isActivePlatform(getASTContext())) {
1104-
return OD->OriginalModuleName;
1104+
return OD->ManglingModuleName;
11051105
}
11061106
}
11071107
}

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2541,10 +2541,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
25412541
if (auto Attribute =
25422542
ND->getAttrs().getAttribute<OriginallyDefinedInAttr>()) {
25432543
auto Identifier = IGM.getSILModule().getASTContext().getIdentifier(
2544-
Attribute->OriginalModuleName);
2544+
Attribute->ManglingModuleName);
25452545
void *Key = (void *)Identifier.get();
25462546
Scope =
2547-
getOrCreateModule(Key, TheCU, Attribute->OriginalModuleName, {});
2547+
getOrCreateModule(Key, TheCU, Attribute->ManglingModuleName, {});
25482548
} else {
25492549
Context = ND->getParent();
25502550
}

lib/IRGen/TBDGen.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,18 @@ void TBDGenVisitor::addSymbolInternal(StringRef name, EncodeKind kind,
8888

8989
static std::vector<OriginallyDefinedInAttr::ActiveVersion>
9090
getAllMovedPlatformVersions(Decl *D) {
91+
StringRef Name = D->getDeclContext()->getParentModule()->getName().str();
92+
9193
std::vector<OriginallyDefinedInAttr::ActiveVersion> Results;
9294
for (auto *attr: D->getAttrs()) {
9395
if (auto *ODA = dyn_cast<OriginallyDefinedInAttr>(attr)) {
9496
auto Active = ODA->isActivePlatform(D->getASTContext());
95-
if (Active.has_value()) {
97+
if (Active.has_value() && Active->LinkerModuleName != Name) {
9698
Results.push_back(*Active);
9799
}
98100
}
99101
}
102+
100103
return Results;
101104
}
102105

@@ -324,16 +327,16 @@ void TBDGenVisitor::addLinkerDirectiveSymbolsLdPrevious(
324327
if (*IntroVer >= Ver.Version)
325328
continue;
326329
auto PlatformNumber = getLinkerPlatformId(Ver, Ctx);
327-
auto It = previousInstallNameMap->find(Ver.ModuleName.str());
330+
auto It = previousInstallNameMap->find(Ver.LinkerModuleName.str());
328331
if (It == previousInstallNameMap->end()) {
329332
Ctx.Diags.diagnose(SourceLoc(), diag::cannot_find_install_name,
330-
Ver.ModuleName, getLinkerPlatformName(Ver, Ctx));
333+
Ver.LinkerModuleName, getLinkerPlatformName(Ver, Ctx));
331334
continue;
332335
}
333336
auto InstallName = It->second.getInstallName(PlatformNumber);
334337
if (InstallName.empty()) {
335338
Ctx.Diags.diagnose(SourceLoc(), diag::cannot_find_install_name,
336-
Ver.ModuleName, getLinkerPlatformName(Ver, Ctx));
339+
Ver.LinkerModuleName, getLinkerPlatformName(Ver, Ctx));
337340
continue;
338341
}
339342
llvm::SmallString<64> Buffer;

lib/Serialization/Deserialization.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6043,11 +6043,23 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() {
60436043
Platform);
60446044
llvm::VersionTuple MovedVer;
60456045
DECODE_VER_TUPLE(MovedVer)
6046-
auto ModuleNameEnd = blobData.find('\0');
6047-
assert(ModuleNameEnd != StringRef::npos);
6048-
auto ModuleName = blobData.slice(0, ModuleNameEnd);
6046+
6047+
auto ManglingModuleNameEnd = blobData.find('\0');
6048+
assert(ManglingModuleNameEnd != StringRef::npos);
6049+
auto ManglingModuleName = blobData.slice(0, ManglingModuleNameEnd);
6050+
6051+
blobData = blobData.slice(ManglingModuleNameEnd + 1, blobData.size());
6052+
6053+
auto LinkerModuleNameEnd = blobData.find('\0');
6054+
assert(LinkerModuleNameEnd != StringRef::npos);
6055+
auto LinkerModuleName = blobData.slice(0, LinkerModuleNameEnd);
6056+
6057+
ASSERT(!ManglingModuleName.empty());
6058+
ASSERT(!LinkerModuleName.empty());
6059+
60496060
Attr = new (ctx) OriginallyDefinedInAttr(SourceLoc(), SourceRange(),
6050-
ModuleName,
6061+
ManglingModuleName,
6062+
LinkerModuleName,
60516063
(PlatformKind)Platform,
60526064
MovedVer,
60536065
isImplicit);

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 928; // abstract conforming type
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 929; // OriginallyDefinedInAttr::LinkerModuleName
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

lib/Serialization/Serialization.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3094,7 +3094,9 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
30943094
Moved, std::optional<llvm::VersionTuple>(theAttr->MovedVersion));
30953095
auto abbrCode = S.DeclTypeAbbrCodes[OriginallyDefinedInDeclAttrLayout::Code];
30963096
llvm::SmallString<32> blob;
3097-
blob.append(theAttr->OriginalModuleName.str());
3097+
blob.append(theAttr->ManglingModuleName.str());
3098+
blob.push_back('\0');
3099+
blob.append(theAttr->LinkerModuleName.str());
30983100
blob.push_back('\0');
30993101
OriginallyDefinedInDeclAttrLayout::emitRecord(
31003102
S.Out, S.ScratchRecord, abbrCode,

stdlib/public/core/CMakeLists.txt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,19 @@ if(SWIFT_STDLIB_HAS_COMMANDLINE)
347347
list(APPEND swift_core_incorporate_object_libraries swiftCommandLineSupport)
348348
endif()
349349

350+
# Backward deployment of Span on Apple platforms is implemented via the
351+
# libswiftCompatibilitySpan.dylib shim.
352+
#
353+
# This flag ensures we emit the correct $ld$previous$ symbols in the standard
354+
# library. When building a binary for an older deployment target, we
355+
# pretend certain symbols are actually in libswiftCompatibilitySpan.dylib.
356+
#
357+
# Further discussion of libswiftCompatibilitySpan.dylib appears below.
358+
#
359+
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
360+
list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-previous-module-installname-map-file" "-Xfrontend" "${CMAKE_CURRENT_SOURCE_DIR}/PreviousModuleInstallName.json")
361+
endif()
362+
350363
set(swiftCore_common_options
351364
IS_STDLIB IS_STDLIB_CORE
352365
${SWIFTLIB_SOURCES}
@@ -424,6 +437,44 @@ add_swift_target_library(swiftCore
424437
zippered
425438
)
426439

440+
# When a binary built with an older deployment target is run with a new
441+
# standard library, the symbols that were previously in the backward
442+
# compatibility shim are now in the standard library. To ensure the
443+
# dynamic linker continues to find these symbols, the compatibility
444+
# shim must be replaced by a symlink to the standard library.
445+
#
446+
# Since we're building the "new" standard library here, we create this
447+
# symlink in the same directory, from libswiftCompatibilitySpan.dylib to
448+
# libswiftCore.dylib.
449+
#
450+
# The sources for the real libswiftCompatibilitySpan.dylib are found in
451+
# stdlib/toolchain/CompatibilitySpan. When running a binary with an old
452+
# standard library, this dynamic library must be present at run time.
453+
#
454+
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
455+
foreach(sdk ${SWIFT_SDKS})
456+
set(lib_dir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}")
457+
set(lib_path "${SWIFTLIB_DIR}/${lib_dir}")
458+
set(compat_lib_name "${lib_path}/libswiftCompatibilitySpan.dylib")
459+
460+
# This doesn't depend on libswiftCore.dylib because we don't actually need
461+
# for it to exist to create the symlink, nor is there any need to recreate
462+
# the symlink if the dylib changes.
463+
add_custom_command_target(unused_var
464+
CUSTOM_TARGET_NAME "swiftCompatibilitySpan-symlink-${lib_dir}"
465+
OUTPUT "${compat_lib_name}"
466+
COMMAND ${CMAKE_COMMAND} "-E" "create_symlink" "${lib_path}/libswiftCore.dylib" "${compat_lib_name}")
467+
foreach(ARCH ${SWIFT_SDK_${sdk}_ARCHITECTURES})
468+
add_dependencies("swiftCore-${lib_dir}-${ARCH}" "swiftCompatibilitySpan-symlink-${lib_dir}")
469+
endforeach()
470+
471+
swift_install_symlink_component(stdlib
472+
LINK_NAME libswiftCompatibilitySpan.dylib
473+
TARGET libswiftCore.dylib
474+
DESTINATION "lib/swift/${lib_dir}")
475+
endforeach()
476+
endif()
477+
427478
# Embedded standard library - embedded libraries are built as .swiftmodule only,
428479
# i.e. there is no .o or .a file produced (no binary code is actually produced)
429480
# and only users of a library are going to actually compile any needed code.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
{
3+
"module": "CompatibilitySpan",
4+
"install_name": "/usr/lib/swift/libswiftCompatibilitySpan.dylib"
5+
}
6+
]

stdlib/public/core/Span/RawSpan.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#if SPAN_COMPATIBILITY_STUB
14+
import Swift
15+
#endif
16+
1317
/// `RawSpan` represents a contiguous region of memory
1418
/// which contains initialized bytes.
1519
///

stdlib/public/core/Span/Span.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#if SPAN_COMPATIBILITY_STUB
14+
import Swift
15+
#endif
16+
1317
/// `Span<Element>` represents a contiguous region of memory
1418
/// which contains initialized instances of `Element`.
1519
///

stdlib/toolchain/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ if(SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT)
5050
add_subdirectory(Compatibility50)
5151
add_subdirectory(Compatibility51)
5252
add_subdirectory(Compatibility56)
53+
add_subdirectory(CompatibilitySpan)
5354
add_subdirectory(CompatibilityDynamicReplacements)
5455
add_subdirectory(CompatibilityConcurrency)
5556
add_subdirectory(CompatibilityThreading)

0 commit comments

Comments
 (0)