Skip to content

Commit d4b82ba

Browse files
committed
[metadata prespecialization] Cross-module: enums and structs.
When a generic type from a different module is not resilient within the current module and at least one of its arguments is from the current module, emit a non-canonical prespecialized record, and access that metadata via a call to swift_getCanonicalSpecializedMetadata, passing in the non-canonical record. rdar://problem/56996727 rdar://problem/56997022
1 parent 5141219 commit d4b82ba

File tree

48 files changed

+1551
-154
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1551
-154
lines changed

docs/ABI/Mangling.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ Globals
173173

174174
global ::= global 'MK' // instantiation cache associated with global
175175

176+
global ::= global 'MJ' // noncanonical specialized generic type metadata instantiation cache associated with global
177+
global ::= global 'MN' // noncanonical specialized generic type metadata for global
178+
176179
A direct symbol resolves directly to the address of an object. An
177180
indirect symbol resolves to the address of a pointer to the object.
178181
They are distinct manglings to make a certain class of bugs

include/swift/Demangling/DemangleNodes.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,12 @@ NODE(OpaqueTypeDescriptorAccessorVar)
287287
NODE(OpaqueReturnType)
288288
CONTEXT_NODE(OpaqueReturnTypeOf)
289289

290-
// Added in Swift 5.3
290+
// Added in Swift 5.4
291291
NODE(CanonicalSpecializedGenericMetaclass)
292292
NODE(CanonicalSpecializedGenericTypeMetadataAccessFunction)
293-
294-
// Added in Swift 5.4
295293
NODE(MetadataInstantiationCache)
294+
NODE(NoncanonicalSpecializedGenericTypeMetadata)
295+
NODE(NoncanonicalSpecializedGenericTypeMetadataCache)
296296

297297
#undef CONTEXT_NODE
298298
#undef NODE

include/swift/IRGen/Linking.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,16 @@ class LinkEntity {
393393
/// An access function for prespecialized type metadata.
394394
/// The pointer is a canonical TypeBase*.
395395
CanonicalSpecializedGenericTypeMetadataAccessFunction,
396+
397+
/// Metadata for a specialized generic type which cannot be statically
398+
/// guaranteed to be canonical and so must be canonicalized.
399+
/// The pointer is a canonical TypeBase*.
400+
NoncanonicalSpecializedGenericTypeMetadata,
401+
402+
/// A cache variable for noncanonical specialized type metadata, to be
403+
/// passed to swift_getCanonicalSpecializedMetadata.
404+
/// The pointer is a canonical TypeBase*.
405+
NoncanonicalSpecializedGenericTypeMetadataCacheVariable,
396406
};
397407
friend struct llvm::DenseMapInfo<LinkEntity>;
398408

@@ -1045,6 +1055,24 @@ class LinkEntity {
10451055
return entity;
10461056
}
10471057

1058+
static LinkEntity
1059+
forNoncanonicalSpecializedGenericTypeMetadata(CanType theType) {
1060+
LinkEntity entity;
1061+
entity.setForType(Kind::NoncanonicalSpecializedGenericTypeMetadata,
1062+
theType);
1063+
entity.Data |= LINKENTITY_SET_FIELD(
1064+
MetadataAddress, unsigned(TypeMetadataAddress::FullMetadata));
1065+
return entity;
1066+
}
1067+
1068+
1069+
static LinkEntity
1070+
forNoncanonicalSpecializedGenericTypeMetadataCacheVariable(CanType theType) {
1071+
LinkEntity entity;
1072+
entity.setForType(Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable, theType);
1073+
return entity;
1074+
}
1075+
10481076
void mangle(llvm::raw_ostream &out) const;
10491077
void mangle(SmallVectorImpl<char> &buffer) const;
10501078
std::string mangleAsString() const;
@@ -1152,6 +1180,7 @@ class LinkEntity {
11521180
}
11531181
TypeMetadataAddress getMetadataAddress() const {
11541182
assert(getKind() == Kind::TypeMetadata ||
1183+
getKind() == Kind::NoncanonicalSpecializedGenericTypeMetadata ||
11551184
getKind() == Kind::ObjCResilientClassStub);
11561185
return (TypeMetadataAddress)LINKENTITY_GET_FIELD(Data, MetadataAddress);
11571186
}

lib/Demangling/Demangler.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1911,12 +1911,14 @@ NodePointer Demangler::demangleMetatype() {
19111911
case 'j':
19121912
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessorKey,
19131913
popNode());
1914-
case 'K':
1915-
return createWithChild(Node::Kind::MetadataInstantiationCache,
1916-
popNode());
1914+
case 'J':
1915+
return createWithChild(Node::Kind::NoncanonicalSpecializedGenericTypeMetadataCache, popNode());
19171916
case 'k':
19181917
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessorVar,
19191918
popNode());
1919+
case 'K':
1920+
return createWithChild(Node::Kind::MetadataInstantiationCache,
1921+
popNode());
19201922
case 'l':
19211923
return createWithPoppedType(
19221924
Node::Kind::TypeMetadataSingletonInitializationCache);
@@ -1929,6 +1931,9 @@ NodePointer Demangler::demangleMetatype() {
19291931
Node::Kind::CanonicalSpecializedGenericMetaclass);
19301932
case 'n':
19311933
return createWithPoppedType(Node::Kind::NominalTypeDescriptor);
1934+
case 'N':
1935+
return createWithPoppedType(
1936+
Node::Kind::NoncanonicalSpecializedGenericTypeMetadata);
19321937
case 'o':
19331938
return createWithPoppedType(Node::Kind::ClassMetadataBaseOffset);
19341939
case 'p':

lib/Demangling/NodePrinter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,8 @@ class NodePrinter {
549549
case Node::Kind::OpaqueReturnTypeOf:
550550
case Node::Kind::CanonicalSpecializedGenericMetaclass:
551551
case Node::Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
552+
case Node::Kind::NoncanonicalSpecializedGenericTypeMetadata:
553+
case Node::Kind::NoncanonicalSpecializedGenericTypeMetadataCache:
552554
return false;
553555
}
554556
printer_unreachable("bad node kind");
@@ -2438,6 +2440,14 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
24382440
Printer << "metadata instantiation cache for ";
24392441
print(Node->getChild(0));
24402442
return nullptr;
2443+
case Node::Kind::NoncanonicalSpecializedGenericTypeMetadata:
2444+
Printer << "noncanonical specialized generic type metadata for ";
2445+
print(Node->getChild(0));
2446+
return nullptr;
2447+
case Node::Kind::NoncanonicalSpecializedGenericTypeMetadataCache:
2448+
Printer << "cache variable for noncanonical specialized generic type metadata for ";
2449+
print(Node->getChild(0));
2450+
return nullptr;
24412451
}
24422452
printer_unreachable("bad node kind!");
24432453
}

lib/Demangling/OldRemangler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,6 +2147,16 @@ void Remangler::mangleCanonicalSpecializedGenericTypeMetadataAccessFunction(
21472147
Buffer << "Mb";
21482148
}
21492149

2150+
void Remangler::mangleNoncanonicalSpecializedGenericTypeMetadata(Node *node) {
2151+
mangleSingleChildNode(node);
2152+
Buffer << "MN";
2153+
}
2154+
2155+
void Remangler::mangleNoncanonicalSpecializedGenericTypeMetadataCache(Node *node) {
2156+
mangleSingleChildNode(node);
2157+
Buffer << "MJ";
2158+
}
2159+
21502160
/// The top-level interface to the remangler.
21512161
std::string Demangle::mangleNodeOld(NodePointer node) {
21522162
if (!node) return "";

lib/Demangling/Remangler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,16 @@ void Remangler::mangleMetadataInstantiationCache(Node *node) {
25522552
Buffer << "MK";
25532553
}
25542554

2555+
void Remangler::mangleNoncanonicalSpecializedGenericTypeMetadata(Node *node) {
2556+
mangleSingleChildNode(node);
2557+
Buffer << "MN";
2558+
}
2559+
2560+
void Remangler::mangleNoncanonicalSpecializedGenericTypeMetadataCache(Node *node) {
2561+
mangleSingleChildNode(node);
2562+
Buffer << "MJ";
2563+
}
2564+
25552565
} // anonymous namespace
25562566

25572567
/// The top-level interface to the remangler.

lib/IRGen/GenDecl.cpp

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,7 +1426,22 @@ void IRGenerator::noteUseOfCanonicalSpecializedMetadataAccessor(
14261426
}
14271427
}
14281428

1429+
static bool typeKindCanBePrespecialized(TypeKind theKind) {
1430+
switch (theKind) {
1431+
case TypeKind::Struct:
1432+
case TypeKind::BoundGenericStruct:
1433+
case TypeKind::Enum:
1434+
case TypeKind::BoundGenericEnum:
1435+
case TypeKind::Class:
1436+
case TypeKind::BoundGenericClass:
1437+
return true;
1438+
default:
1439+
return false;
1440+
}
1441+
}
1442+
14291443
void IRGenerator::noteUseOfSpecializedGenericTypeMetadata(CanType type) {
1444+
assert(typeKindCanBePrespecialized(type->getKind()));
14301445
auto key = type->getAnyNominal();
14311446
assert(key);
14321447
assert(key->isGenericContext());
@@ -3736,6 +3751,22 @@ IRGenModule::getAddrOfTypeMetadataLazyCacheVariable(CanType type) {
37363751
return variable;
37373752
}
37383753

3754+
llvm::Constant *
3755+
IRGenModule::getAddrOfNoncanonicalSpecializedGenericTypeMetadataCacheVariable(CanType type) {
3756+
assert(!type->hasArchetype() && !type->hasTypeParameter());
3757+
LinkEntity entity = LinkEntity::forNoncanonicalSpecializedGenericTypeMetadataCacheVariable(type);
3758+
if (auto &entry = GlobalVars[entity]) {
3759+
return entry;
3760+
}
3761+
auto variable =
3762+
getAddrOfLLVMVariable(entity, ForDefinition, DebugTypeInfo());
3763+
3764+
cast<llvm::GlobalVariable>(variable)->setInitializer(
3765+
llvm::ConstantPointerNull::get(TypeMetadataPtrTy));
3766+
3767+
return variable;
3768+
}
3769+
37393770
/// Get or create a type metadata cache variable. These are an
37403771
/// implementation detail of type metadata access functions.
37413772
llvm::Constant *
@@ -3817,6 +3848,9 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
38173848
llvm::StringRef section) {
38183849
assert(init);
38193850

3851+
auto isPrespecialized = concreteType->getAnyGeneric() &&
3852+
concreteType->getAnyGeneric()->isGenericContext();
3853+
38203854
if (isPattern) {
38213855
assert(isConstant && "Type metadata patterns must be constant");
38223856
auto addr = getAddrOfTypeMetadataPattern(concreteType->getAnyNominal(),
@@ -3844,7 +3878,13 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
38443878
adjustmentIndex = MetadataAdjustmentIndex::ValueType;
38453879
}
38463880

3847-
auto entity = LinkEntity::forTypeMetadata(concreteType, addrKind);
3881+
auto entity =
3882+
(isPrespecialized &&
3883+
!irgen::isCanonicalInitializableTypeMetadataStaticallyAddressable(
3884+
*this, concreteType))
3885+
? LinkEntity::forNoncanonicalSpecializedGenericTypeMetadata(
3886+
concreteType)
3887+
: LinkEntity::forTypeMetadata(concreteType, addrKind);
38483888

38493889
auto DbgTy = DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
38503890
entity.getDefaultDeclarationType(*this)->getPointerTo(),
@@ -3868,9 +3908,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
38683908

38693909
// Don't define the alias for foreign type metadata or prespecialized generic
38703910
// metadata, since neither is ABI.
3871-
if ((nominal && requiresForeignTypeMetadata(nominal)) ||
3872-
(concreteType->getAnyGeneric() &&
3873-
concreteType->getAnyGeneric()->isGenericContext()))
3911+
if ((nominal && requiresForeignTypeMetadata(nominal)) || isPrespecialized)
38743912
return var;
38753913

38763914
// For concrete metadata, declare the alias to its address point.
@@ -3892,13 +3930,18 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
38923930
}
38933931

38943932
/// Fetch the declaration of the (possibly uninitialized) metadata for a type.
3895-
llvm::Constant *IRGenModule::getAddrOfTypeMetadata(CanType concreteType) {
3896-
return getAddrOfTypeMetadata(concreteType,
3897-
SymbolReferenceKind::Absolute).getDirectValue();
3933+
llvm::Constant *
3934+
IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
3935+
TypeMetadataCanonicality canonicality) {
3936+
return getAddrOfTypeMetadata(concreteType, SymbolReferenceKind::Absolute,
3937+
canonicality)
3938+
.getDirectValue();
38983939
}
38993940

3900-
ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
3901-
SymbolReferenceKind refKind) {
3941+
ConstantReference
3942+
IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
3943+
SymbolReferenceKind refKind,
3944+
TypeMetadataCanonicality canonicality) {
39023945
assert(!isa<UnboundGenericType>(concreteType));
39033946

39043947
auto nominal = concreteType->getAnyNominal();
@@ -3952,12 +3995,20 @@ ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
39523995
Optional<LinkEntity> entity;
39533996
DebugTypeInfo DbgTy;
39543997

3955-
if (fullMetadata) {
3956-
entity = LinkEntity::forTypeMetadata(concreteType,
3957-
TypeMetadataAddress::FullMetadata);
3958-
} else {
3959-
entity = LinkEntity::forTypeMetadata(concreteType,
3960-
TypeMetadataAddress::AddressPoint);
3998+
switch (canonicality) {
3999+
case TypeMetadataCanonicality::Canonical:
4000+
if (fullMetadata) {
4001+
entity = LinkEntity::forTypeMetadata(concreteType,
4002+
TypeMetadataAddress::FullMetadata);
4003+
} else {
4004+
entity = LinkEntity::forTypeMetadata(concreteType,
4005+
TypeMetadataAddress::AddressPoint);
4006+
}
4007+
break;
4008+
case TypeMetadataCanonicality::Noncanonical:
4009+
entity =
4010+
LinkEntity::forNoncanonicalSpecializedGenericTypeMetadata(concreteType);
4011+
break;
39614012
}
39624013
DbgTy = DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
39634014
defaultVarTy->getPointerTo(), Size(0),

lib/IRGen/GenMeta.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,8 +1977,9 @@ void irgen::emitLazySpecializedGenericTypeMetadata(IRGenModule &IGM,
19771977
*type.getClassOrBoundGenericClass());
19781978
break;
19791979
default:
1980-
llvm_unreachable("Cannot statically specialize types of kind other than "
1981-
"struct and enum.");
1980+
llvm_unreachable(
1981+
"Cannot statically specialize metadata for generic types of"
1982+
"kind other than struct, enum, and class.");
19821983
}
19831984
}
19841985

@@ -3476,7 +3477,9 @@ namespace {
34763477
MetadataTrailingFlags flags = super::getTrailingFlags();
34773478

34783479
flags.setIsStaticSpecialization(true);
3479-
flags.setIsCanonicalStaticSpecialization(true);
3480+
flags.setIsCanonicalStaticSpecialization(
3481+
irgen::isCanonicalInitializableTypeMetadataStaticallyAddressable(
3482+
IGM, type));
34803483

34813484
return flags;
34823485
}

lib/IRGen/IRGenMangler.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ class IRGenMangler : public Mangle::ASTMangler {
118118
return mangleTypeSymbol(type, "N");
119119
}
120120

121+
std::string mangleNoncanonicalTypeMetadata(Type type) {
122+
return mangleTypeSymbol(type, "MN");
123+
}
124+
125+
std::string mangleNoncanonicalSpecializedGenericTypeMetadataCache(Type type) {
126+
return mangleTypeSymbol(type, "MJ");
127+
}
128+
121129
std::string mangleTypeMetadataPattern(const NominalTypeDecl *decl) {
122130
return mangleNominalTypeSymbol(decl, "MP");
123131
}

0 commit comments

Comments
 (0)