Skip to content

Commit 0fdca11

Browse files
committed
[IRGen] Use proper linkage for async function pointers to partial apply forwarders
rdar://163631865 Under certain circumstances the same symbol can be used for different implementations of the forwarders. The forwarders themselves are already emitted with "internal" LLVM linkage, but some particularities in the mapping from SILLinkage to LLVM linkage caused async function pointers to partial apply forwarders to be emitted with linkonce_odr instead, which caused the wrong forwarder to be called at runtime, causing unexpected behavior and crashes.
1 parent 223fc08 commit 0fdca11

File tree

3 files changed

+36
-18
lines changed

3 files changed

+36
-18
lines changed

include/swift/IRGen/Linking.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,6 +1861,15 @@ class LinkEntity {
18611861

18621862
bool isAlwaysSharedLinkage() const;
18631863

1864+
/// Partial apply forwarders always need real private linkage,
1865+
/// to ensure the correct implementation is used in case of
1866+
/// colliding symbols.
1867+
bool privateMeansPrivate() const {
1868+
return getKind() == Kind::PartialApplyForwarder ||
1869+
getKind() == Kind::PartialApplyForwarderAsyncFunctionPointer ||
1870+
getKind() == Kind::PartialApplyForwarderCoroFunctionPointer;
1871+
}
1872+
18641873
/// Whether the link entity's definitions must be considered non-unique.
18651874
///
18661875
/// This applies only in the Embedded Swift linkage model, and is used for

lib/IRGen/GenDecl.cpp

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,11 +2324,11 @@ void IRGenerator::emitEntryPointInfo() {
23242324
IGM.addUsedGlobal(var);
23252325
}
23262326

2327-
static IRLinkage
2328-
getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
2329-
SILLinkage linkage, ForDefinition_t isDefinition,
2330-
bool isWeakImported, bool isKnownLocal,
2331-
bool hasNonUniqueDefinition) {
2327+
static IRLinkage getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
2328+
SILLinkage linkage, ForDefinition_t isDefinition,
2329+
bool isWeakImported, bool isKnownLocal,
2330+
bool hasNonUniqueDefinition,
2331+
bool privateMeansPrivate) {
23322332
#define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE) \
23332333
IRLinkage{llvm::GlobalValue::LINKAGE##Linkage, \
23342334
llvm::GlobalValue::VISIBILITY##Visibility, \
@@ -2390,12 +2390,15 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
23902390
case SILLinkage::Private: {
23912391
if (info.forcePublicDecls() && !isDefinition)
23922392
return getIRLinkage(name, info, SILLinkage::PublicExternal, isDefinition,
2393-
isWeakImported, isKnownLocal, hasNonUniqueDefinition);
2394-
2395-
auto linkage = info.needLinkerToMergeDuplicateSymbols()
2396-
? llvm::GlobalValue::LinkOnceODRLinkage
2397-
: llvm::GlobalValue::InternalLinkage;
2398-
auto visibility = info.shouldAllPrivateDeclsBeVisibleFromOtherFiles()
2393+
isWeakImported, isKnownLocal, hasNonUniqueDefinition,
2394+
privateMeansPrivate);
2395+
2396+
auto linkage =
2397+
info.needLinkerToMergeDuplicateSymbols() && !privateMeansPrivate
2398+
? llvm::GlobalValue::LinkOnceODRLinkage
2399+
: llvm::GlobalValue::InternalLinkage;
2400+
auto visibility = info.shouldAllPrivateDeclsBeVisibleFromOtherFiles() &&
2401+
!privateMeansPrivate
23992402
? llvm::GlobalValue::HiddenVisibility
24002403
: llvm::GlobalValue::DefaultVisibility;
24012404
return {linkage, visibility, llvm::GlobalValue::DefaultStorageClass};
@@ -2446,8 +2449,8 @@ void irgen::updateLinkageForDefinition(IRGenModule &IGM,
24462449
auto IRL =
24472450
getIRLinkage(global->hasName() ? global->getName() : StringRef(),
24482451
linkInfo, entity.getLinkage(ForDefinition), ForDefinition,
2449-
weakImported, isKnownLocal,
2450-
entity.hasNonUniqueDefinition());
2452+
weakImported, isKnownLocal, entity.hasNonUniqueDefinition(),
2453+
entity.privateMeansPrivate());
24512454
ApplyIRLinkage(IRL).to(global);
24522455

24532456
LinkInfo link = LinkInfo::get(IGM, entity, ForDefinition);
@@ -2498,10 +2501,10 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
24982501
}
24992502

25002503
bool weakImported = entity.isWeakImported(swiftModule);
2501-
result.IRL = getIRLinkage(result.Name, linkInfo,
2502-
entity.getLinkage(isDefinition), isDefinition,
2503-
weakImported, isKnownLocal,
2504-
entity.hasNonUniqueDefinition());
2504+
result.IRL = getIRLinkage(
2505+
result.Name, linkInfo, entity.getLinkage(isDefinition), isDefinition,
2506+
weakImported, isKnownLocal, entity.hasNonUniqueDefinition(),
2507+
entity.privateMeansPrivate());
25052508
result.ForDefinition = isDefinition;
25062509
return result;
25072510
}
@@ -2513,7 +2516,8 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo, StringRef name,
25132516
result.Name += name;
25142517
result.IRL = getIRLinkage(name, linkInfo, linkage, isDefinition,
25152518
isWeakImported, linkInfo.Internalize,
2516-
/*hasNonUniqueDefinition=*/false);
2519+
/*hasNonUniqueDefinition=*/false,
2520+
/*privateMeansPrivate=*/false);
25172521
result.ForDefinition = isDefinition;
25182522
return result;
25192523
}

test/IRGen/async/partial_apply_forwarder.sil

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ entry(%e : $EmptyType, %b : $WeakBox<τ_0_0>):
8989
unreachable
9090
}
9191

92+
// CHECK-DAG: @"$s7takingQTATu" = internal
93+
// CHECK-DAG: @"$s11takingQAndSTATu" = internal
94+
// CHECK-DAG: @"$s13inner_closureTATu" = internal
95+
// CHECK-DAG: @"$s15returns_closureTATu" = internal
96+
9297
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swift{{(tail)?}}cc void @bind_polymorphic_param_from_context(
9398
// CHECK-LABEL: define internal swift{{(tail)?}}cc void @"$s7takingQTA"(
9499
sil public @bind_polymorphic_param_from_context : $@async @convention(thin) <τ_0_1>(@in τ_0_1) -> @owned @async @callee_guaranteed () -> () {

0 commit comments

Comments
 (0)