@@ -547,9 +547,8 @@ static void collectGlobalList(IRGenModule &IGM,
547547static llvm::GlobalVariable *
548548emitGlobalList (IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
549549 StringRef name, StringRef section,
550- llvm::GlobalValue::LinkageTypes linkage,
551- llvm::Type *eltTy,
552- bool isConstant) {
550+ llvm::GlobalValue::LinkageTypes linkage, llvm::Type *eltTy,
551+ bool isConstant, bool asContiguousArray) {
553552 // Do nothing if the list is empty.
554553 if (handles.empty ()) return nullptr ;
555554
@@ -558,6 +557,31 @@ emitGlobalList(IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
558557 // so that the linker doesn't accidentally put padding in the list.
559558 Alignment alignment = IGM.getPointerAlignment ();
560559
560+ if (!asContiguousArray) {
561+ // Emit as individual globals, which is required for conditional runtime
562+ // records to work.
563+ for (auto &handle : handles) {
564+ llvm::Constant *elt = cast<llvm::Constant>(&*handle);
565+ auto eltName = name + " _" + elt->getName ();
566+ if (elt->getType () != eltTy)
567+ elt = llvm::ConstantExpr::getBitCast (elt, eltTy);
568+ auto var = new llvm::GlobalVariable (IGM.Module , eltTy, isConstant,
569+ linkage, elt, eltName);
570+ var->setSection (section);
571+ var->setAlignment (llvm::MaybeAlign (alignment.getValue ()));
572+ disableAddressSanitizer (IGM, var);
573+ if (llvm::GlobalValue::isLocalLinkage (linkage))
574+ IGM.addUsedGlobal (var);
575+
576+ if (IGM.IRGen .Opts .ConditionalRuntimeRecords ) {
577+ // Allow dead-stripping `var` (the runtime record from the global list)
578+ // when `handle` / `elt` (the underlaying entity) is not referenced.
579+ IGM.appendLLVMUsedConditionalEntry (var, elt->stripPointerCasts ());
580+ }
581+ }
582+ return nullptr ;
583+ }
584+
561585 // We have an array of value handles, but we need an array of constants.
562586 SmallVector<llvm::Constant*, 8 > elts;
563587 elts.reserve (handles.size ());
@@ -1037,36 +1061,41 @@ void IRGenModule::emitGlobalLists() {
10371061 if (ObjCInterop) {
10381062 // Objective-C class references go in a variable with a meaningless
10391063 // name but a magic section.
1040- emitGlobalList (*this , ObjCClasses, " objc_classes" ,
1041- GetObjCSectionName (" __objc_classlist" ,
1042- " regular,no_dead_strip" ),
1043- llvm::GlobalValue::InternalLinkage, Int8PtrTy, false );
1064+ emitGlobalList (
1065+ *this , ObjCClasses, " objc_classes" ,
1066+ GetObjCSectionName (" __objc_classlist" , " regular,no_dead_strip" ),
1067+ llvm::GlobalValue::InternalLinkage, Int8PtrTy, /* isConstant*/ false ,
1068+ /* asContiguousArray*/ false );
10441069
10451070 // So do resilient class stubs.
1046- emitGlobalList (*this , ObjCClassStubs, " objc_class_stubs" ,
1047- GetObjCSectionName (" __objc_stublist" ,
1048- " regular,no_dead_strip" ),
1049- llvm::GlobalValue::InternalLinkage, Int8PtrTy, false );
1071+ emitGlobalList (
1072+ *this , ObjCClassStubs, " objc_class_stubs" ,
1073+ GetObjCSectionName (" __objc_stublist" , " regular,no_dead_strip" ),
1074+ llvm::GlobalValue::InternalLinkage, Int8PtrTy, /* isConstant*/ false ,
1075+ /* asContiguousArray*/ true );
10501076
10511077 // So do categories.
1052- emitGlobalList (*this , ObjCCategories, " objc_categories" ,
1053- GetObjCSectionName (" __objc_catlist" ,
1054- " regular,no_dead_strip" ),
1055- llvm::GlobalValue::InternalLinkage, Int8PtrTy, false );
1078+ emitGlobalList (
1079+ *this , ObjCCategories, " objc_categories" ,
1080+ GetObjCSectionName (" __objc_catlist" , " regular,no_dead_strip" ),
1081+ llvm::GlobalValue::InternalLinkage, Int8PtrTy, /* isConstant*/ false ,
1082+ /* asContiguousArray*/ true );
10561083
10571084 // And categories on class stubs.
1058- emitGlobalList (*this , ObjCCategoriesOnStubs, " objc_categories_stubs" ,
1059- GetObjCSectionName (" __objc_catlist2" ,
1060- " regular,no_dead_strip" ),
1061- llvm::GlobalValue::InternalLinkage, Int8PtrTy, false );
1062-
1063- // Emit nonlazily realized class references in a second magic section to make
1064- // sure they are realized by the Objective-C runtime before any instances
1065- // are allocated.
1066- emitGlobalList (*this , ObjCNonLazyClasses, " objc_non_lazy_classes" ,
1067- GetObjCSectionName (" __objc_nlclslist" ,
1068- " regular,no_dead_strip" ),
1069- llvm::GlobalValue::InternalLinkage, Int8PtrTy, false );
1085+ emitGlobalList (
1086+ *this , ObjCCategoriesOnStubs, " objc_categories_stubs" ,
1087+ GetObjCSectionName (" __objc_catlist2" , " regular,no_dead_strip" ),
1088+ llvm::GlobalValue::InternalLinkage, Int8PtrTy, /* isConstant*/ false ,
1089+ /* asContiguousArray*/ true );
1090+
1091+ // Emit nonlazily realized class references in a second magic section to
1092+ // make sure they are realized by the Objective-C runtime before any
1093+ // instances are allocated.
1094+ emitGlobalList (
1095+ *this , ObjCNonLazyClasses, " objc_non_lazy_classes" ,
1096+ GetObjCSectionName (" __objc_nlclslist" , " regular,no_dead_strip" ),
1097+ llvm::GlobalValue::InternalLinkage, Int8PtrTy, /* isConstant*/ false ,
1098+ /* asContiguousArray*/ true );
10701099 }
10711100
10721101 // @llvm.used
@@ -1076,15 +1105,15 @@ void IRGenModule::emitGlobalLists() {
10761105 emitGlobalList (*this , LLVMUsed, " llvm.used" , " llvm.metadata" ,
10771106 llvm::GlobalValue::AppendingLinkage,
10781107 Int8PtrTy,
1079- false );
1108+ /* isConstant */ false , /* asContiguousArray */ true );
10801109
10811110 // Collect llvm.compiler.used globals already in the module (coming
10821111 // from ClangCodeGen).
10831112 collectGlobalList (*this , LLVMCompilerUsed, " llvm.compiler.used" );
10841113 emitGlobalList (*this , LLVMCompilerUsed, " llvm.compiler.used" , " llvm.metadata" ,
10851114 llvm::GlobalValue::AppendingLinkage,
10861115 Int8PtrTy,
1087- false );
1116+ /* isConstant */ false , /* asContiguousArray */ true );
10881117}
10891118
10901119static bool hasCodeCoverageInstrumentation (SILFunction &f, SILModule &m) {
@@ -3709,39 +3738,34 @@ IRGenModule::emitDirectRelativeReference(llvm::Constant *target,
37093738
37103739// / Expresses that `var` is removable (dead-strippable) when `dependsOn` is not
37113740// / referenced.
3712- static void appendLLVMUsedConditionalEntry (IRGenModule &IGM,
3713- llvm::GlobalVariable *var,
3714- llvm::Constant *dependsOn) {
3741+ void IRGenModule::appendLLVMUsedConditionalEntry (llvm::GlobalVariable *var,
3742+ llvm::Constant *dependsOn) {
37153743 llvm::Metadata *metadata[] = {
37163744 // (1) which variable is being conditionalized, "target"
37173745 llvm::ConstantAsMetadata::get (var),
37183746 // (2) type, not relevant for a single-edge condition
37193747 llvm::ConstantAsMetadata::get (llvm::ConstantInt::get (
3720- llvm::Type::getInt32Ty (IGM. Module .getContext ()), 0 )),
3748+ llvm::Type::getInt32Ty (Module.getContext ()), 0 )),
37213749 // (3) the "edge" that holds the target alive, if it's missing the target
37223750 // is allowed to be removed
3723- llvm::MDNode::get (IGM. Module .getContext (),
3751+ llvm::MDNode::get (Module.getContext (),
37243752 {
37253753 llvm::ConstantAsMetadata::get (dependsOn),
37263754 }),
37273755 };
37283756 auto *usedConditional =
3729- IGM.Module .getOrInsertNamedMetadata (" llvm.used.conditional" );
3730- usedConditional->addOperand (
3731- llvm::MDNode::get (IGM.Module .getContext (), metadata));
3757+ Module.getOrInsertNamedMetadata (" llvm.used.conditional" );
3758+ usedConditional->addOperand (llvm::MDNode::get (Module.getContext (), metadata));
37323759}
37333760
37343761// / Expresses that `var` is removable (dead-strippable) when either the protocol
37353762// / from `record` is not referenced or the type from `record` is not referenced.
3736- static void
3737- appendLLVMUsedConditionalEntry (IRGenModule &IGM, llvm::GlobalVariable *var,
3738- const ConformanceDescription &record) {
3739- auto *protocol =
3740- IGM.getAddrOfProtocolDescriptor (record.conformance ->getProtocol ())
3741- ->stripPointerCasts ();
3742- auto *type = IGM.getAddrOfTypeContextDescriptor (
3743- record.conformance ->getType ()->getAnyNominal (),
3744- DontRequireMetadata)
3763+ void IRGenModule::appendLLVMUsedConditionalEntry (
3764+ llvm::GlobalVariable *var, const ProtocolConformance *conformance) {
3765+ auto *protocol = getAddrOfProtocolDescriptor (conformance->getProtocol ())
3766+ ->stripPointerCasts ();
3767+ auto *type = getAddrOfTypeContextDescriptor (
3768+ conformance->getType ()->getAnyNominal (), DontRequireMetadata)
37453769 ->stripPointerCasts ();
37463770
37473771 llvm::Metadata *metadata[] = {
@@ -3750,18 +3774,17 @@ appendLLVMUsedConditionalEntry(IRGenModule &IGM, llvm::GlobalVariable *var,
37503774 // (2) type, "1" = if either edge is missing, the target is allowed to be
37513775 // removed.
37523776 llvm::ConstantAsMetadata::get (llvm::ConstantInt::get (
3753- llvm::Type::getInt32Ty (IGM. Module .getContext ()), 1 )),
3777+ llvm::Type::getInt32Ty (Module.getContext ()), 1 )),
37543778 // (3) list of edges
3755- llvm::MDNode::get (IGM. Module .getContext (),
3779+ llvm::MDNode::get (Module.getContext (),
37563780 {
37573781 llvm::ConstantAsMetadata::get (protocol),
37583782 llvm::ConstantAsMetadata::get (type),
37593783 }),
37603784 };
37613785 auto *usedConditional =
3762- IGM.Module .getOrInsertNamedMetadata (" llvm.used.conditional" );
3763- usedConditional->addOperand (
3764- llvm::MDNode::get (IGM.Module .getContext (), metadata));
3786+ Module.getOrInsertNamedMetadata (" llvm.used.conditional" );
3787+ usedConditional->addOperand (llvm::MDNode::get (Module.getContext (), metadata));
37653788}
37663789
37673790// / Emit the protocol descriptors list and return it (if asContiguousArray is
@@ -3843,7 +3866,7 @@ llvm::Constant *IRGenModule::emitSwiftProtocols(bool asContiguousArray) {
38433866 if (IRGen.Opts .ConditionalRuntimeRecords ) {
38443867 // Allow dead-stripping `var` (the protocol record) when the protocol
38453868 // (descriptorRef) is not referenced.
3846- appendLLVMUsedConditionalEntry (* this , var, descriptorRef.getValue ());
3869+ appendLLVMUsedConditionalEntry (var, descriptorRef.getValue ());
38473870 }
38483871 }
38493872
@@ -3937,7 +3960,7 @@ llvm::Constant *IRGenModule::emitProtocolConformances(bool asContiguousArray) {
39373960 if (IRGen.Opts .ConditionalRuntimeRecords ) {
39383961 // Allow dead-stripping `var` (the conformance record) when the protocol
39393962 // or type (from the conformance) is not referenced.
3940- appendLLVMUsedConditionalEntry (* this , var, record);
3963+ appendLLVMUsedConditionalEntry (var, record. conformance );
39413964 }
39423965 }
39433966
@@ -4052,7 +4075,7 @@ llvm::Constant *IRGenModule::emitTypeMetadataRecords(bool asContiguousArray) {
40524075 if (IRGen.Opts .ConditionalRuntimeRecords ) {
40534076 // Allow dead-stripping `var` (the type record) when the type (`ref`) is
40544077 // not referenced.
4055- appendLLVMUsedConditionalEntry (* this , var, ref.getValue ());
4078+ appendLLVMUsedConditionalEntry (var, ref.getValue ());
40564079 }
40574080 }
40584081
0 commit comments