@@ -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) {
@@ -3709,39 +3738,34 @@ IRGenModule::emitDirectRelativeReference(llvm::Constant *target,
3709
3738
3710
3739
// / Expresses that `var` is removable (dead-strippable) when `dependsOn` is not
3711
3740
// / 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) {
3715
3743
llvm::Metadata *metadata[] = {
3716
3744
// (1) which variable is being conditionalized, "target"
3717
3745
llvm::ConstantAsMetadata::get (var),
3718
3746
// (2) type, not relevant for a single-edge condition
3719
3747
llvm::ConstantAsMetadata::get (llvm::ConstantInt::get (
3720
- llvm::Type::getInt32Ty (IGM. Module .getContext ()), 0 )),
3748
+ llvm::Type::getInt32Ty (Module.getContext ()), 0 )),
3721
3749
// (3) the "edge" that holds the target alive, if it's missing the target
3722
3750
// is allowed to be removed
3723
- llvm::MDNode::get (IGM. Module .getContext (),
3751
+ llvm::MDNode::get (Module.getContext (),
3724
3752
{
3725
3753
llvm::ConstantAsMetadata::get (dependsOn),
3726
3754
}),
3727
3755
};
3728
3756
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));
3732
3759
}
3733
3760
3734
3761
// / Expresses that `var` is removable (dead-strippable) when either the protocol
3735
3762
// / 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)
3745
3769
->stripPointerCasts ();
3746
3770
3747
3771
llvm::Metadata *metadata[] = {
@@ -3750,18 +3774,17 @@ appendLLVMUsedConditionalEntry(IRGenModule &IGM, llvm::GlobalVariable *var,
3750
3774
// (2) type, "1" = if either edge is missing, the target is allowed to be
3751
3775
// removed.
3752
3776
llvm::ConstantAsMetadata::get (llvm::ConstantInt::get (
3753
- llvm::Type::getInt32Ty (IGM. Module .getContext ()), 1 )),
3777
+ llvm::Type::getInt32Ty (Module.getContext ()), 1 )),
3754
3778
// (3) list of edges
3755
- llvm::MDNode::get (IGM. Module .getContext (),
3779
+ llvm::MDNode::get (Module.getContext (),
3756
3780
{
3757
3781
llvm::ConstantAsMetadata::get (protocol),
3758
3782
llvm::ConstantAsMetadata::get (type),
3759
3783
}),
3760
3784
};
3761
3785
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));
3765
3788
}
3766
3789
3767
3790
// / Emit the protocol descriptors list and return it (if asContiguousArray is
@@ -3843,7 +3866,7 @@ llvm::Constant *IRGenModule::emitSwiftProtocols(bool asContiguousArray) {
3843
3866
if (IRGen.Opts .ConditionalRuntimeRecords ) {
3844
3867
// Allow dead-stripping `var` (the protocol record) when the protocol
3845
3868
// (descriptorRef) is not referenced.
3846
- appendLLVMUsedConditionalEntry (* this , var, descriptorRef.getValue ());
3869
+ appendLLVMUsedConditionalEntry (var, descriptorRef.getValue ());
3847
3870
}
3848
3871
}
3849
3872
@@ -3937,7 +3960,7 @@ llvm::Constant *IRGenModule::emitProtocolConformances(bool asContiguousArray) {
3937
3960
if (IRGen.Opts .ConditionalRuntimeRecords ) {
3938
3961
// Allow dead-stripping `var` (the conformance record) when the protocol
3939
3962
// or type (from the conformance) is not referenced.
3940
- appendLLVMUsedConditionalEntry (* this , var, record);
3963
+ appendLLVMUsedConditionalEntry (var, record. conformance );
3941
3964
}
3942
3965
}
3943
3966
@@ -4052,7 +4075,7 @@ llvm::Constant *IRGenModule::emitTypeMetadataRecords(bool asContiguousArray) {
4052
4075
if (IRGen.Opts .ConditionalRuntimeRecords ) {
4053
4076
// Allow dead-stripping `var` (the type record) when the type (`ref`) is
4054
4077
// not referenced.
4055
- appendLLVMUsedConditionalEntry (* this , var, ref.getValue ());
4078
+ appendLLVMUsedConditionalEntry (var, ref.getValue ());
4056
4079
}
4057
4080
}
4058
4081
0 commit comments