Skip to content

Commit 43a7b44

Browse files
Merge pull request #24201 from aschwaighofer/opaque_result_types_dyn_replacement_and_specialization
Opaque result types: dynamic replacement
2 parents 54af09a + f55d68d commit 43a7b44

25 files changed

+725
-62
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4685,6 +4685,10 @@ class AbstractStorageDecl : public ValueDecl {
46854685

46864686
bool hasDidSetOrWillSetDynamicReplacement() const;
46874687

4688+
bool hasAnyNativeDynamicAccessors() const;
4689+
4690+
bool hasAnyDynamicReplacementAccessors() const;
4691+
46884692
OpaqueTypeDecl *getOpaqueResultTypeDecl() const {
46894693
return OpaqueReturn;
46904694
}

include/swift/AST/Types.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,9 @@ enum class TypeMatchFlags {
257257
///
258258
/// This is necessary because Objective-C allows optional function paramaters
259259
/// to be non-escaping, but Swift currently does not.
260-
IgnoreNonEscapingForOptionalFunctionParam = 1 << 4
260+
IgnoreNonEscapingForOptionalFunctionParam = 1 << 4,
261+
/// Allow compatible opaque archetypes.
262+
AllowCompatibleOpaqueTypeArchetypes = 1 << 5
261263
};
262264
using TypeMatchOptions = OptionSet<TypeMatchFlags>;
263265

include/swift/Demangling/DemangleNodes.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ NODE(AccessorFunctionReference)
266266
NODE(OpaqueType)
267267
NODE(OpaqueTypeDescriptorSymbolicReference)
268268
NODE(OpaqueTypeDescriptor)
269+
NODE(OpaqueTypeDescriptorAccessor)
270+
NODE(OpaqueTypeDescriptorAccessorImpl)
271+
NODE(OpaqueTypeDescriptorAccessorKey)
272+
NODE(OpaqueTypeDescriptorAccessorVar)
269273
NODE(OpaqueReturnType)
270274
CONTEXT_NODE(OpaqueReturnTypeOf)
271275

include/swift/IRGen/Linking.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,24 @@ class LinkEntity {
200200
/// The pointer is an OpaqueTypeDecl*.
201201
OpaqueTypeDescriptor,
202202

203+
/// The descriptor accessor for an opaque type used for dynamic functions.
204+
/// The pointer is an OpaqueTypeDecl*.
205+
OpaqueTypeDescriptorAccessor,
206+
207+
/// The descriptor accessor implementation for an opaque type used for
208+
/// dynamic functions.
209+
/// The pointer is an OpaqueTypeDecl*.
210+
OpaqueTypeDescriptorAccessorImpl,
211+
212+
/// The descriptor accessor key of dynamic replacements for an opaque type.
213+
/// The pointer is an OpaqueTypeDecl*.
214+
OpaqueTypeDescriptorAccessorKey,
215+
216+
/// The descriptor accessor variable of dynamic replacements for an opaque
217+
/// type.
218+
/// The pointer is an OpaqueTypeDecl*.
219+
OpaqueTypeDescriptorAccessorVar,
220+
203221
/// The metadata pattern for a generic nominal type.
204222
/// The pointer is a NominalTypeDecl*.
205223
TypeMetadataPattern,
@@ -706,6 +724,30 @@ class LinkEntity {
706724
return entity;
707725
}
708726

727+
static LinkEntity forOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *decl) {
728+
LinkEntity entity;
729+
entity.setForDecl(Kind::OpaqueTypeDescriptorAccessor, decl);
730+
return entity;
731+
}
732+
733+
static LinkEntity forOpaqueTypeDescriptorAccessorImpl(OpaqueTypeDecl *decl) {
734+
LinkEntity entity;
735+
entity.setForDecl(Kind::OpaqueTypeDescriptorAccessorImpl, decl);
736+
return entity;
737+
}
738+
739+
static LinkEntity forOpaqueTypeDescriptorAccessorKey(OpaqueTypeDecl *decl) {
740+
LinkEntity entity;
741+
entity.setForDecl(Kind::OpaqueTypeDescriptorAccessorKey, decl);
742+
return entity;
743+
}
744+
745+
static LinkEntity forOpaqueTypeDescriptorAccessorVar(OpaqueTypeDecl *decl) {
746+
LinkEntity entity;
747+
entity.setForDecl(Kind::OpaqueTypeDescriptorAccessorVar, decl);
748+
return entity;
749+
}
750+
709751
static LinkEntity forPropertyDescriptor(AbstractStorageDecl *decl) {
710752
assert(decl->exportsPropertyDescriptor());
711753
LinkEntity entity;

lib/AST/Decl.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4518,6 +4518,21 @@ bool AbstractStorageDecl::hasDidSetOrWillSetDynamicReplacement() const {
45184518
return false;
45194519
}
45204520

4521+
bool AbstractStorageDecl::hasAnyNativeDynamicAccessors() const {
4522+
for (auto accessor : getAllAccessors()) {
4523+
if (accessor->isNativeDynamic())
4524+
return true;
4525+
}
4526+
return false;
4527+
}
4528+
4529+
bool AbstractStorageDecl::hasAnyDynamicReplacementAccessors() const {
4530+
for (auto accessor : getAllAccessors()) {
4531+
if (accessor->getAttrs().hasAttribute<DynamicReplacementAttr>())
4532+
return true;
4533+
}
4534+
return false;
4535+
}
45214536
void AbstractStorageDecl::setAccessors(StorageImplInfo implInfo,
45224537
SourceLoc lbraceLoc,
45234538
ArrayRef<AccessorDecl *> accessors,

lib/AST/Type.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,6 +2293,13 @@ static bool matches(CanType t1, CanType t2, TypeMatchOptions matchMode,
22932293
if (isABICompatibleEvenAddingOptional(t1, t2))
22942294
return true;
22952295

2296+
if (matchMode.contains(TypeMatchFlags::AllowCompatibleOpaqueTypeArchetypes))
2297+
if (auto opaque1 = t1->getAs<OpaqueTypeArchetypeType>())
2298+
if (auto opaque2 = t2->getAs<OpaqueTypeArchetypeType>())
2299+
return opaque1->getBoundSignature() == opaque2->getBoundSignature() &&
2300+
opaque1->getInterfaceType()->getCanonicalType()->matches(
2301+
opaque2->getInterfaceType()->getCanonicalType(), matchMode);
2302+
22962303
return false;
22972304
}
22982305

lib/Demangling/Demangler.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,6 +1806,18 @@ NodePointer Demangler::demangleMetatype() {
18061806
return createWithPoppedType(Node::Kind::GenericTypeMetadataPattern);
18071807
case 'a':
18081808
return createWithPoppedType(Node::Kind::TypeMetadataAccessFunction);
1809+
case 'g':
1810+
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessor,
1811+
popNode());
1812+
case 'h':
1813+
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessorImpl,
1814+
popNode());
1815+
case 'j':
1816+
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessorKey,
1817+
popNode());
1818+
case 'k':
1819+
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessorVar,
1820+
popNode());
18091821
case 'I':
18101822
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationCache);
18111823
case 'i':

lib/Demangling/NodePrinter.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,10 @@ class NodePrinter {
415415
case Node::Kind::ObjCMetadataUpdateFunction:
416416
case Node::Kind::ObjCResilientClassStub:
417417
case Node::Kind::OpaqueTypeDescriptor:
418+
case Node::Kind::OpaqueTypeDescriptorAccessor:
419+
case Node::Kind::OpaqueTypeDescriptorAccessorImpl:
420+
case Node::Kind::OpaqueTypeDescriptorAccessorKey:
421+
case Node::Kind::OpaqueTypeDescriptorAccessorVar:
418422
case Node::Kind::Owned:
419423
case Node::Kind::OwningAddressor:
420424
case Node::Kind::OwningMutableAddressor:
@@ -1733,6 +1737,22 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
17331737
Printer << "opaque type descriptor for ";
17341738
print(Node->getChild(0));
17351739
return nullptr;
1740+
case Node::Kind::OpaqueTypeDescriptorAccessor:
1741+
Printer << "opaque type descriptor accessor for ";
1742+
print(Node->getChild(0));
1743+
return nullptr;
1744+
case Node::Kind::OpaqueTypeDescriptorAccessorImpl:
1745+
Printer << "opaque type descriptor accessor impl for ";
1746+
print(Node->getChild(0));
1747+
return nullptr;
1748+
case Node::Kind::OpaqueTypeDescriptorAccessorKey:
1749+
Printer << "opaque type descriptor accessor key for ";
1750+
print(Node->getChild(0));
1751+
return nullptr;
1752+
case Node::Kind::OpaqueTypeDescriptorAccessorVar:
1753+
Printer << "opaque type descriptor accessor var for ";
1754+
print(Node->getChild(0));
1755+
return nullptr;
17361756
case Node::Kind::CoroutineContinuationPrototype:
17371757
Printer << "coroutine continuation prototype for ";
17381758
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,6 +2038,18 @@ void Remangler::mangleOpaqueType(Node *node) {
20382038
void Remangler::mangleOpaqueTypeDescriptor(Node *node) {
20392039
unreachable("unsupported");
20402040
}
2041+
void Remangler::mangleOpaqueTypeDescriptorAccessor(Node *node) {
2042+
unreachable("unsupported");
2043+
}
2044+
void Remangler::mangleOpaqueTypeDescriptorAccessorImpl(Node *node) {
2045+
unreachable("unsupported");
2046+
}
2047+
void Remangler::mangleOpaqueTypeDescriptorAccessorKey(Node *node) {
2048+
unreachable("unsupported");
2049+
}
2050+
void Remangler::mangleOpaqueTypeDescriptorAccessorVar(Node *node) {
2051+
unreachable("unsupported");
2052+
}
20412053
void Remangler::mangleAccessorFunctionReference(Node *node) {
20422054
unreachable("can't remangle");
20432055
}

lib/Demangling/Remangler.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,26 @@ void Remangler::mangleOpaqueTypeDescriptor(Node *node) {
15991599
Buffer << "MQ";
16001600
}
16011601

1602+
void Remangler::mangleOpaqueTypeDescriptorAccessor(Node *node) {
1603+
mangleSingleChildNode(node);
1604+
Buffer << "Mg";
1605+
}
1606+
1607+
void Remangler::mangleOpaqueTypeDescriptorAccessorImpl(Node *node) {
1608+
mangleSingleChildNode(node);
1609+
Buffer << "Mh";
1610+
}
1611+
1612+
void Remangler::mangleOpaqueTypeDescriptorAccessorKey(Node *node) {
1613+
mangleSingleChildNode(node);
1614+
Buffer << "Mj";
1615+
}
1616+
1617+
void Remangler::mangleOpaqueTypeDescriptorAccessorVar(Node *node) {
1618+
mangleSingleChildNode(node);
1619+
Buffer << "Mk";
1620+
}
1621+
16021622
void Remangler::manglePropertyDescriptor(Node *node) {
16031623
mangleSingleChildNode(node);
16041624
Buffer << "MV";

lib/IRGen/GenArchetype.cpp

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/ASTContext.h"
2020
#include "swift/AST/Decl.h"
2121
#include "swift/AST/GenericEnvironment.h"
22+
#include "swift/AST/IRGenOptions.h"
2223
#include "swift/AST/Types.h"
2324
#include "swift/IRGen/Linking.h"
2425
#include "swift/SIL/SILValue.h"
@@ -389,7 +390,6 @@ llvm::Value *irgen::emitDynamicTypeOfOpaqueArchetype(IRGenFunction &IGF,
389390
Address addr,
390391
SILType type) {
391392
auto archetype = type.castTo<ArchetypeType>();
392-
393393
// Acquire the archetype's static metadata.
394394
llvm::Value *metadata =
395395
emitArchetypeTypeMetadataRef(IGF, archetype, MetadataState::Complete)
@@ -450,14 +450,51 @@ withOpaqueTypeGenericArgs(IRGenFunction &IGF,
450450
}
451451
}
452452

453+
bool shouldUseOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *opaque) {
454+
auto *namingDecl = opaque->getNamingDecl();
455+
auto *abstractStorage = dyn_cast<AbstractStorageDecl>(namingDecl);
456+
457+
// Don't emit accessors for abstract storage that is not dynamic or a dynamic
458+
// replacement.
459+
if (abstractStorage) {
460+
return abstractStorage->hasAnyNativeDynamicAccessors() ||
461+
abstractStorage->hasAnyDynamicReplacementAccessors();
462+
}
463+
464+
// Don't emit accessors for functions that are not dynamic or dynamic
465+
// replacements.
466+
return opaque->getNamingDecl()->isNativeDynamic() ||
467+
opaque->getNamingDecl()
468+
->getAttrs()
469+
.hasAttribute<DynamicReplacementAttr>();
470+
}
471+
472+
static llvm::Value *
473+
getAddressOfOpaqueTypeDescriptor(IRGenFunction &IGF,
474+
OpaqueTypeDecl *opaqueDecl) {
475+
auto &IGM = IGF.IGM;
476+
477+
// Support dynamically replacing the return type as part of dynamic function
478+
// replacement.
479+
if (!IGM.getOptions().shouldOptimize() &&
480+
shouldUseOpaqueTypeDescriptorAccessor(opaqueDecl)) {
481+
auto descriptorAccessor = IGM.getAddrOfOpaqueTypeDescriptorAccessFunction(
482+
opaqueDecl, NotForDefinition, false);
483+
auto desc = IGF.Builder.CreateCall(descriptorAccessor, {});
484+
desc->setDoesNotThrow();
485+
desc->setCallingConv(IGM.SwiftCC);
486+
return desc;
487+
}
488+
return IGM.getAddrOfOpaqueTypeDescriptor(opaqueDecl, ConstantInit());
489+
}
490+
453491
MetadataResponse irgen::emitOpaqueTypeMetadataRef(IRGenFunction &IGF,
454492
CanOpaqueTypeArchetypeType archetype,
455493
DynamicMetadataRequest request) {
456494
auto accessorFn = IGF.IGM.getGetOpaqueTypeMetadataFn();
457495
auto opaqueDecl = archetype->getDecl();
458-
auto descriptor = IGF.IGM
459-
.getAddrOfOpaqueTypeDescriptor(opaqueDecl, ConstantInit());
460496

497+
auto *descriptor = getAddressOfOpaqueTypeDescriptor(IGF, opaqueDecl);
461498
auto indexValue = llvm::ConstantInt::get(IGF.IGM.SizeTy, 0);
462499

463500
llvm::CallInst *result = nullptr;
@@ -482,8 +519,9 @@ llvm::Value *irgen::emitOpaqueTypeWitnessTableRef(IRGenFunction &IGF,
482519
ProtocolDecl *protocol) {
483520
auto accessorFn = IGF.IGM.getGetOpaqueTypeConformanceFn();
484521
auto opaqueDecl = archetype->getDecl();
485-
auto descriptor = IGF.IGM
486-
.getAddrOfOpaqueTypeDescriptor(opaqueDecl, ConstantInit());
522+
523+
524+
llvm::Value *descriptor = getAddressOfOpaqueTypeDescriptor(IGF, opaqueDecl);
487525

488526
auto foundProtocol = std::find(archetype->getConformsTo().begin(),
489527
archetype->getConformsTo().end(),

0 commit comments

Comments
 (0)