Skip to content

Commit ee5f7e9

Browse files
committed
[IRGen] Emit opaque type descriptors into client for @_alwaysEmitIntoClient decls
If opaque result type has availability conditions and is associated with an `@_alwaysEmitIntoClient` declaration, its metadata descriptor has to be emitted into a client module because the body of the inlined function depends on it for the runtime information about the underlying type. Resolves: rdar://82791712 (cherry picked from commit 76ab70c)
1 parent d6e5805 commit ee5f7e9

File tree

6 files changed

+81
-2
lines changed

6 files changed

+81
-2
lines changed

lib/IRGen/IRGenModule.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,10 @@ private: \
14421442
void emitClassDecl(ClassDecl *D);
14431443
void emitExtension(ExtensionDecl *D);
14441444
void emitOpaqueTypeDecl(OpaqueTypeDecl *D);
1445+
/// This method does additional checking vs. \c emitOpaqueTypeDecl
1446+
/// based on the state and flags associated with the module.
1447+
void maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *D);
1448+
14451449
void emitSILGlobalVariable(SILGlobalVariable *gv);
14461450
void emitCoverageMapping();
14471451
void emitSILFunction(SILFunction *f);
@@ -1764,7 +1768,6 @@ private: \
17641768

17651769
void emitLazyPrivateDefinitions();
17661770
void addRuntimeResolvableType(GenericTypeDecl *nominal);
1767-
void maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *opaque);
17681771

17691772
/// Add all conformances of the given \c IterableDeclContext
17701773
/// LazyWitnessTables.

lib/IRGen/IRGenSIL.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,22 @@ void IRGenSILFunction::emitSILFunction() {
22202220
if (CurSILFn->getDynamicallyReplacedFunction())
22212221
IGM.IRGen.addDynamicReplacement(CurSILFn);
22222222

2223+
if (CurSILFn->getLinkage() == SILLinkage::Shared) {
2224+
if (auto *V = CurSILFn->getLocation().getAsASTNode<ValueDecl>()) {
2225+
bool alwaysEmitIntoClient =
2226+
V->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>();
2227+
auto *opaqueResult = V->getOpaqueResultTypeDecl();
2228+
// `@_alwaysEmitIntoClient` declaration with opaque result
2229+
// has to emit opaque type descriptor into client module
2230+
// when it has availability conditions because the underlying
2231+
// type in such cases is unknown until runtime.
2232+
if (alwaysEmitIntoClient && opaqueResult &&
2233+
opaqueResult->hasConditionallyAvailableSubstitutions()) {
2234+
IGM.maybeEmitOpaqueTypeDecl(opaqueResult);
2235+
}
2236+
}
2237+
}
2238+
22232239
auto funcTy = CurSILFn->getLoweredFunctionType();
22242240
bool isAsyncFn = funcTy->isAsync();
22252241
if (isAsyncFn && funcTy->getLanguage() == SILFunctionLanguage::Swift) {

lib/IRGen/Linking.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,23 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
708708
return getSILLinkage(getDeclLinkage(getterDecl), forDefinition);
709709
}
710710

711+
case Kind::OpaqueTypeDescriptor: {
712+
auto *opaqueType = cast<OpaqueTypeDecl>(getDecl());
713+
714+
// The opaque result type descriptor with availability conditions
715+
// has to be emitted into a client module when associated with
716+
// `@_alwaysEmitIntoClient` declaration which means it's linkage
717+
// has to be "shared".
718+
if (opaqueType->hasConditionallyAvailableSubstitutions()) {
719+
if (auto *srcDecl = opaqueType->getNamingDecl()) {
720+
if (srcDecl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
721+
return SILLinkage::Shared;
722+
}
723+
}
724+
725+
return getSILLinkage(getDeclLinkage(opaqueType), forDefinition);
726+
}
727+
711728
case Kind::AssociatedConformanceDescriptor:
712729
case Kind::BaseConformanceDescriptor:
713730
case Kind::ObjCClass:
@@ -720,7 +737,6 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
720737
case Kind::ProtocolDescriptorRecord:
721738
case Kind::ProtocolRequirementsBaseDescriptor:
722739
case Kind::MethodLookupFunction:
723-
case Kind::OpaqueTypeDescriptor:
724740
case Kind::OpaqueTypeDescriptorRecord:
725741
case Kind::OpaqueTypeDescriptorAccessor:
726742
case Kind::OpaqueTypeDescriptorAccessorImpl:
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
public protocol P {
2+
}
3+
4+
extension Int : P {
5+
}
6+
7+
extension Double : P {
8+
}
9+
10+
@_alwaysEmitIntoClient
11+
public func testInlineWithOpaque() -> some P {
12+
if #available(macOS 9.0, *) {
13+
return 1
14+
}
15+
return 2.0
16+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
public protocol P {
2+
}
3+
4+
extension Int : P {
5+
}
6+
7+
extension Double : P {
8+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -emit-library -emit-module-path %t/AlwaysInlineIntoWithOpaque.swiftmodule -module-name AlwaysInlineIntoWithOpaque %S/Inputs/AlwaysInlineIntoWithOpaque.swift -o %t/%target-library-name(AlwaysInlineIntoWithOpaque)
3+
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -lAlwaysInlineIntoWithOpaque -module-name main -I %t -L %t %s -o %t/a.out
4+
// RUN: %target-run %t/a.out | %FileCheck %s
5+
6+
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -emit-library -emit-module-path %t/AlwaysInlineIntoWithOpaque.swiftmodule -module-name AlwaysInlineIntoWithOpaque %S/Inputs/AlwaysInlineIntoWithOpaqueReplacement.swift -o %t/%target-library-name(AlwaysInlineIntoWithOpaque)
7+
// RUN: %target-run %t/a.out | %FileCheck %s
8+
9+
// REQUIRES: OS=macosx && (CPU=x86_64 || CPU=arm64)
10+
// REQUIRES: executable_test
11+
12+
import AlwaysInlineIntoWithOpaque
13+
14+
public func test() {
15+
let p = testInlineWithOpaque()
16+
print(p)
17+
}
18+
19+
test()
20+
// CHECK: 1

0 commit comments

Comments
 (0)