Skip to content

Commit 8d15f81

Browse files
Merge pull request #4699 from swiftwasm/release/5.7
[pull] swiftwasm-release/5.7 from release/5.7
2 parents 974a1c0 + 7c9a716 commit 8d15f81

File tree

9 files changed

+112
-3
lines changed

9 files changed

+112
-3
lines changed

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1598,7 +1598,7 @@ class TypeRefBuilder {
15981598
// is an offset to a TypeRef string, read it.
15991599
auto readRequirementTypeRefAddress =
16001600
[&](uintptr_t offsetFromOpaqueDescBase,
1601-
uintptr_t requirementAddress) -> uint32_t {
1601+
uintptr_t requirementAddress) -> uintptr_t {
16021602
std::string typeRefString = "";
16031603
auto fieldOffsetOffset = requirementAddress + offsetFromOpaqueDescBase -
16041604
(uintptr_t)opaqueTypeDescriptor;

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/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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,19 @@ void IRGenSILFunction::emitSILFunction() {
22202220
if (CurSILFn->getDynamicallyReplacedFunction())
22212221
IGM.IRGen.addDynamicReplacement(CurSILFn);
22222222

2223+
if (CurSILFn->getLinkage() == SILLinkage::Shared) {
2224+
if (CurSILFn->markedAsAlwaysEmitIntoClient() &&
2225+
CurSILFn->hasOpaqueResultTypeWithAvailabilityConditions()) {
2226+
auto *V = CurSILFn->getLocation().castToASTNode<ValueDecl>();
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+
IGM.maybeEmitOpaqueTypeDecl(opaqueResult);
2233+
}
2234+
}
2235+
22232236
auto funcTy = CurSILFn->getLoweredFunctionType();
22242237
bool isAsyncFn = funcTy->isAsync();
22252238
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:

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

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)