Skip to content

Commit 9bd97ea

Browse files
authored
Merge pull request swiftlang#26542 from jckarter/opaque-type-metadata-peephole
IRGen: Peephole metadata requests for opaque types.
2 parents 1918a3d + 8bd2319 commit 9bd97ea

14 files changed

+178
-18
lines changed

lib/AST/Type.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2551,6 +2551,10 @@ bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
25512551
OpaqueTypeDecl *opaque, ModuleDecl *contextModule,
25522552
ResilienceExpansion contextExpansion) {
25532553
auto namingDecl = opaque->getNamingDecl();
2554+
2555+
// Don't allow replacement if the naming decl is dynamically replaceable.
2556+
if (namingDecl && namingDecl->isDynamic())
2557+
return false;
25542558

25552559
// Allow replacement of opaque result types of inlineable function regardless
25562560
// of resilience and in which context.

lib/IRGen/GenProto.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2739,6 +2739,12 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
27392739
assert(Lowering::TypeConverter::protocolRequiresWitnessTable(proto)
27402740
&& "protocol does not have witness tables?!");
27412741

2742+
// Look through any opaque types we're allowed to.
2743+
if (srcType->hasOpaqueArchetype()) {
2744+
std::tie(srcType, conformance) =
2745+
IGF.IGM.substOpaqueTypesWithUnderlyingTypes(srcType, conformance);
2746+
}
2747+
27422748
// If we don't have concrete conformance information, the type must be
27432749
// an archetype and the conformance must be via one of the protocol
27442750
// requirements of the archetype. Look at what's locally bound.

lib/IRGen/GenReflection.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ IRGenModule::getTypeRef(Type type, GenericSignature *genericSig,
176176

177177
std::pair<llvm::Constant *, unsigned>
178178
IRGenModule::getTypeRef(CanType type, MangledTypeRefRole role) {
179+
type = substOpaqueTypesWithUnderlyingTypes(type);
180+
179181
switch (role) {
180182
case MangledTypeRefRole::DefaultAssociatedTypeWitness:
181183
case MangledTypeRefRole::Metadata:
@@ -209,6 +211,9 @@ IRGenModule::emitWitnessTableRefString(CanType type,
209211
ProtocolConformanceRef conformance,
210212
GenericSignature *origGenericSig,
211213
bool shouldSetLowBit) {
214+
std::tie(type, conformance)
215+
= substOpaqueTypesWithUnderlyingTypes(type, conformance);
216+
212217
auto origType = type;
213218
CanGenericSignature genericSig;
214219
SmallVector<GenericRequirement, 4> requirements;

lib/IRGen/GenType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1606,7 +1606,7 @@ const TypeInfo *TypeConverter::getTypeEntry(CanType canonicalTy) {
16061606
return it->second;
16071607
}
16081608
}
1609-
1609+
16101610
// If the type is dependent, substitute it into our current context.
16111611
auto contextTy = canonicalTy;
16121612
if (contextTy->hasTypeParameter()) {

lib/IRGen/IRGenModule.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,13 @@ class IRGenModule {
820820
}
821821

822822
clang::CodeGen::CodeGenModule &getClangCGM() const;
823+
824+
CanType getRuntimeReifiedType(CanType type);
825+
CanType substOpaqueTypesWithUnderlyingTypes(CanType type);
826+
SILType substOpaqueTypesWithUnderlyingTypes(SILType type);
827+
std::pair<CanType, ProtocolConformanceRef>
828+
substOpaqueTypesWithUnderlyingTypes(CanType type,
829+
ProtocolConformanceRef conformance);
823830

824831
bool isResilient(NominalTypeDecl *decl, ResilienceExpansion expansion);
825832
bool hasResilientMetadata(ClassDecl *decl, ResilienceExpansion expansion);

lib/IRGen/IRGenSIL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,7 @@ class IRGenSILFunction :
857857
/// TODO: just make sure that we have a path to them that the debug info
858858
/// can follow.
859859
void bindArchetypes(swift::Type Ty) {
860-
auto runtimeTy = getRuntimeReifiedType(IGM, Ty->getCanonicalType());
860+
auto runtimeTy = IGM.getRuntimeReifiedType(Ty->getCanonicalType());
861861
if (!IGM.IRGen.Opts.shouldOptimize() && runtimeTy->hasArchetype())
862862
runtimeTy.visit([&](CanType t) {
863863
if (auto archetype = dyn_cast<ArchetypeType>(t))

lib/IRGen/MetadataRequest.cpp

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,8 +501,9 @@ static bool isTypeErasedGenericClassType(CanType type) {
501501
}
502502

503503
// Get the type that exists at runtime to represent a compile-time type.
504-
CanType
505-
irgen::getRuntimeReifiedType(IRGenModule &IGM, CanType type) {
504+
CanType IRGenModule::getRuntimeReifiedType(CanType type) {
505+
// Leave type-erased ObjC generics with their generic arguments unbound, since
506+
// the arguments do not exist at runtime.
506507
return CanType(type.transform([&](Type t) -> Type {
507508
if (isTypeErasedGenericClassType(CanType(t))) {
508509
return t->getAnyNominal()->getDeclaredType()->getCanonicalType();
@@ -511,6 +512,53 @@ irgen::getRuntimeReifiedType(IRGenModule &IGM, CanType type) {
511512
}));
512513
}
513514

515+
CanType IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type) {
516+
// Substitute away opaque types whose underlying types we're allowed to
517+
// assume are constant.
518+
if (type->hasOpaqueArchetype()) {
519+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
520+
ResilienceExpansion::Maximal);
521+
type = type.subst(replacer, replacer,
522+
SubstFlags::SubstituteOpaqueArchetypes)
523+
->getCanonicalType();
524+
}
525+
526+
return type;
527+
}
528+
529+
SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes(SILType type) {
530+
// Substitute away opaque types whose underlying types we're allowed to
531+
// assume are constant.
532+
if (type.getASTType()->hasOpaqueArchetype()) {
533+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
534+
ResilienceExpansion::Maximal);
535+
type = type.subst(getSILModule(), replacer, replacer,
536+
CanGenericSignature(),
537+
/*substitute opaque*/ true);
538+
}
539+
540+
return type;
541+
}
542+
543+
std::pair<CanType, ProtocolConformanceRef>
544+
IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type,
545+
ProtocolConformanceRef conformance) {
546+
// Substitute away opaque types whose underlying types we're allowed to
547+
// assume are constant.
548+
if (type->hasOpaqueArchetype()) {
549+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
550+
ResilienceExpansion::Maximal);
551+
conformance = conformance.subst(type, replacer, replacer,
552+
SubstFlags::SubstituteOpaqueArchetypes);
553+
type = type.subst(replacer, replacer,
554+
SubstFlags::SubstituteOpaqueArchetypes)
555+
->getCanonicalType();
556+
}
557+
558+
return std::make_pair(type, conformance);
559+
}
560+
561+
514562
/// Attempts to return a constant heap metadata reference for a
515563
/// class type. This is generally only valid for specific kinds of
516564
/// ObjC reference, like superclasses or category references.
@@ -2313,7 +2361,9 @@ llvm::Value *IRGenFunction::emitTypeMetadataRef(CanType type) {
23132361
MetadataResponse
23142362
IRGenFunction::emitTypeMetadataRef(CanType type,
23152363
DynamicMetadataRequest request) {
2316-
type = getRuntimeReifiedType(IGM, type);
2364+
type = IGM.getRuntimeReifiedType(type);
2365+
// Look through any opaque types we're allowed to.
2366+
type = IGM.substOpaqueTypesWithUnderlyingTypes(type);
23172367

23182368
if (type->hasArchetype() ||
23192369
isTypeMetadataAccessTrivial(IGM, type)) {
@@ -2328,7 +2378,7 @@ IRGenFunction::emitTypeMetadataRef(CanType type,
23282378
/// for the given non-dependent type.
23292379
llvm::Function *irgen::getOrCreateTypeMetadataAccessFunction(IRGenModule &IGM,
23302380
CanType type) {
2331-
type = getRuntimeReifiedType(IGM, type);
2381+
type = IGM.getRuntimeReifiedType(type);
23322382

23332383
assert(!type->hasArchetype() &&
23342384
"cannot create global function to return dependent type metadata");

lib/IRGen/MetadataRequest.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -583,10 +583,6 @@ ConstantReference tryEmitConstantTypeMetadataRef(IRGenModule &IGM,
583583
CanType type,
584584
SymbolReferenceKind refKind);
585585

586-
/// Get the type as it exists in Swift's runtime type system, removing any
587-
/// erased generic parameters.
588-
CanType getRuntimeReifiedType(IRGenModule &IGM, CanType type);
589-
590586
/// Emit a reference to a compile-time constant piece of heap metadata, or
591587
/// return a null pointer if the type's heap metadata cannot be represented
592588
/// by a constant.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
public protocol P {
3+
static func stat()
4+
}
5+
6+
extension Int: P {
7+
public static func stat() {}
8+
}
9+
10+
public func external_opaque() -> some P {
11+
return 0
12+
}
13+
14+
@inlinable
15+
public func external_inlinable() -> some P {
16+
return 0
17+
}

test/IRGen/lazy_opaque_result_type.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -disable-availability-checking -Xllvm -sil-disable-pass=OpaqueArchetypeSpecializer -parse-as-library -module-name=test -O -primary-file %s -emit-ir > %t.ll
1+
// RUN: %target-swift-frontend -enable-implicit-dynamic -disable-availability-checking -Xllvm -sil-disable-pass=OpaqueArchetypeSpecializer -parse-as-library -module-name=test -O -primary-file %s -emit-ir > %t.ll
22
// RUN: %FileCheck %s < %t.ll
33

44
protocol P { }

0 commit comments

Comments
 (0)