Skip to content

Commit eeee799

Browse files
committed
[SIL] Keep alive @_alwaysEmitIntoClient decls with opaque result types
If such declarations have availability conditions they have to be kept alive until IRGen to emit opaque type descriptor that is going be used at runtime to determine the underlying type. This is important for "optimized" mode only because in non-optimized mode "shared" symbol survives SILGen.
1 parent ee5f7e9 commit eeee799

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,32 @@ class SILFunction
11211121
return false;
11221122
}
11231123

1124+
/// Returns true if this function belongs to a declaration that
1125+
/// has `@_alwaysEmitIntoClient` attribute.
1126+
bool markedAsAlwaysEmitIntoClient() const {
1127+
if (!hasLocation())
1128+
return false;
1129+
1130+
auto *V = getLocation().getAsASTNode<ValueDecl>();
1131+
return V && V->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>();
1132+
}
1133+
1134+
/// Returns true if this function belongs to a declaration that returns
1135+
/// an opaque result type with one or more availability conditions that are
1136+
/// allowed to produce a different underlying type at runtime.
1137+
bool hasOpaqueResultTypeWithAvailabilityConditions() const {
1138+
if (!hasLocation())
1139+
return false;
1140+
1141+
if (auto *V = getLocation().getAsASTNode<ValueDecl>()) {
1142+
auto *opaqueResult = V->getOpaqueResultTypeDecl();
1143+
return opaqueResult &&
1144+
opaqueResult->hasConditionallyAvailableSubstitutions();
1145+
}
1146+
1147+
return false;
1148+
}
1149+
11241150
//===--------------------------------------------------------------------===//
11251151
// Block List Access
11261152
//===--------------------------------------------------------------------===//

lib/IRGen/IRGenSIL.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,18 +2221,15 @@ void IRGenSILFunction::emitSILFunction() {
22212221
IGM.IRGen.addDynamicReplacement(CurSILFn);
22222222

22232223
if (CurSILFn->getLinkage() == SILLinkage::Shared) {
2224-
if (auto *V = CurSILFn->getLocation().getAsASTNode<ValueDecl>()) {
2225-
bool alwaysEmitIntoClient =
2226-
V->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>();
2224+
if (CurSILFn->markedAsAlwaysEmitIntoClient() &&
2225+
CurSILFn->hasOpaqueResultTypeWithAvailabilityConditions()) {
2226+
auto *V = CurSILFn->getLocation().castToASTNode<ValueDecl>();
22272227
auto *opaqueResult = V->getOpaqueResultTypeDecl();
22282228
// `@_alwaysEmitIntoClient` declaration with opaque result
22292229
// has to emit opaque type descriptor into client module
22302230
// when it has availability conditions because the underlying
22312231
// type in such cases is unknown until runtime.
2232-
if (alwaysEmitIntoClient && opaqueResult &&
2233-
opaqueResult->hasConditionallyAvailableSubstitutions()) {
2234-
IGM.maybeEmitOpaqueTypeDecl(opaqueResult);
2235-
}
2232+
IGM.maybeEmitOpaqueTypeDecl(opaqueResult);
22362233
}
22372234
}
22382235

lib/SIL/IR/SILFunction.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,13 @@ SILFunction::isPossiblyUsedExternally() const {
704704
if (isDistributed() && isThunk())
705705
return true;
706706

707+
// Declaration marked as `@_alwaysEmitIntoClient` that
708+
// returns opaque result type with availability conditions
709+
// has to be kept alive to emit opaque type metadata descriptor.
710+
if (markedAsAlwaysEmitIntoClient() &&
711+
hasOpaqueResultTypeWithAvailabilityConditions())
712+
return true;
713+
707714
return swift::isPossiblyUsedExternally(linkage, getModule().isWholeModule());
708715
}
709716

0 commit comments

Comments
 (0)