Skip to content

Commit beba678

Browse files
authored
Merge pull request #79302 from mikeash/singleton-metadata-pointer
[IRGen] Emit a pointer from nominal type descriptor to concrete metadata.
2 parents f8b60bb + 270ddf6 commit beba678

File tree

7 files changed

+142
-15
lines changed

7 files changed

+142
-15
lines changed

include/swift/ABI/Metadata.h

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3879,6 +3879,13 @@ struct TargetCanonicalSpecializedMetadatasCachingOnceToken {
38793879
TargetRelativeDirectPointer<Runtime, swift_once_t, /*Nullable*/ false> token;
38803880
};
38813881

3882+
template <typename Runtime>
3883+
struct TargetSingletonMetadataPointer {
3884+
TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>,
3885+
/*Nullable*/ false>
3886+
metadata;
3887+
};
3888+
38823889
template <typename Runtime>
38833890
class swift_ptrauth_struct_context_descriptor(TypeContextDescriptor)
38843891
TargetTypeContextDescriptor : public TargetContextDescriptor<Runtime> {
@@ -3931,7 +3938,15 @@ class swift_ptrauth_struct_context_descriptor(TypeContextDescriptor)
39313938
}
39323939

39333940
bool hasCanonicalMetadataPrespecializations() const {
3934-
return getTypeContextDescriptorFlags().hasCanonicalMetadataPrespecializations();
3941+
return this->isGeneric() &&
3942+
getTypeContextDescriptorFlags()
3943+
.hasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer();
3944+
}
3945+
3946+
bool hasSingletonMetadataPointer() const {
3947+
return !this->isGeneric() &&
3948+
getTypeContextDescriptorFlags()
3949+
.hasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer();
39353950
}
39363951

39373952
bool hasLayoutString() const {
@@ -4123,7 +4138,8 @@ class swift_ptrauth_struct_context_descriptor(ClassDescriptor)
41234138
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
41244139
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>,
41254140
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>,
4126-
InvertibleProtocolSet> {
4141+
InvertibleProtocolSet,
4142+
TargetSingletonMetadataPointer<Runtime>> {
41274143
private:
41284144
using TrailingGenericContextObjects =
41294145
swift::TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
@@ -4140,7 +4156,8 @@ class swift_ptrauth_struct_context_descriptor(ClassDescriptor)
41404156
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
41414157
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>,
41424158
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>,
4143-
InvertibleProtocolSet>;
4159+
InvertibleProtocolSet,
4160+
TargetSingletonMetadataPointer<Runtime>>;
41444161

41454162
using TrailingObjects =
41464163
typename TrailingGenericContextObjects::TrailingObjects;
@@ -4170,6 +4187,7 @@ class swift_ptrauth_struct_context_descriptor(ClassDescriptor)
41704187
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>;
41714188
using MetadataCachingOnceToken =
41724189
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;
4190+
using SingletonMetadataPointer = TargetSingletonMetadataPointer<Runtime>;
41734191

41744192
using StoredPointer = typename Runtime::StoredPointer;
41754193
using StoredPointerDifference = typename Runtime::StoredPointerDifference;
@@ -4311,6 +4329,10 @@ class swift_ptrauth_struct_context_descriptor(ClassDescriptor)
43114329
return this->hasCanonicalMetadataPrespecializations() ? 1 : 0;
43124330
}
43134331

4332+
size_t numTrailingObjects(OverloadToken<SingletonMetadataPointer>) const {
4333+
return this->hasSingletonMetadataPointer() ? 1 : 0;
4334+
}
4335+
43144336
public:
43154337
const TargetRelativeDirectPointer<Runtime, const void, /*nullable*/true> &
43164338
getResilientSuperclass() const {
@@ -4490,6 +4512,14 @@ class swift_ptrauth_struct_context_descriptor(ClassDescriptor)
44904512
return box->token.get();
44914513
}
44924514

4515+
TargetMetadata<Runtime> *getSingletonMetadata() const {
4516+
if (!this->hasSingletonMetadataInitialization())
4517+
return nullptr;
4518+
4519+
auto box = this->template getTrailingObjects<SingletonMetadataPointer>();
4520+
return box->token.get();
4521+
}
4522+
44934523
/// Retrieve the set of protocols that are inverted by this type's
44944524
/// primary definition.
44954525
///
@@ -4537,7 +4567,8 @@ class swift_ptrauth_struct_context_descriptor(StructDescriptor)
45374567
TargetCanonicalSpecializedMetadatasListCount<Runtime>,
45384568
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
45394569
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>,
4540-
InvertibleProtocolSet> {
4570+
InvertibleProtocolSet,
4571+
TargetSingletonMetadataPointer<Runtime>> {
45414572
public:
45424573
using ForeignMetadataInitialization =
45434574
TargetForeignMetadataInitialization<Runtime>;
@@ -4551,6 +4582,7 @@ class swift_ptrauth_struct_context_descriptor(StructDescriptor)
45514582
TargetCanonicalSpecializedMetadatasListEntry<Runtime>;
45524583
using MetadataCachingOnceToken =
45534584
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;
4585+
using SingletonMetadataPointer = TargetSingletonMetadataPointer<Runtime>;
45544586

45554587
private:
45564588
using TrailingGenericContextObjects =
@@ -4561,7 +4593,8 @@ class swift_ptrauth_struct_context_descriptor(StructDescriptor)
45614593
MetadataListCount,
45624594
MetadataListEntry,
45634595
MetadataCachingOnceToken,
4564-
InvertibleProtocolSet>;
4596+
InvertibleProtocolSet,
4597+
TargetSingletonMetadataPointer<Runtime>>;
45654598

45664599
using TrailingObjects =
45674600
typename TrailingGenericContextObjects::TrailingObjects;
@@ -4595,6 +4628,10 @@ class swift_ptrauth_struct_context_descriptor(StructDescriptor)
45954628
return this->hasCanonicalMetadataPrespecializations() ? 1 : 0;
45964629
}
45974630

4631+
size_t numTrailingObjects(OverloadToken<SingletonMetadataPointer>) const {
4632+
return this->hasSingletonMetadataPointer() ? 1 : 0;
4633+
}
4634+
45984635
public:
45994636
using TrailingGenericContextObjects::getGenericContext;
46004637
using TrailingGenericContextObjects::getGenericContextHeader;
@@ -4648,6 +4685,14 @@ class swift_ptrauth_struct_context_descriptor(StructDescriptor)
46484685
return box->token.get();
46494686
}
46504687

4688+
TargetMetadata<Runtime> *getSingletonMetadata() const {
4689+
if (!this->hasSingletonMetadataInitialization())
4690+
return nullptr;
4691+
4692+
auto box = this->template getTrailingObjects<SingletonMetadataPointer>();
4693+
return box->token.get();
4694+
}
4695+
46514696
/// Retrieve the set of protocols that are inverted by this type's
46524697
/// primary definition.
46534698
///
@@ -4684,7 +4729,8 @@ class swift_ptrauth_struct_context_descriptor(EnumDescriptor)
46844729
TargetCanonicalSpecializedMetadatasListCount<Runtime>,
46854730
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
46864731
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>,
4687-
InvertibleProtocolSet> {
4732+
InvertibleProtocolSet,
4733+
TargetSingletonMetadataPointer<Runtime>> {
46884734
public:
46894735
using SingletonMetadataInitialization =
46904736
TargetSingletonMetadataInitialization<Runtime>;
@@ -4698,6 +4744,7 @@ class swift_ptrauth_struct_context_descriptor(EnumDescriptor)
46984744
TargetCanonicalSpecializedMetadatasListEntry<Runtime>;
46994745
using MetadataCachingOnceToken =
47004746
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;
4747+
using SingletonMetadataPointer = TargetSingletonMetadataPointer<Runtime>;
47014748

47024749
private:
47034750
using TrailingGenericContextObjects =
@@ -4708,7 +4755,8 @@ class swift_ptrauth_struct_context_descriptor(EnumDescriptor)
47084755
MetadataListCount,
47094756
MetadataListEntry,
47104757
MetadataCachingOnceToken,
4711-
InvertibleProtocolSet>;
4758+
InvertibleProtocolSet,
4759+
TargetSingletonMetadataPointer<Runtime>>;
47124760

47134761
using TrailingObjects =
47144762
typename TrailingGenericContextObjects::TrailingObjects;
@@ -4742,6 +4790,10 @@ class swift_ptrauth_struct_context_descriptor(EnumDescriptor)
47424790
return this->hasCanonicalMetadataPrespecializations() ? 1 : 0;
47434791
}
47444792

4793+
size_t numTrailingObjects(OverloadToken<SingletonMetadataPointer>) const {
4794+
return this->hasSingletonMetadataPointer() ? 1 : 0;
4795+
}
4796+
47454797
public:
47464798
using TrailingGenericContextObjects::getGenericContext;
47474799
using TrailingGenericContextObjects::getGenericContextHeader;
@@ -4809,6 +4861,14 @@ class swift_ptrauth_struct_context_descriptor(EnumDescriptor)
48094861
return box->token.get();
48104862
}
48114863

4864+
TargetMetadata<Runtime> *getSingletonMetadata() const {
4865+
if (!this->hasSingletonMetadataInitialization())
4866+
return nullptr;
4867+
4868+
auto box = this->template getTrailingObjects<SingletonMetadataPointer>();
4869+
return box->token.get();
4870+
}
4871+
48124872
/// Retrieve the set of protocols that are inverted by this type's
48134873
/// primary definition.
48144874
///

include/swift/ABI/MetadataValues.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,9 +1872,10 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
18721872
/// Meaningful for all type-descriptor kinds.
18731873
HasImportInfo = 2,
18741874

1875-
/// Set if the type descriptor has a pointer to a list of canonical
1876-
/// prespecializations.
1877-
HasCanonicalMetadataPrespecializations = 3,
1875+
/// Set if the generic type descriptor has a pointer to a list of canonical
1876+
/// prespecializations, or the non-generic type descriptor has a pointer to
1877+
/// its singleton metadata.
1878+
HasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer = 3,
18781879

18791880
/// Set if the metadata contains a pointer to a layout string
18801881
HasLayoutString = 4,
@@ -1959,7 +1960,10 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
19591960

19601961
FLAGSET_DEFINE_FLAG_ACCESSORS(HasImportInfo, hasImportInfo, setHasImportInfo)
19611962

1962-
FLAGSET_DEFINE_FLAG_ACCESSORS(HasCanonicalMetadataPrespecializations, hasCanonicalMetadataPrespecializations, setHasCanonicalMetadataPrespecializations)
1963+
FLAGSET_DEFINE_FLAG_ACCESSORS(
1964+
HasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer,
1965+
hasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer,
1966+
setHasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer)
19631967

19641968
FLAGSET_DEFINE_FLAG_ACCESSORS(HasLayoutString,
19651969
hasLayoutString,

include/swift/AST/IRGenOptions.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,10 @@ class IRGenOptions {
406406
/// arguments.
407407
unsigned PrespecializeGenericMetadata : 1;
408408

409+
/// Emit pointers to the corresponding type metadata in non-public non-generic
410+
/// type descriptors.
411+
unsigned EmitSingletonMetadataPointers : 1;
412+
409413
/// The path to load legacy type layouts from.
410414
StringRef ReadLegacyTypeInfoPath;
411415

@@ -597,7 +601,8 @@ class IRGenOptions {
597601
LazyInitializeProtocolConformances(false),
598602
IndirectAsyncFunctionPointer(false), IndirectCoroFunctionPointer(false),
599603
CompactAbsoluteFunctionPointer(false), DisableLegacyTypeInfo(false),
600-
PrespecializeGenericMetadata(false), UseIncrementalLLVMCodeGen(true),
604+
PrespecializeGenericMetadata(false),
605+
EmitSingletonMetadataPointers(false), UseIncrementalLLVMCodeGen(true),
601606
UseTypeLayoutValueHandling(true), ForceStructTypeLayouts(false),
602607
EnableLargeLoadableTypesReg2Mem(true),
603608
EnableLayoutStringValueWitnesses(false),

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,10 @@ def prespecialize_generic_metadata : Flag<["-"], "prespecialize-generic-metadata
11161116
HelpText<"Statically specialize metadata for generic types at types that "
11171117
"are known to be used in source.">;
11181118

1119+
def emit_singleton_metadata_pointer : Flag<["-"], "emit-singleton-metadata-pointer">,
1120+
HelpText<"Emit a pointer to the corresponding type metadata into non-public "
1121+
"non-generic type descriptors.">;
1122+
11191123
def read_legacy_type_info_path_EQ : Joined<["-"], "read-legacy-type-info-path=">,
11201124
HelpText<"Read legacy type layout from the given path instead of default path">;
11211125

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3453,6 +3453,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
34533453
Opts.PrespecializeGenericMetadata = true;
34543454
}
34553455

3456+
if (Args.hasArg(OPT_emit_singleton_metadata_pointer)) {
3457+
Opts.EmitSingletonMetadataPointers = true;
3458+
}
3459+
34563460
if (const Arg *A = Args.getLastArg(OPT_read_legacy_type_info_path_EQ)) {
34573461
Opts.ReadLegacyTypeInfoPath = A->getValue();
34583462
}

lib/IRGen/GenMeta.cpp

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,8 @@ namespace {
15891589
void setCommonFlags(TypeContextDescriptorFlags &flags) {
15901590
setClangImportedFlags(flags);
15911591
setMetadataInitializationKind(flags);
1592-
setHasCanonicalMetadataPrespecializations(flags);
1592+
setHasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer(
1593+
flags);
15931594
}
15941595

15951596
void setClangImportedFlags(TypeContextDescriptorFlags &flags) {
@@ -1623,8 +1624,11 @@ namespace {
16231624
flags.setMetadataInitialization(MetadataInitialization);
16241625
}
16251626

1626-
void setHasCanonicalMetadataPrespecializations(TypeContextDescriptorFlags &flags) {
1627-
flags.setHasCanonicalMetadataPrespecializations(hasCanonicalMetadataPrespecializations());
1627+
void setHasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer(
1628+
TypeContextDescriptorFlags &flags) {
1629+
flags.setHasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer(
1630+
hasCanonicalMetadataPrespecializations() ||
1631+
hasSingletonMetadataPointer());
16281632
}
16291633

16301634
bool hasCanonicalMetadataPrespecializations() {
@@ -1636,6 +1640,30 @@ namespace {
16361640
});
16371641
}
16381642

1643+
bool hasSingletonMetadataPointer() {
1644+
if (!IGM.IRGen.Opts.EmitSingletonMetadataPointers)
1645+
return false;
1646+
1647+
bool isGeneric = Type->isGenericContext();
1648+
bool noInitialization =
1649+
MetadataInitialization ==
1650+
TypeContextDescriptorFlags::NoMetadataInitialization;
1651+
auto isPublic = Type->getFormalAccessScope().isPublic();
1652+
1653+
auto kind = asImpl().getContextKind();
1654+
auto isSupportedKind = kind == ContextDescriptorKind::Class ||
1655+
kind == ContextDescriptorKind::Struct ||
1656+
kind == ContextDescriptorKind::Enum;
1657+
1658+
// Only emit a singleton metadata pointer if:
1659+
// The type is not generic (there's no single metadata if it's generic).
1660+
// The metadata doesn't require runtime initialization. (The metadata
1661+
// can't safely be accessed directly if it does.)
1662+
// The type is not public. (If it's public it can be found by symbol.)
1663+
// It's a class, struct, or enum.
1664+
return !isGeneric && noInitialization && !isPublic && isSupportedKind;
1665+
}
1666+
16391667
void maybeAddMetadataInitialization() {
16401668
switch (MetadataInitialization) {
16411669
case TypeContextDescriptorFlags::NoMetadataInitialization:
@@ -1724,6 +1752,14 @@ namespace {
17241752
B.addRelativeAddress(cachingOnceToken);
17251753
}
17261754

1755+
void maybeAddSingletonMetadataPointer() {
1756+
if (hasSingletonMetadataPointer()) {
1757+
auto type = Type->getDeclaredTypeInContext()->getCanonicalType();
1758+
auto metadata = IGM.getAddrOfTypeMetadata(type);
1759+
B.addRelativeAddress(metadata);
1760+
}
1761+
}
1762+
17271763
// Subclasses should provide:
17281764
// ContextDescriptorKind getContextKind();
17291765
// void addLayoutInfo();
@@ -1758,6 +1794,7 @@ namespace {
17581794
super::layout();
17591795
maybeAddCanonicalMetadataPrespecializations();
17601796
addInvertedProtocols();
1797+
maybeAddSingletonMetadataPointer();
17611798
}
17621799

17631800
ContextDescriptorKind getContextKind() {
@@ -1832,6 +1869,7 @@ namespace {
18321869
super::layout();
18331870
maybeAddCanonicalMetadataPrespecializations();
18341871
addInvertedProtocols();
1872+
maybeAddSingletonMetadataPointer();
18351873
}
18361874

18371875
ContextDescriptorKind getContextKind() {
@@ -1965,6 +2003,7 @@ namespace {
19652003
addObjCResilientClassStubInfo();
19662004
maybeAddCanonicalMetadataPrespecializations();
19672005
addInvertedProtocols();
2006+
maybeAddSingletonMetadataPointer();
19682007
}
19692008

19702009
void addIncompleteMetadataOrRelocationFunction() {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-frontend -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -emit-singleton-metadata-pointer | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK --check-prefix=CHECK-%target-vendor --dump-input=always
2+
3+
// CHECK: @"$s4main23PrivateNongenericStructVMn" =
4+
// CHECK-SAME: hidden constant <{ i32, i32, i32, i32, i32, i32, i32, i32 }>
5+
// -- flags: struct, unique, has singleton metadata pointer
6+
// CHECK-SAME: <{ i32 524369,
7+
// -- 32-bit relative pointer to metadata
8+
// CHECK-64-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (<{ {{.*}} }>, ptr @"$s4main23PrivateNongenericStructVMf", i32 0, i32 2) to i64)
9+
// CHECK-32-SAME: i32 sub (i32 ptrtoint (ptr getelementptr inbounds (<{ {{.*}} }>, ptr @"$s4main23PrivateNongenericStructVMf", i32 0, i32 2) to i32)
10+
11+
internal struct PrivateNongenericStruct {}

0 commit comments

Comments
 (0)