Skip to content

Commit 7ec52e6

Browse files
committed
IRGen: Separate the concept of "metadata should be cached" from "statically referenced"
Some metadata may require instantiation, but not in a way that requires us to put an additional cache layer in front of it. `Self` metadata is also trivial to access from the local cache, but isn't statically referenceable. Split these concepts and update code to use one or the other appropriately. This catches an issue with metadata prespecialization where it would try to make records for dynamic `Self` incorrectly.
1 parent e35ae37 commit 7ec52e6

File tree

4 files changed

+28
-35
lines changed

4 files changed

+28
-35
lines changed

lib/IRGen/LocalTypeData.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ addAbstractForFulfillments(IRGenFunction &IGF, FulfillmentMap &&fulfillments,
560560
// the type metadata for Int by chasing through N layers of metadata
561561
// just because that path happens to be in the cache.
562562
if (!type->hasArchetype() &&
563-
isTypeMetadataAccessTrivial(IGF.IGM, type)) {
563+
!shouldCacheTypeMetadataAccess(IGF.IGM, type)) {
564564
continue;
565565
}
566566

lib/IRGen/MetadataRequest.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ irgen::tryEmitConstantTypeMetadataRef(IRGenModule &IGM, CanType type,
556556
SymbolReferenceKind refKind) {
557557
if (IGM.isStandardLibrary())
558558
return ConstantReference();
559-
if (!isTypeMetadataAccessTrivial(IGM, type))
559+
if (isCompleteTypeMetadataStaticallyAddressable(IGM, type))
560560
return ConstantReference();
561561
return IGM.getAddrOfTypeMetadata(type, refKind);
562562
}
@@ -722,7 +722,7 @@ bool irgen::isNominalGenericContextTypeMetadataAccessTrivial(
722722
};
723723
auto isExistential = [&]() { return argument->isExistentialType(); };
724724
auto metadataAccessIsTrivial = [&]() {
725-
return irgen::isTypeMetadataAccessTrivial(IGM,
725+
return irgen::isCompleteTypeMetadataStaticallyAddressable(IGM,
726726
argument->getCanonicalType());
727727
};
728728
return !isGenericWithoutPrespecializedConformance() && !isExistential() &&
@@ -732,9 +732,9 @@ bool irgen::isNominalGenericContextTypeMetadataAccessTrivial(
732732
&& IGM.getTypeInfoForUnlowered(type).isFixedSize(ResilienceExpansion::Maximal);
733733
}
734734

735-
/// Is it basically trivial to access the given metadata? If so, we don't
736-
/// need a cache variable in its accessor.
737-
bool irgen::isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type) {
735+
/// Is complete metadata for the given type available at a fixed address?
736+
bool irgen::isCompleteTypeMetadataStaticallyAddressable(IRGenModule &IGM,
737+
CanType type) {
738738
assert(!type->hasArchetype());
739739

740740
// Value type metadata only requires dynamic initialization on first
@@ -775,10 +775,6 @@ bool irgen::isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type) {
775775
if (isa<SILBoxType>(type))
776776
return true;
777777

778-
// DynamicSelfType is actually local.
779-
if (type->hasDynamicSelfType())
780-
return true;
781-
782778
if (isa<BoundGenericStructType>(type) || isa<BoundGenericEnumType>(type)) {
783779
auto nominalType = cast<BoundGenericType>(type);
784780
auto *nominalDecl = nominalType->getDecl();
@@ -794,6 +790,19 @@ bool irgen::isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type) {
794790
return false;
795791
}
796792

793+
/// Should requests for the given type's metadata be cached?
794+
bool irgen::shouldCacheTypeMetadataAccess(IRGenModule &IGM, CanType type) {
795+
// DynamicSelfType is actually local.
796+
if (type->hasDynamicSelfType())
797+
return false;
798+
799+
// Statically addressable metadata does not need a cache.
800+
if (isCompleteTypeMetadataStaticallyAddressable(IGM, type))
801+
return false;
802+
803+
return true;
804+
}
805+
797806
/// Return the standard access strategy for getting a non-dependent
798807
/// type metadata object.
799808
MetadataAccessStrategy irgen::getTypeMetadataAccessStrategy(CanType type) {
@@ -2016,7 +2025,7 @@ emitDirectTypeMetadataAccessFunctionBody(IRGenFunction &IGF,
20162025
}
20172026

20182027
// We should not be doing more serious work along this path.
2019-
assert(isTypeMetadataAccessTrivial(IGF.IGM, type));
2028+
assert(isCompleteTypeMetadataStaticallyAddressable(IGF.IGM, type));
20202029

20212030
// Okay, everything else is built from a Swift metadata object.
20222031
llvm::Constant *metadata = IGF.IGM.getAddrOfTypeMetadata(type);
@@ -2064,7 +2073,7 @@ irgen::createTypeMetadataAccessFunction(IRGenModule &IGM, CanType type,
20642073

20652074
// If our preferred access method is to go via an accessor, it means
20662075
// there is some non-trivial computation that needs to be cached.
2067-
if (isTypeMetadataAccessTrivial(IGM, type)) {
2076+
if (!shouldCacheTypeMetadataAccess(IGM, type)) {
20682077
cacheStrategy = CacheStrategy::None;
20692078
} else {
20702079
switch (cacheStrategy) {
@@ -2194,7 +2203,7 @@ static bool shouldAccessByMangledName(IRGenModule &IGM, CanType type) {
21942203
// others may require accessors to trigger instantiation.
21952204
//
21962205
// TODO: Also need to count the parent type's generic arguments.
2197-
if (isTypeMetadataAccessTrivial(IGM, nom)) {
2206+
if (!shouldCacheTypeMetadataAccess(IGM, nom)) {
21982207
NumAddresses += 1;
21992208
} else {
22002209
NumCalls += 1;
@@ -2545,8 +2554,7 @@ IRGenFunction::emitTypeMetadataRef(CanType type,
25452554
}
25462555

25472556
if (type->hasArchetype() ||
2548-
isTypeMetadataAccessTrivial(IGM, type)) {
2549-
// FIXME: propagate metadata request!
2557+
!shouldCacheTypeMetadataAccess(IGM, type)) {
25502558
return emitDirectTypeMetadataRef(*this, type, request);
25512559
}
25522560

lib/IRGen/MetadataRequest.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -500,9 +500,10 @@ static inline bool isAccessorLazilyGenerated(MetadataAccessStrategy strategy) {
500500
llvm_unreachable("bad kind");
501501
}
502502

503-
/// Is it basically trivial to access the given metadata? If so, we don't
504-
/// need a cache variable in its accessor.
505-
bool isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type);
503+
/// Is complete metadata for the given type available at a fixed address?
504+
bool isCompleteTypeMetadataStaticallyAddressable(IRGenModule &IGM, CanType type);
505+
/// Should requests for the given type's metadata be cached?
506+
bool shouldCacheTypeMetadataAccess(IRGenModule &IGM, CanType type);
506507

507508
bool isNominalGenericContextTypeMetadataAccessTrivial(IRGenModule &IGM,
508509
NominalTypeDecl &nominal,

test/IRGen/dynamic_self_metadata_future.swift

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,7 @@ class C {
5757
// CHECK-SAME: {{.*}} @"$s28dynamic_self_metadata_future1GVyxGAA1PAAMc"
5858
// CHECK-SAME: to %swift.protocol_conformance_descriptor*
5959
// CHECK-SAME: ),
60-
// CHECK-SAME: %swift.type* getelementptr inbounds (
61-
// CHECK-SAME: %swift.full_type,
62-
// CHECK-SAME: %swift.full_type* bitcast (
63-
// CHECK-SAME: <{
64-
// CHECK-SAME: i8**,
65-
// CHECK-SAME: [[INT]],
66-
// CHECK-SAME: %swift.type_descriptor*,
67-
// CHECK-SAME: %swift.type*,
68-
// CHECK-SAME: i32,
69-
// CHECK-SAME: {{(\[4 x i8\])?}},
70-
// CHECK-SAME: i64
71-
// CHECK-SAME: }>* @"$s28dynamic_self_metadata_future1GVyAA1CCXDGMf"
72-
// CHECK-SAME: to %swift.full_type*
73-
// CHECK-SAME: ),
74-
// CHECK-SAME: i32 0,
75-
// CHECK-SAME: i32 1
76-
// CHECK-SAME: ),
60+
// CHECK-SAME: %swift.type* %{{[0-9]+}},
7761
// CHECK-SAME: i8*** undef
7862
// CHECK-SAME: )
7963
}

0 commit comments

Comments
 (0)