Skip to content

Commit b7119ee

Browse files
authored
Merge pull request #26455 from jckarter/type-metadata-by-mangled-name
IRGen: Access concrete type metadata by mangled name.
2 parents ca9deda + 5d05809 commit b7119ee

Some content is hidden

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

59 files changed

+653
-535
lines changed

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ NODE(TypeMetadataCompletionFunction)
211211
NODE(TypeMetadataInstantiationCache)
212212
NODE(TypeMetadataInstantiationFunction)
213213
NODE(TypeMetadataSingletonInitializationCache)
214+
NODE(TypeMetadataDemanglingCache)
214215
NODE(TypeMetadataLazyCache)
215216
NODE(UncurriedFunctionType)
216217
NODE(UnknownIndex)

include/swift/IRGen/Linking.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,10 @@ class LinkEntity {
368368
/// The pointer is a canonical TypeBase*.
369369
TypeMetadataLazyCacheVariable,
370370

371+
/// A lazy cache variable for fetching type metadata from a mangled name.
372+
/// The pointer is a canonical TypeBase*.
373+
TypeMetadataDemanglingCacheVariable,
374+
371375
/// A reflection metadata descriptor for a builtin or imported type.
372376
ReflectionBuiltinDescriptor,
373377

@@ -705,6 +709,12 @@ class LinkEntity {
705709
return entity;
706710
}
707711

712+
static LinkEntity forTypeMetadataDemanglingCacheVariable(CanType type) {
713+
LinkEntity entity;
714+
entity.setForType(Kind::TypeMetadataDemanglingCacheVariable, type);
715+
return entity;
716+
}
717+
708718
static LinkEntity forClassMetadataBaseOffset(ClassDecl *decl) {
709719
LinkEntity entity;
710720
entity.setForDecl(Kind::ClassMetadataBaseOffset, decl);

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,7 @@ FUNCTION(IsOptionalType,
11901190
FUNCTION(Once, swift_once, C_CC, AlwaysAvailable,
11911191
RETURNS(VoidTy),
11921192
ARGS(OnceTy->getPointerTo(), Int8PtrTy, Int8PtrTy),
1193-
ATTRS())
1193+
ATTRS(NoUnwind))
11941194

11951195
// void swift_registerProtocols(const ProtocolRecord *begin,
11961196
// const ProtocolRecord *end)
@@ -1398,6 +1398,17 @@ FUNCTION(IntToFloat64, swift_intToFloat64, SwiftCC, AlwaysAvailable,
13981398
ARGS(SizeTy->getPointerTo(), SizeTy),
13991399
ATTRS(NoUnwind, ReadOnly))
14001400

1401+
// const Metadata *swift_getTypeByMangledNameInContext(
1402+
// const char *typeNameStart,
1403+
// size_t typeNameLength,
1404+
// const TargetContextDescriptor<InProcess> *context,
1405+
// const void * const *genericArgs)
1406+
FUNCTION(GetTypeByMangledNameInContext, swift_getTypeByMangledNameInContext,
1407+
SwiftCC, AlwaysAvailable,
1408+
RETURNS(TypeMetadataPtrTy),
1409+
ARGS(Int8PtrTy, SizeTy, TypeContextDescriptorPtrTy, Int8PtrPtrTy),
1410+
ATTRS(NoUnwind, ArgMemOnly))
1411+
14011412
#undef RETURNS
14021413
#undef ARGS
14031414
#undef ATTRS

lib/Demangling/Demangler.cpp

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,36 +1788,50 @@ NodePointer Demangler::demangleImplFunctionType() {
17881788

17891789
NodePointer Demangler::demangleMetatype() {
17901790
switch (nextChar()) {
1791+
case 'a':
1792+
return createWithPoppedType(Node::Kind::TypeMetadataAccessFunction);
1793+
case 'A':
1794+
return createWithChild(Node::Kind::ReflectionMetadataAssocTypeDescriptor,
1795+
popProtocolConformance());
1796+
case 'B':
1797+
return createWithChild(Node::Kind::ReflectionMetadataBuiltinDescriptor,
1798+
popNode(Node::Kind::Type));
17911799
case 'c':
17921800
return createWithChild(Node::Kind::ProtocolConformanceDescriptor,
17931801
popProtocolConformance());
1802+
case 'C': {
1803+
NodePointer Ty = popNode(Node::Kind::Type);
1804+
if (!Ty || !isAnyGeneric(Ty->getChild(0)->getKind()))
1805+
return nullptr;
1806+
return createWithChild(Node::Kind::ReflectionMetadataSuperclassDescriptor,
1807+
Ty->getChild(0));
1808+
}
1809+
case 'D':
1810+
return createWithPoppedType(Node::Kind::TypeMetadataDemanglingCache);
17941811
case 'f':
17951812
return createWithPoppedType(Node::Kind::FullTypeMetadata);
1796-
case 'P':
1797-
return createWithPoppedType(Node::Kind::GenericTypeMetadataPattern);
1798-
case 'a':
1799-
return createWithPoppedType(Node::Kind::TypeMetadataAccessFunction);
1813+
case 'F':
1814+
return createWithChild(Node::Kind::ReflectionMetadataFieldDescriptor,
1815+
popNode(Node::Kind::Type));
18001816
case 'g':
18011817
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessor,
18021818
popNode());
18031819
case 'h':
18041820
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessorImpl,
18051821
popNode());
1822+
case 'i':
1823+
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationFunction);
1824+
case 'I':
1825+
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationCache);
18061826
case 'j':
18071827
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessorKey,
18081828
popNode());
18091829
case 'k':
18101830
return createWithChild(Node::Kind::OpaqueTypeDescriptorAccessorVar,
18111831
popNode());
1812-
case 'I':
1813-
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationCache);
1814-
case 'i':
1815-
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationFunction);
1816-
case 'r':
1817-
return createWithPoppedType(Node::Kind::TypeMetadataCompletionFunction);
18181832
case 'l':
18191833
return createWithPoppedType(
1820-
Node::Kind::TypeMetadataSingletonInitializationCache);
1834+
Node::Kind::TypeMetadataSingletonInitializationCache);
18211835
case 'L':
18221836
return createWithPoppedType(Node::Kind::TypeMetadataLazyCache);
18231837
case 'm':
@@ -1828,35 +1842,23 @@ NodePointer Demangler::demangleMetatype() {
18281842
return createWithPoppedType(Node::Kind::ClassMetadataBaseOffset);
18291843
case 'p':
18301844
return createWithChild(Node::Kind::ProtocolDescriptor, popProtocol());
1845+
case 'P':
1846+
return createWithPoppedType(Node::Kind::GenericTypeMetadataPattern);
18311847
case 'Q':
18321848
return createWithChild(Node::Kind::OpaqueTypeDescriptor, popNode());
1849+
case 'r':
1850+
return createWithPoppedType(Node::Kind::TypeMetadataCompletionFunction);
1851+
case 's':
1852+
return createWithPoppedType(Node::Kind::ObjCResilientClassStub);
18331853
case 'S':
18341854
return createWithChild(Node::Kind::ProtocolSelfConformanceDescriptor,
18351855
popProtocol());
1856+
case 't':
1857+
return createWithPoppedType(Node::Kind::FullObjCResilientClassStub);
18361858
case 'u':
18371859
return createWithPoppedType(Node::Kind::MethodLookupFunction);
18381860
case 'U':
18391861
return createWithPoppedType(Node::Kind::ObjCMetadataUpdateFunction);
1840-
case 's':
1841-
return createWithPoppedType(Node::Kind::ObjCResilientClassStub);
1842-
case 't':
1843-
return createWithPoppedType(Node::Kind::FullObjCResilientClassStub);
1844-
case 'B':
1845-
return createWithChild(Node::Kind::ReflectionMetadataBuiltinDescriptor,
1846-
popNode(Node::Kind::Type));
1847-
case 'F':
1848-
return createWithChild(Node::Kind::ReflectionMetadataFieldDescriptor,
1849-
popNode(Node::Kind::Type));
1850-
case 'A':
1851-
return createWithChild(Node::Kind::ReflectionMetadataAssocTypeDescriptor,
1852-
popProtocolConformance());
1853-
case 'C': {
1854-
NodePointer Ty = popNode(Node::Kind::Type);
1855-
if (!Ty || !isAnyGeneric(Ty->getChild(0)->getKind()))
1856-
return nullptr;
1857-
return createWithChild(Node::Kind::ReflectionMetadataSuperclassDescriptor,
1858-
Ty->getChild(0));
1859-
}
18601862
case 'V':
18611863
return createWithChild(Node::Kind::PropertyDescriptor,
18621864
popNode(isEntity));

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ class NodePrinter {
472472
case Node::Kind::TypeMetadataInstantiationCache:
473473
case Node::Kind::TypeMetadataInstantiationFunction:
474474
case Node::Kind::TypeMetadataSingletonInitializationCache:
475+
case Node::Kind::TypeMetadataDemanglingCache:
475476
case Node::Kind::TypeMetadataLazyCache:
476477
case Node::Kind::UncurriedFunctionType:
477478
#define REF_STORAGE(Name, ...) \
@@ -1679,6 +1680,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
16791680
Printer << "type metadata completion function for ";
16801681
print(Node->getChild(0));
16811682
return nullptr;
1683+
case Node::Kind::TypeMetadataDemanglingCache:
1684+
Printer << "demangling cache variable for type metadata for ";
1685+
print(Node->getChild(0));
1686+
return nullptr;
16821687
case Node::Kind::TypeMetadataLazyCache:
16831688
Printer << "lazy cache variable for type metadata for ";
16841689
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,10 @@ void Remangler::mangleTypeMetadataCompletionFunction(Node *node) {
513513
mangleSingleChildNode(node); // type
514514
}
515515

516+
void Remangler::mangleTypeMetadataDemanglingCache(Node *node) {
517+
unreachable("not supported");
518+
}
519+
516520
void Remangler::mangleTypeMetadataLazyCache(Node *node) {
517521
Buffer << "ML";
518522
mangleSingleChildNode(node); // type

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,11 @@ void Remangler::mangleTypeMetadataCompletionFunction(Node *node) {
20652065
Buffer << "Mr";
20662066
}
20672067

2068+
void Remangler::mangleTypeMetadataDemanglingCache(Node *node) {
2069+
mangleChildNodes(node);
2070+
Buffer << "MD";
2071+
}
2072+
20682073
void Remangler::mangleTypeMetadataLazyCache(Node *node) {
20692074
mangleChildNodes(node);
20702075
Buffer << "ML";

lib/IRGen/GenBuiltin.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,18 +799,24 @@ if (Builtin.ID == BuiltinValueKind::id) { \
799799

800800
// If we know the platform runtime's "done" value, emit the check inline.
801801
llvm::BasicBlock *doneBB = nullptr;
802+
803+
llvm::BasicBlock *beforeBB = IGF.Builder.GetInsertBlock();
802804

803805
if (auto ExpectedPred = IGF.IGM.TargetInfo.OnceDonePredicateValue) {
804806
auto PredValue = IGF.Builder.CreateLoad(PredPtr,
805807
IGF.IGM.getPointerAlignment());
806808
auto ExpectedPredValue = llvm::ConstantInt::getSigned(IGF.IGM.OnceTy,
807809
*ExpectedPred);
808810
auto PredIsDone = IGF.Builder.CreateICmpEQ(PredValue, ExpectedPredValue);
811+
PredIsDone = IGF.Builder.CreateExpect(PredIsDone,
812+
llvm::ConstantInt::get(IGF.IGM.Int1Ty, 1));
809813

810814
auto notDoneBB = IGF.createBasicBlock("once_not_done");
811815
doneBB = IGF.createBasicBlock("once_done");
812816

813817
IGF.Builder.CreateCondBr(PredIsDone, doneBB, notDoneBB);
818+
819+
IGF.Builder.SetInsertPoint(&IGF.CurFn->back());
814820
IGF.Builder.emitBlock(notDoneBB);
815821
}
816822

@@ -822,6 +828,7 @@ if (Builtin.ID == BuiltinValueKind::id) { \
822828
// If we emitted the "done" check inline, join the branches.
823829
if (auto ExpectedPred = IGF.IGM.TargetInfo.OnceDonePredicateValue) {
824830
IGF.Builder.CreateBr(doneBB);
831+
IGF.Builder.SetInsertPoint(beforeBB);
825832
IGF.Builder.emitBlock(doneBB);
826833
// We can assume the once predicate is in the "done" state now.
827834
auto PredValue = IGF.Builder.CreateLoad(PredPtr,

lib/IRGen/GenCall.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,8 +1538,6 @@ void CallEmission::emitToUnmappedExplosion(Explosion &out) {
15381538
// for methods that have covariant ABI-compatible overrides.
15391539
auto expectedNativeResultType = nativeSchema.getExpandedType(IGF.IGM);
15401540
if (result->getType() != expectedNativeResultType) {
1541-
assert(origFnType->getLanguage() == SILFunctionLanguage::C ||
1542-
origFnType->getRepresentation() == SILFunctionTypeRepresentation::Method);
15431541
result =
15441542
IGF.coerceValue(result, expectedNativeResultType, IGF.IGM.DataLayout);
15451543
}

lib/IRGen/GenDecl.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "llvm/Support/ConvertUTF.h"
4848
#include "llvm/Support/Path.h"
4949
#include "llvm/Support/SaveAndRestore.h"
50+
#include "llvm/Target/TargetMachine.h"
5051
#include "llvm/Transforms/Utils/ModuleUtils.h"
5152

5253
#include "Callee.h"
@@ -1248,6 +1249,14 @@ void IRGenerator::noteUseOfTypeGlobals(NominalTypeDecl *type,
12481249
RequireMetadata_t requireMetadata) {
12491250
if (!type)
12501251
return;
1252+
1253+
// Force emission of ObjC protocol descriptors used by type refs.
1254+
if (auto proto = dyn_cast<ProtocolDecl>(type)) {
1255+
if (proto->isObjC()) {
1256+
PrimaryIGM->getAddrOfObjCProtocolRecord(proto, NotForDefinition);
1257+
return;
1258+
}
1259+
}
12511260

12521261
if (!hasLazyMetadata(type))
12531262
return;
@@ -2562,7 +2571,11 @@ static llvm::GlobalVariable *createGOTEquivalent(IRGenModule &IGM,
25622571
// rdar://problem/50968433: Unnamed_addr constants appear to get emitted
25632572
// with incorrect alignment by the LLVM JIT in some cases. Don't use
25642573
// unnamed_addr as a workaround.
2565-
if (!IGM.getOptions().UseJIT) {
2574+
// rdar://problem/53836960: i386 ld64 also mis-links relative references
2575+
// to GOT entries.
2576+
if (!IGM.getOptions().UseJIT
2577+
&& (!IGM.Triple.isOSDarwin()
2578+
|| IGM.Triple.getArch() != llvm::Triple::x86)) {
25662579
gotEquivalent->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
25672580
} else {
25682581
ApplyIRLinkage(IRLinkage::InternalLinkOnceODR)
@@ -3411,22 +3424,29 @@ IRGenModule::getAddrOfGenericTypeMetadataAccessFunction(
34113424
/// Get or create a type metadata cache variable. These are an
34123425
/// implementation detail of type metadata access functions.
34133426
llvm::Constant *
3414-
IRGenModule::getAddrOfTypeMetadataLazyCacheVariable(CanType type,
3415-
ForDefinition_t forDefinition) {
3427+
IRGenModule::getAddrOfTypeMetadataLazyCacheVariable(CanType type) {
34163428
assert(!type->hasArchetype() && !type->hasTypeParameter());
34173429
LinkEntity entity = LinkEntity::forTypeMetadataLazyCacheVariable(type);
34183430
auto variable =
3419-
getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
3431+
getAddrOfLLVMVariable(entity, ForDefinition, DebugTypeInfo());
34203432

34213433
// Zero-initialize if we're asking for a definition.
3422-
if (forDefinition) {
3423-
cast<llvm::GlobalVariable>(variable)->setInitializer(
3424-
llvm::ConstantPointerNull::get(TypeMetadataPtrTy));
3425-
}
3434+
cast<llvm::GlobalVariable>(variable)->setInitializer(
3435+
llvm::ConstantPointerNull::get(TypeMetadataPtrTy));
34263436

34273437
return variable;
34283438
}
34293439

3440+
/// Get or create a type metadata cache variable. These are an
3441+
/// implementation detail of type metadata access functions.
3442+
llvm::Constant *
3443+
IRGenModule::getAddrOfTypeMetadataDemanglingCacheVariable(CanType type,
3444+
ConstantInit definition) {
3445+
assert(!type->hasArchetype() && !type->hasTypeParameter());
3446+
LinkEntity entity = LinkEntity::forTypeMetadataDemanglingCacheVariable(type);
3447+
return getAddrOfLLVMVariable(entity, definition, DebugTypeInfo());
3448+
}
3449+
34303450
llvm::Constant *
34313451
IRGenModule::getAddrOfTypeMetadataSingletonInitializationCache(
34323452
NominalTypeDecl *D,

lib/IRGen/GenKeyPath.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ getInitializerForComputedComponent(IRGenModule &IGM,
651651
static llvm::Constant *
652652
emitMetadataTypeRefForKeyPath(IRGenModule &IGM, CanType type) {
653653
// Produce a mangled name for the type.
654-
auto constant = IGM.getTypeRef(type, MangledTypeRefRole::Metadata);
654+
auto constant = IGM.getTypeRef(type, MangledTypeRefRole::Metadata).first;
655655

656656
// Mask the bottom bit to tell the key path runtime this is a mangled name
657657
// rather than a direct reference.

lib/IRGen/GenMeta.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ namespace {
470470
void addExtendedContext() {
471471
auto string = IGM.getTypeRef(E->getSelfInterfaceType(),
472472
E->getGenericSignature(),
473-
MangledTypeRefRole::Metadata);
473+
MangledTypeRefRole::Metadata).first;
474474
B.addRelativeAddress(string);
475475
}
476476

@@ -1594,7 +1594,8 @@ namespace {
15941594
GenericSignature *genericSig = getType()->getGenericSignature();
15951595
B.addRelativeAddress(IGM.getTypeRef(superclassType->getCanonicalType(),
15961596
genericSig,
1597-
MangledTypeRefRole::Metadata));
1597+
MangledTypeRefRole::Metadata)
1598+
.first);
15981599
} else {
15991600
B.addInt32(0);
16001601
}
@@ -1685,7 +1686,7 @@ namespace {
16851686
->getCanonicalType(O->getOpaqueInterfaceGenericSignature());
16861687

16871688
B.addRelativeAddress(IGM.getTypeRef(underlyingType,
1688-
MangledTypeRefRole::Metadata));
1689+
MangledTypeRefRole::Metadata).first);
16891690

16901691
auto opaqueType = O->getDeclaredInterfaceType()
16911692
->castTo<OpaqueTypeArchetypeType>();
@@ -4266,7 +4267,7 @@ static void addGenericRequirement(IRGenModule &IGM, ConstantStructBuilder &B,
42664267

42674268
B.addInt(IGM.Int32Ty, flags.getIntValue());
42684269
auto typeName =
4269-
IGM.getTypeRef(paramType, nullptr, MangledTypeRefRole::Metadata);
4270+
IGM.getTypeRef(paramType, nullptr, MangledTypeRefRole::Metadata).first;
42704271
B.addRelativeAddress(typeName);
42714272
addReference();
42724273
}
@@ -4334,7 +4335,7 @@ GenericRequirementsMetadata irgen::addGenericRequirements(
43344335
auto flags = GenericRequirementFlags(abiKind, false, false);
43354336
auto typeName =
43364337
IGM.getTypeRef(requirement.getSecondType(), nullptr,
4337-
MangledTypeRefRole::Metadata);
4338+
MangledTypeRefRole::Metadata).first;
43384339

43394340
addGenericRequirement(IGM, B, metadata, sig, flags,
43404341
requirement.getFirstType(),

lib/IRGen/GenProto.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1432,7 +1432,7 @@ llvm::Constant *IRGenModule::getAssociatedTypeWitness(Type type,
14321432
auto role = inProtocolContext
14331433
? MangledTypeRefRole::DefaultAssociatedTypeWitness
14341434
: MangledTypeRefRole::Metadata;
1435-
auto typeRef = getTypeRef(type, /*generic signature*/nullptr, role);
1435+
auto typeRef = getTypeRef(type, /*generic signature*/nullptr, role).first;
14361436

14371437
// Set the low bit to indicate that this is a mangled name.
14381438
auto witness = llvm::ConstantExpr::getPtrToInt(typeRef, IntPtrTy);

0 commit comments

Comments
 (0)