Skip to content

Commit bf1164f

Browse files
authored
Merge pull request #60010 from xedin/rdar-82791712
[IRGen] Emit opaque type descriptors into client for `@_alwaysInlineI…
2 parents 33a987f + 76ab70c commit bf1164f

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
@@ -1450,6 +1450,10 @@ private: \
14501450
void emitClassDecl(ClassDecl *D);
14511451
void emitExtension(ExtensionDecl *D);
14521452
void emitOpaqueTypeDecl(OpaqueTypeDecl *D);
1453+
/// This method does additional checking vs. \c emitOpaqueTypeDecl
1454+
/// based on the state and flags associated with the module.
1455+
void maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *D);
1456+
14531457
void emitSILGlobalVariable(SILGlobalVariable *gv);
14541458
void emitCoverageMapping();
14551459
void emitSILFunction(SILFunction *f);
@@ -1772,7 +1776,6 @@ private: \
17721776

17731777
void emitLazyPrivateDefinitions();
17741778
void addRuntimeResolvableType(GenericTypeDecl *nominal);
1775-
void maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *opaque);
17761779

17771780
/// Add all conformances of the given \c IterableDeclContext
17781781
/// LazyWitnessTables.

lib/IRGen/IRGenSIL.cpp

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

2234+
if (CurSILFn->getLinkage() == SILLinkage::Shared) {
2235+
if (auto *V = CurSILFn->getLocation().getAsASTNode<ValueDecl>()) {
2236+
bool alwaysEmitIntoClient =
2237+
V->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>();
2238+
auto *opaqueResult = V->getOpaqueResultTypeDecl();
2239+
// `@_alwaysEmitIntoClient` declaration with opaque result
2240+
// has to emit opaque type descriptor into client module
2241+
// when it has availability conditions because the underlying
2242+
// type in such cases is unknown until runtime.
2243+
if (alwaysEmitIntoClient && opaqueResult &&
2244+
opaqueResult->hasConditionallyAvailableSubstitutions()) {
2245+
IGM.maybeEmitOpaqueTypeDecl(opaqueResult);
2246+
}
2247+
}
2248+
}
2249+
22342250
auto funcTy = CurSILFn->getLoweredFunctionType();
22352251
bool isAsyncFn = funcTy->isAsync();
22362252
if (isAsyncFn && funcTy->getLanguage() == SILFunctionLanguage::Swift) {

lib/IRGen/Linking.cpp

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

726+
case Kind::OpaqueTypeDescriptor: {
727+
auto *opaqueType = cast<OpaqueTypeDecl>(getDecl());
728+
729+
// The opaque result type descriptor with availability conditions
730+
// has to be emitted into a client module when associated with
731+
// `@_alwaysInlineIntoClient` declaration which means it's linkage
732+
// has to be "shared".
733+
if (opaqueType->hasConditionallyAvailableSubstitutions()) {
734+
if (auto *srcDecl = opaqueType->getNamingDecl()) {
735+
if (srcDecl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
736+
return SILLinkage::Shared;
737+
}
738+
}
739+
740+
return getSILLinkage(getDeclLinkage(opaqueType), forDefinition);
741+
}
742+
726743
case Kind::AssociatedConformanceDescriptor:
727744
case Kind::BaseConformanceDescriptor:
728745
case Kind::ObjCClass:
@@ -735,7 +752,6 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
735752
case Kind::ProtocolDescriptorRecord:
736753
case Kind::ProtocolRequirementsBaseDescriptor:
737754
case Kind::MethodLookupFunction:
738-
case Kind::OpaqueTypeDescriptor:
739755
case Kind::OpaqueTypeDescriptorRecord:
740756
case Kind::OpaqueTypeDescriptorAccessor:
741757
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)