Skip to content

Commit ee7e048

Browse files
authored
Add a -reflection-metadata-for-debugger-only flag that emits reflection metadata but does not link them from runtime data structures (#40853)
1 parent 6c23d92 commit ee7e048

File tree

6 files changed

+76
-12
lines changed

6 files changed

+76
-12
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ enum class SwiftAsyncFramePointerKind : unsigned {
8787
Never, // Don't emit Swift async extended frame info.
8888
};
8989

90+
enum class ReflectionMetadataMode : unsigned {
91+
None, ///< Don't emit reflection metadata at all.
92+
DebuggerOnly, ///< Emit reflection metadata for the debugger, don't link them
93+
/// into runtime metadata and don't force them to stay alive.
94+
Runtime, ///< Make reflection metadata fully available.
95+
};
96+
9097
using clang::PointerAuthSchema;
9198

9299
struct PointerAuthOptions : clang::PointerAuthOptions {
@@ -295,7 +302,7 @@ class IRGenOptions {
295302
unsigned ValueNames : 1;
296303

297304
/// Emit nominal type field metadata.
298-
unsigned EnableReflectionMetadata : 1;
305+
ReflectionMetadataMode ReflectionMetadata : 2;
299306

300307
/// Emit names of struct stored properties and enum cases.
301308
unsigned EnableReflectionNames : 1;
@@ -423,7 +430,7 @@ class IRGenOptions {
423430
LLVMLTOKind(IRGenLLVMLTOKind::None),
424431
SwiftAsyncFramePointer(SwiftAsyncFramePointerKind::Auto),
425432
HasValueNamesSetting(false),
426-
ValueNames(false), EnableReflectionMetadata(true),
433+
ValueNames(false), ReflectionMetadata(ReflectionMetadataMode::Runtime),
427434
EnableReflectionNames(true), EnableAnonymousContextMangledNames(false),
428435
ForcePublicLinkage(false), LazyInitializeClassMetadata(false),
429436
LazyInitializeProtocolConformances(false),

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,9 @@ def enable_anonymous_context_mangled_names :
455455
def disable_reflection_metadata : Flag<["-"], "disable-reflection-metadata">,
456456
HelpText<"Disable emission of reflection metadata for nominal types">;
457457

458+
def reflection_metadata_for_debugger_only : Flag<["-"], "reflection-metadata-for-debugger-only">,
459+
HelpText<"Emit reflection metadata for debugger only, don't make them available at runtime">;
460+
458461
def disable_reflection_names : Flag<["-"], "disable-reflection-names">,
459462
HelpText<"Disable emission of names of stored properties and enum cases in"
460463
"reflection metadata">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2043,10 +2043,15 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
20432043
}
20442044

20452045
if (Args.hasArg(OPT_disable_reflection_metadata)) {
2046-
Opts.EnableReflectionMetadata = false;
2046+
Opts.ReflectionMetadata = ReflectionMetadataMode::None;
20472047
Opts.EnableReflectionNames = false;
20482048
}
20492049

2050+
if (Args.hasArg(OPT_reflection_metadata_for_debugger_only)) {
2051+
Opts.ReflectionMetadata = ReflectionMetadataMode::DebuggerOnly;
2052+
Opts.EnableReflectionNames = true;
2053+
}
2054+
20502055
if (Args.hasArg(OPT_enable_anonymous_context_mangled_names))
20512056
Opts.EnableAnonymousContextMangledNames = true;
20522057

lib/IRGen/GenMeta.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,11 +1488,12 @@ namespace {
14881488
void maybeAddResilientSuperclass() { }
14891489

14901490
void addReflectionFieldDescriptor() {
1491-
if (!IGM.IRGen.Opts.EnableReflectionMetadata) {
1491+
if (IGM.IRGen.Opts.ReflectionMetadata !=
1492+
ReflectionMetadataMode::Runtime) {
14921493
B.addInt32(0);
14931494
return;
14941495
}
1495-
1496+
14961497
IGM.IRGen.noteUseOfFieldDescriptor(getType());
14971498

14981499
B.addRelativeAddress(IGM.getAddrOfReflectionFieldDescriptor(
@@ -1566,7 +1567,8 @@ namespace {
15661567
void maybeAddResilientSuperclass() { }
15671568

15681569
void addReflectionFieldDescriptor() {
1569-
if (!IGM.IRGen.Opts.EnableReflectionMetadata) {
1570+
if (IGM.IRGen.Opts.ReflectionMetadata !=
1571+
ReflectionMetadataMode::Runtime) {
15701572
B.addInt32(0);
15711573
return;
15721574
}
@@ -1723,7 +1725,8 @@ namespace {
17231725
void addReflectionFieldDescriptor() {
17241726
// Classes are always reflectable, unless reflection is disabled or this
17251727
// is a foreign class.
1726-
if (!IGM.IRGen.Opts.EnableReflectionMetadata ||
1728+
if ((IGM.IRGen.Opts.ReflectionMetadata !=
1729+
ReflectionMetadataMode::Runtime) ||
17271730
getType()->isForeign()) {
17281731
B.addInt32(0);
17291732
return;

lib/IRGen/GenReflection.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,12 @@ class ReflectionMetadataBuilder {
623623

624624
var->setSection(section);
625625

626-
IGM.addUsedGlobal(var);
626+
// Only mark the reflection record as used when emitting for the runtime.
627+
// In ReflectionMetadataMode::DebuggerOnly mode we want to allow the linker
628+
// to remove/dead-strip these.
629+
if (IGM.IRGen.Opts.ReflectionMetadata == ReflectionMetadataMode::Runtime) {
630+
IGM.addUsedGlobal(var);
631+
}
627632

628633
disableAddressSanitizer(IGM, var);
629634

@@ -1335,7 +1340,7 @@ llvm::Constant *IRGenModule::getAddrOfFieldName(StringRef Name) {
13351340
llvm::Constant *
13361341
IRGenModule::getAddrOfBoxDescriptor(SILType BoxedType,
13371342
CanGenericSignature genericSig) {
1338-
if (!IRGen.Opts.EnableReflectionMetadata)
1343+
if (IRGen.Opts.ReflectionMetadata != ReflectionMetadataMode::Runtime)
13391344
return llvm::Constant::getNullValue(CaptureDescriptorPtrTy);
13401345

13411346
BoxDescriptorBuilder builder(*this, BoxedType, genericSig);
@@ -1350,7 +1355,7 @@ IRGenModule::getAddrOfCaptureDescriptor(SILFunction &Caller,
13501355
CanSILFunctionType SubstCalleeType,
13511356
SubstitutionMap Subs,
13521357
const HeapLayout &Layout) {
1353-
if (!IRGen.Opts.EnableReflectionMetadata)
1358+
if (IRGen.Opts.ReflectionMetadata != ReflectionMetadataMode::Runtime)
13541359
return llvm::Constant::getNullValue(CaptureDescriptorPtrTy);
13551360

13561361
if (CaptureDescriptorBuilder::hasOpenedExistential(OrigCalleeType, Layout))
@@ -1369,7 +1374,7 @@ emitAssociatedTypeMetadataRecord(const RootProtocolConformance *conformance) {
13691374
if (!normalConf)
13701375
return;
13711376

1372-
if (!IRGen.Opts.EnableReflectionMetadata)
1377+
if (IRGen.Opts.ReflectionMetadata != ReflectionMetadataMode::Runtime)
13731378
return;
13741379

13751380
SmallVector<std::pair<StringRef, CanType>, 2> AssociatedTypes;
@@ -1428,7 +1433,7 @@ void IRGenerator::emitBuiltinReflectionMetadata() {
14281433
}
14291434

14301435
void IRGenModule::emitFieldDescriptor(const NominalTypeDecl *D) {
1431-
if (!IRGen.Opts.EnableReflectionMetadata)
1436+
if (IRGen.Opts.ReflectionMetadata == ReflectionMetadataMode::None)
14321437
return;
14331438

14341439
auto T = D->getDeclaredTypeInContext()->getCanonicalType();
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -module-name main %s -emit-ir | %FileCheck %s --check-prefix=CHECK-REFL
3+
// RUN: %target-swift-frontend -module-name main %s -emit-ir -reflection-metadata-for-debugger-only | %FileCheck %s --check-prefix=CHECK-REFLDEBUG
4+
// RUN: %target-swift-frontend -module-name main %s -emit-ir -disable-reflection-metadata | %FileCheck %s --check-prefix=CHECK-NOREFL
5+
6+
public class Generic<T> {
7+
public func m1(t: T) -> T { return t }
8+
public func m2(t: T) -> T { return t }
9+
}
10+
11+
protocol MyProtocol {
12+
associatedtype T
13+
func foo() -> T
14+
}
15+
16+
public struct MyStruct<T>: MyProtocol {
17+
func foo() -> T { fatalError() }
18+
}
19+
20+
// CHECK-REFL: @"$s4main8MyStructVyxGAA0B8ProtocolAAMA"
21+
// CHECK-REFL: @"$s4main7GenericCMn" = {{.*}} @"$s4main7GenericCMF" {{.*}}
22+
// CHECK-REFL: @"$s4main7GenericCMF" =
23+
// CHECK-REFL: @"$s4main10MyProtocol_pMF" =
24+
// CHECK-REFL: @"$s4main8MyStructVMn" = {{.*}} @"$s4main8MyStructVMF" {{.*}}
25+
// CHECK-REFL: @"$s4main8MyStructVMF" =
26+
27+
// CHECK-REFLDEBUG-NOT: @"$s4main8MyStructVyxGAA0B8ProtocolAAMA"
28+
// CHECK-REFLDEBUG: @"$s4main7GenericCMn" =
29+
// CHECK-REFLDEBUG-NOT: @"$s4main7GenericCMF"
30+
// CHECK-REFLDEBUG-SAME: , align 4
31+
// CHECK-REFLDEBUG: @"$s4main7GenericCMF" =
32+
// CHECK-REFLDEBUG: @"$s4main10MyProtocol_pMF" =
33+
// CHECK-REFLDEBUG: @"$s4main8MyStructVMn" =
34+
// CHECK-REFLDEBUG-NOT: @"$s4main8MyStructVMF"
35+
// CHECK-REFLDEBUG-SAME: , align 4
36+
// CHECK-REFLDEBUG: @"$s4main8MyStructVMF" =
37+
38+
// CHECK-NOREFL-NOT: @"$s4main8MyStructVyxGAA0B8ProtocolAAMA"
39+
// CHECK-NOREFL-NOT: @"$s4main10MyProtocol_pMF"
40+
// CHECK-NOREFL-NOT: @"$s4main7GenericCMF"
41+
// CHECK-NOREFL-NOT: @"$s4main8MyStructVMF"

0 commit comments

Comments
 (0)