@@ -547,9 +547,8 @@ static void collectGlobalList(IRGenModule &IGM,
547
547
static llvm::GlobalVariable *
548
548
emitGlobalList (IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
549
549
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) {
553
552
// Do nothing if the list is empty.
554
553
if (handles.empty ()) return nullptr ;
555
554
@@ -558,6 +557,31 @@ emitGlobalList(IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
558
557
// so that the linker doesn't accidentally put padding in the list.
559
558
Alignment alignment = IGM.getPointerAlignment ();
560
559
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
+ std::string eltName = name.str () + " _" + elt->getName ().str ();
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
+
561
585
// We have an array of value handles, but we need an array of constants.
562
586
SmallVector<llvm::Constant*, 8 > elts;
563
587
elts.reserve (handles.size ());
@@ -1037,36 +1061,41 @@ void IRGenModule::emitGlobalLists() {
1037
1061
if (ObjCInterop) {
1038
1062
// Objective-C class references go in a variable with a meaningless
1039
1063
// 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 );
1044
1069
1045
1070
// 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 );
1050
1076
1051
1077
// 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 );
1056
1083
1057
1084
// 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 );
1070
1099
}
1071
1100
1072
1101
// @llvm.used
@@ -1076,15 +1105,15 @@ void IRGenModule::emitGlobalLists() {
1076
1105
emitGlobalList (*this , LLVMUsed, " llvm.used" , " llvm.metadata" ,
1077
1106
llvm::GlobalValue::AppendingLinkage,
1078
1107
Int8PtrTy,
1079
- false );
1108
+ /* isConstant */ false , /* asContiguousArray */ true );
1080
1109
1081
1110
// Collect llvm.compiler.used globals already in the module (coming
1082
1111
// from ClangCodeGen).
1083
1112
collectGlobalList (*this , LLVMCompilerUsed, " llvm.compiler.used" );
1084
1113
emitGlobalList (*this , LLVMCompilerUsed, " llvm.compiler.used" , " llvm.metadata" ,
1085
1114
llvm::GlobalValue::AppendingLinkage,
1086
1115
Int8PtrTy,
1087
- false );
1116
+ /* isConstant */ false , /* asContiguousArray */ true );
1088
1117
}
1089
1118
1090
1119
static bool hasCodeCoverageInstrumentation (SILFunction &f, SILModule &m) {
@@ -3720,39 +3749,34 @@ IRGenModule::emitDirectRelativeReference(llvm::Constant *target,
3720
3749
3721
3750
// / Expresses that `var` is removable (dead-strippable) when `dependsOn` is not
3722
3751
// / referenced.
3723
- static void appendLLVMUsedConditionalEntry (IRGenModule &IGM,
3724
- llvm::GlobalVariable *var,
3725
- llvm::Constant *dependsOn) {
3752
+ void IRGenModule::appendLLVMUsedConditionalEntry (llvm::GlobalVariable *var,
3753
+ llvm::Constant *dependsOn) {
3726
3754
llvm::Metadata *metadata[] = {
3727
3755
// (1) which variable is being conditionalized, "target"
3728
3756
llvm::ConstantAsMetadata::get (var),
3729
3757
// (2) type, not relevant for a single-edge condition
3730
3758
llvm::ConstantAsMetadata::get (llvm::ConstantInt::get (
3731
- llvm::Type::getInt32Ty (IGM. Module .getContext ()), 0 )),
3759
+ llvm::Type::getInt32Ty (Module.getContext ()), 0 )),
3732
3760
// (3) the "edge" that holds the target alive, if it's missing the target
3733
3761
// is allowed to be removed
3734
- llvm::MDNode::get (IGM. Module .getContext (),
3762
+ llvm::MDNode::get (Module.getContext (),
3735
3763
{
3736
3764
llvm::ConstantAsMetadata::get (dependsOn),
3737
3765
}),
3738
3766
};
3739
3767
auto *usedConditional =
3740
- IGM.Module .getOrInsertNamedMetadata (" llvm.used.conditional" );
3741
- usedConditional->addOperand (
3742
- llvm::MDNode::get (IGM.Module .getContext (), metadata));
3768
+ Module.getOrInsertNamedMetadata (" llvm.used.conditional" );
3769
+ usedConditional->addOperand (llvm::MDNode::get (Module.getContext (), metadata));
3743
3770
}
3744
3771
3745
3772
// / Expresses that `var` is removable (dead-strippable) when either the protocol
3746
3773
// / from `record` is not referenced or the type from `record` is not referenced.
3747
- static void
3748
- appendLLVMUsedConditionalEntry (IRGenModule &IGM, llvm::GlobalVariable *var,
3749
- const ConformanceDescription &record) {
3750
- auto *protocol =
3751
- IGM.getAddrOfProtocolDescriptor (record.conformance ->getProtocol ())
3752
- ->stripPointerCasts ();
3753
- auto *type = IGM.getAddrOfTypeContextDescriptor (
3754
- record.conformance ->getType ()->getAnyNominal (),
3755
- DontRequireMetadata)
3774
+ void IRGenModule::appendLLVMUsedConditionalEntry (
3775
+ llvm::GlobalVariable *var, const ProtocolConformance *conformance) {
3776
+ auto *protocol = getAddrOfProtocolDescriptor (conformance->getProtocol ())
3777
+ ->stripPointerCasts ();
3778
+ auto *type = getAddrOfTypeContextDescriptor (
3779
+ conformance->getType ()->getAnyNominal (), DontRequireMetadata)
3756
3780
->stripPointerCasts ();
3757
3781
3758
3782
llvm::Metadata *metadata[] = {
@@ -3761,18 +3785,17 @@ appendLLVMUsedConditionalEntry(IRGenModule &IGM, llvm::GlobalVariable *var,
3761
3785
// (2) type, "1" = if either edge is missing, the target is allowed to be
3762
3786
// removed.
3763
3787
llvm::ConstantAsMetadata::get (llvm::ConstantInt::get (
3764
- llvm::Type::getInt32Ty (IGM. Module .getContext ()), 1 )),
3788
+ llvm::Type::getInt32Ty (Module.getContext ()), 1 )),
3765
3789
// (3) list of edges
3766
- llvm::MDNode::get (IGM. Module .getContext (),
3790
+ llvm::MDNode::get (Module.getContext (),
3767
3791
{
3768
3792
llvm::ConstantAsMetadata::get (protocol),
3769
3793
llvm::ConstantAsMetadata::get (type),
3770
3794
}),
3771
3795
};
3772
3796
auto *usedConditional =
3773
- IGM.Module .getOrInsertNamedMetadata (" llvm.used.conditional" );
3774
- usedConditional->addOperand (
3775
- llvm::MDNode::get (IGM.Module .getContext (), metadata));
3797
+ Module.getOrInsertNamedMetadata (" llvm.used.conditional" );
3798
+ usedConditional->addOperand (llvm::MDNode::get (Module.getContext (), metadata));
3776
3799
}
3777
3800
3778
3801
// / Emit the protocol descriptors list and return it (if asContiguousArray is
@@ -3854,7 +3877,7 @@ llvm::Constant *IRGenModule::emitSwiftProtocols(bool asContiguousArray) {
3854
3877
if (IRGen.Opts .ConditionalRuntimeRecords ) {
3855
3878
// Allow dead-stripping `var` (the protocol record) when the protocol
3856
3879
// (descriptorRef) is not referenced.
3857
- appendLLVMUsedConditionalEntry (* this , var, descriptorRef.getValue ());
3880
+ appendLLVMUsedConditionalEntry (var, descriptorRef.getValue ());
3858
3881
}
3859
3882
}
3860
3883
@@ -3948,7 +3971,7 @@ llvm::Constant *IRGenModule::emitProtocolConformances(bool asContiguousArray) {
3948
3971
if (IRGen.Opts .ConditionalRuntimeRecords ) {
3949
3972
// Allow dead-stripping `var` (the conformance record) when the protocol
3950
3973
// or type (from the conformance) is not referenced.
3951
- appendLLVMUsedConditionalEntry (* this , var, record);
3974
+ appendLLVMUsedConditionalEntry (var, record. conformance );
3952
3975
}
3953
3976
}
3954
3977
@@ -4063,7 +4086,7 @@ llvm::Constant *IRGenModule::emitTypeMetadataRecords(bool asContiguousArray) {
4063
4086
if (IRGen.Opts .ConditionalRuntimeRecords ) {
4064
4087
// Allow dead-stripping `var` (the type record) when the type (`ref`) is
4065
4088
// not referenced.
4066
- appendLLVMUsedConditionalEntry (* this , var, ref.getValue ());
4089
+ appendLLVMUsedConditionalEntry (var, ref.getValue ());
4067
4090
}
4068
4091
}
4069
4092
0 commit comments