Skip to content

Commit 78f5e0b

Browse files
Merge pull request #60231 from aschwaighofer/generic_objc_method_list_section
IRGen: Add a list of class_ro_t referenced from generic class metadata patterns to a section __swift_rodatas
2 parents b33112f + 6ce452b commit 78f5e0b

File tree

7 files changed

+108
-6
lines changed

7 files changed

+108
-6
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,9 @@ class IRGenOptions {
401401
/// Internalize symbols (static library) - do not export any public symbols.
402402
unsigned InternalizeSymbols : 1;
403403

404+
/// Emit a section with references to class_ro_t* in generic class patterns.
405+
unsigned EmitGenericRODatas : 1;
406+
404407
/// Whether to avoid emitting zerofill globals as preallocated type metadata
405408
/// and protocol conformance caches.
406409
unsigned NoPreallocatedInstantiationCaches : 1;
@@ -475,7 +478,7 @@ class IRGenOptions {
475478
EnableGlobalISel(false), VirtualFunctionElimination(false),
476479
WitnessMethodElimination(false), ConditionalRuntimeRecords(false),
477480
InternalizeAtLink(false), InternalizeSymbols(false),
478-
NoPreallocatedInstantiationCaches(false),
481+
EmitGenericRODatas(false), NoPreallocatedInstantiationCaches(false),
479482
DisableReadonlyStaticObjects(false), CmdArgs(),
480483
SanitizeCoverage(llvm::SanitizerCoverageOptions()),
481484
TypeInfoFilter(TypeInfoDumpFilter::All) {

include/swift/Option/FrontendOptions.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,4 +1085,13 @@ def enable_new_llvm_pass_manager :
10851085
def disable_new_llvm_pass_manager :
10861086
Flag<["-"], "disable-new-llvm-pass-manager">,
10871087
HelpText<"Disable the new llvm pass manager">;
1088+
1089+
def disable_emit_generic_class_ro_t_list :
1090+
Flag<["-"], "disable-emit-generic-class-ro_t-list">,
1091+
HelpText<"Disable emission of a section with references to class_ro_t of "
1092+
"generic class patterns">;
1093+
def enable_emit_generic_class_ro_t_list :
1094+
Flag<["-"], "enable-emit-generic-class-ro_t-list">,
1095+
HelpText<"Enable emission of a section with references to class_ro_t of "
1096+
"generic class patterns">;
10881097
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

lib/Frontend/CompilerInvocation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2397,6 +2397,11 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
23972397
Opts.SwiftAsyncFramePointer = SwiftAsyncFramePointerKind::Never;
23982398
}
23992399

2400+
Opts.EmitGenericRODatas =
2401+
Args.hasFlag(OPT_enable_emit_generic_class_ro_t_list,
2402+
OPT_disable_emit_generic_class_ro_t_list,
2403+
Opts.EmitGenericRODatas);
2404+
24002405
Opts.LegacyPassManager =
24012406
Args.hasFlag(OPT_disable_new_llvm_pass_manager,
24022407
OPT_enable_new_llvm_pass_manager,

lib/IRGen/GenDecl.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ static llvm::GlobalVariable *
556556
emitGlobalList(IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
557557
StringRef name, StringRef section,
558558
llvm::GlobalValue::LinkageTypes linkage, llvm::Type *eltTy,
559-
bool isConstant, bool asContiguousArray) {
559+
bool isConstant, bool asContiguousArray, bool canBeStrippedByLinker = false) {
560560
// Do nothing if the list is empty.
561561
if (handles.empty()) return nullptr;
562562

@@ -578,8 +578,12 @@ emitGlobalList(IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
578578
var->setSection(section);
579579
var->setAlignment(llvm::MaybeAlign(alignment.getValue()));
580580
disableAddressSanitizer(IGM, var);
581-
if (llvm::GlobalValue::isLocalLinkage(linkage))
582-
IGM.addUsedGlobal(var);
581+
if (llvm::GlobalValue::isLocalLinkage(linkage)) {
582+
if (canBeStrippedByLinker)
583+
IGM.addCompilerUsedGlobal(var);
584+
else
585+
IGM.addUsedGlobal(var);
586+
}
583587

584588
if (IGM.IRGen.Opts.ConditionalRuntimeRecords) {
585589
// Allow dead-stripping `var` (the runtime record from the global list)
@@ -616,8 +620,12 @@ emitGlobalList(IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
616620

617621
// Mark the variable as used if doesn't have external linkage.
618622
// (Note that we'd specifically like to not put @llvm.used in itself.)
619-
if (llvm::GlobalValue::isLocalLinkage(linkage))
620-
IGM.addUsedGlobal(var);
623+
if (llvm::GlobalValue::isLocalLinkage(linkage)) {
624+
if (canBeStrippedByLinker)
625+
IGM.addCompilerUsedGlobal(var);
626+
else
627+
IGM.addUsedGlobal(var);
628+
}
621629
return var;
622630
}
623631

@@ -962,6 +970,10 @@ void IRGenModule::addCompilerUsedGlobal(llvm::GlobalValue *global) {
962970
LLVMCompilerUsed.push_back(global);
963971
}
964972

973+
void IRGenModule::addGenericROData(llvm::Constant *RODataAddr) {
974+
GenericRODatas.push_back(RODataAddr);
975+
}
976+
965977
/// Add the given global value to the Objective-C class list.
966978
void IRGenModule::addObjCClass(llvm::Constant *classPtr, bool nonlazy) {
967979
ObjCClasses.push_back(classPtr);
@@ -1067,6 +1079,14 @@ void IRGenModule::SetCStringLiteralSection(llvm::GlobalVariable *GV,
10671079

10681080
void IRGenModule::emitGlobalLists() {
10691081
if (ObjCInterop) {
1082+
if (IRGen.Opts.EmitGenericRODatas) {
1083+
emitGlobalList(
1084+
*this, GenericRODatas, "generic_ro_datas",
1085+
GetObjCSectionName("__swift_rodatas", "regular"),
1086+
llvm::GlobalValue::InternalLinkage, Int8PtrTy, /*isConstant*/ false,
1087+
/*asContiguousArray*/ true, /*canBeStrippedByLinker*/ true);
1088+
}
1089+
10701090
// Objective-C class references go in a variable with a meaningless
10711091
// name but a magic section.
10721092
emitGlobalList(

lib/IRGen/GenMeta.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4043,6 +4043,8 @@ namespace {
40434043
// Any bytes before this will be zeroed. Currently we don't take
40444044
// advantage of this.
40454045
Size patternOffset = Size(0);
4046+
Size classROData = Size(0);
4047+
Size metaclassROData = Size(0);
40464048

40474049
if (IGM.ObjCInterop) {
40484050
// Add the metaclass object.
@@ -4057,13 +4059,27 @@ namespace {
40574059
IGM.getOffsetInWords(patternOffset + roDataPoints.first));
40584060
B.fillPlaceholderWithInt(*MetaclassRODataOffset, IGM.Int16Ty,
40594061
IGM.getOffsetInWords(patternOffset + roDataPoints.second));
4062+
classROData = patternOffset + roDataPoints.first;
4063+
metaclassROData = patternOffset + roDataPoints.second;
40604064
}
40614065

40624066
auto patternSize = subB.getNextOffsetFromGlobal();
40634067

40644068
auto global = subB.finishAndCreateGlobal("", IGM.getPointerAlignment(),
40654069
/*constant*/ true);
4070+
if (IGM.ObjCInterop) {
4071+
auto getRODataAtOffset = [&] (Size offset) -> llvm::Constant * {
4072+
auto t0 = llvm::ConstantExpr::getBitCast(global, IGM.Int8PtrTy);
4073+
llvm::Constant *indices[] = {llvm::ConstantInt::get(IGM.Int32Ty, offset.getValue())};
4074+
return llvm::ConstantExpr::getBitCast(
4075+
llvm::ConstantExpr::getInBoundsGetElementPtr(IGM.Int8Ty,
4076+
t0, indices),
4077+
IGM.Int8PtrTy);
40664078

4079+
};
4080+
IGM.addGenericROData(getRODataAtOffset(classROData));
4081+
IGM.addGenericROData(getRODataAtOffset(metaclassROData));
4082+
}
40674083
return { global, patternOffset, patternSize };
40684084
}
40694085

lib/IRGen/IRGenModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,7 @@ class IRGenModule {
10801080

10811081
void addUsedGlobal(llvm::GlobalValue *global);
10821082
void addCompilerUsedGlobal(llvm::GlobalValue *global);
1083+
void addGenericROData(llvm::Constant *addr);
10831084
void addObjCClass(llvm::Constant *addr, bool nonlazy);
10841085
void addObjCClassStub(llvm::Constant *addr);
10851086
void addProtocolConformance(ConformanceDescription &&conformance);
@@ -1198,6 +1199,8 @@ class IRGenModule {
11981199
/// Metadata nodes for autolinking info.
11991200
SmallVector<LinkLibrary, 32> AutolinkEntries;
12001201

1202+
// List of ro_data_t referenced from generic class patterns.
1203+
SmallVector<llvm::WeakTrackingVH, 4> GenericRODatas;
12011204
/// List of Objective-C classes, bitcast to i8*.
12021205
SmallVector<llvm::WeakTrackingVH, 4> ObjCClasses;
12031206
/// List of Objective-C classes that require nonlazy realization, bitcast to
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %target-swift-frontend -enable-emit-generic-class-ro_t-list -S %s -o - | %FileCheck %s
2+
// REQUIRES: objc_interop
3+
// REQUIRES: CPU=x86_64 || CPU=arm64
4+
// REQUIRES: OS=macosx
5+
6+
// CHECK: ___unnamed_1:
7+
// CHECK: .quad _OBJC_METACLASS_$__TtCs12_SwiftObject
8+
// CHECK: .quad 0
9+
// CHECK: .quad __objc_empty_cache
10+
// CHECK: .quad 0
11+
// CHECK: .quad 0
12+
// Start of rodata_t
13+
// CHECK: .long 128
14+
// CHECK: .long 16
15+
// CHECK: .long 16
16+
// CHECK: .long 0
17+
// CHECK: .quad 0
18+
// CHECK: .quad 0
19+
// CHECK: .quad __INSTANCE_METHODS__TtC25generic_class_rodata_list9Something
20+
// CHECK: .quad 0
21+
// CHECK: .quad 0
22+
// CHECK: .quad 0
23+
// CHECK: .quad 0
24+
// Start of rodata_t
25+
// CHECK: .long 129
26+
// CHECK: .long 40
27+
// CHECK: .long 40
28+
// CHECK: .long 0
29+
// CHECK: .quad 0
30+
// CHECK: .quad 0
31+
// CHECK: .quad __CLASS_METHODS__TtC25generic_class_rodata_list9Somethin
32+
33+
// CHECK: .section __DATA,__swift_rodatas
34+
// CHECK: .p2align 3
35+
// CHECK:_generic_ro_datas:
36+
// CHECK: .quad ___unnamed_1+40
37+
// CHECK: .quad ___unnamed_1+112
38+
39+
import Foundation
40+
41+
public class Something<T> {
42+
@objc
43+
public func myMethod() { print("hello") }
44+
@objc
45+
public static func myStaticMethod() { print("static") }
46+
}

0 commit comments

Comments
 (0)