Skip to content

Commit

Permalink
Add a -reflection-metadata-for-debugger-only flag that emits reflecti…
Browse files Browse the repository at this point in the history
…on metadata but does not link them from runtime data structures (swiftlang#40853)
  • Loading branch information
kubamracek authored Feb 3, 2022
1 parent 6c23d92 commit ee7e048
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 12 deletions.
11 changes: 9 additions & 2 deletions include/swift/AST/IRGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ enum class SwiftAsyncFramePointerKind : unsigned {
Never, // Don't emit Swift async extended frame info.
};

enum class ReflectionMetadataMode : unsigned {
None, ///< Don't emit reflection metadata at all.
DebuggerOnly, ///< Emit reflection metadata for the debugger, don't link them
/// into runtime metadata and don't force them to stay alive.
Runtime, ///< Make reflection metadata fully available.
};

using clang::PointerAuthSchema;

struct PointerAuthOptions : clang::PointerAuthOptions {
Expand Down Expand Up @@ -295,7 +302,7 @@ class IRGenOptions {
unsigned ValueNames : 1;

/// Emit nominal type field metadata.
unsigned EnableReflectionMetadata : 1;
ReflectionMetadataMode ReflectionMetadata : 2;

/// Emit names of struct stored properties and enum cases.
unsigned EnableReflectionNames : 1;
Expand Down Expand Up @@ -423,7 +430,7 @@ class IRGenOptions {
LLVMLTOKind(IRGenLLVMLTOKind::None),
SwiftAsyncFramePointer(SwiftAsyncFramePointerKind::Auto),
HasValueNamesSetting(false),
ValueNames(false), EnableReflectionMetadata(true),
ValueNames(false), ReflectionMetadata(ReflectionMetadataMode::Runtime),
EnableReflectionNames(true), EnableAnonymousContextMangledNames(false),
ForcePublicLinkage(false), LazyInitializeClassMetadata(false),
LazyInitializeProtocolConformances(false),
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,9 @@ def enable_anonymous_context_mangled_names :
def disable_reflection_metadata : Flag<["-"], "disable-reflection-metadata">,
HelpText<"Disable emission of reflection metadata for nominal types">;

def reflection_metadata_for_debugger_only : Flag<["-"], "reflection-metadata-for-debugger-only">,
HelpText<"Emit reflection metadata for debugger only, don't make them available at runtime">;

def disable_reflection_names : Flag<["-"], "disable-reflection-names">,
HelpText<"Disable emission of names of stored properties and enum cases in"
"reflection metadata">;
Expand Down
7 changes: 6 additions & 1 deletion lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2043,10 +2043,15 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
}

if (Args.hasArg(OPT_disable_reflection_metadata)) {
Opts.EnableReflectionMetadata = false;
Opts.ReflectionMetadata = ReflectionMetadataMode::None;
Opts.EnableReflectionNames = false;
}

if (Args.hasArg(OPT_reflection_metadata_for_debugger_only)) {
Opts.ReflectionMetadata = ReflectionMetadataMode::DebuggerOnly;
Opts.EnableReflectionNames = true;
}

if (Args.hasArg(OPT_enable_anonymous_context_mangled_names))
Opts.EnableAnonymousContextMangledNames = true;

Expand Down
11 changes: 7 additions & 4 deletions lib/IRGen/GenMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1488,11 +1488,12 @@ namespace {
void maybeAddResilientSuperclass() { }

void addReflectionFieldDescriptor() {
if (!IGM.IRGen.Opts.EnableReflectionMetadata) {
if (IGM.IRGen.Opts.ReflectionMetadata !=
ReflectionMetadataMode::Runtime) {
B.addInt32(0);
return;
}

IGM.IRGen.noteUseOfFieldDescriptor(getType());

B.addRelativeAddress(IGM.getAddrOfReflectionFieldDescriptor(
Expand Down Expand Up @@ -1566,7 +1567,8 @@ namespace {
void maybeAddResilientSuperclass() { }

void addReflectionFieldDescriptor() {
if (!IGM.IRGen.Opts.EnableReflectionMetadata) {
if (IGM.IRGen.Opts.ReflectionMetadata !=
ReflectionMetadataMode::Runtime) {
B.addInt32(0);
return;
}
Expand Down Expand Up @@ -1723,7 +1725,8 @@ namespace {
void addReflectionFieldDescriptor() {
// Classes are always reflectable, unless reflection is disabled or this
// is a foreign class.
if (!IGM.IRGen.Opts.EnableReflectionMetadata ||
if ((IGM.IRGen.Opts.ReflectionMetadata !=
ReflectionMetadataMode::Runtime) ||
getType()->isForeign()) {
B.addInt32(0);
return;
Expand Down
15 changes: 10 additions & 5 deletions lib/IRGen/GenReflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,12 @@ class ReflectionMetadataBuilder {

var->setSection(section);

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

disableAddressSanitizer(IGM, var);

Expand Down Expand Up @@ -1335,7 +1340,7 @@ llvm::Constant *IRGenModule::getAddrOfFieldName(StringRef Name) {
llvm::Constant *
IRGenModule::getAddrOfBoxDescriptor(SILType BoxedType,
CanGenericSignature genericSig) {
if (!IRGen.Opts.EnableReflectionMetadata)
if (IRGen.Opts.ReflectionMetadata != ReflectionMetadataMode::Runtime)
return llvm::Constant::getNullValue(CaptureDescriptorPtrTy);

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

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

if (!IRGen.Opts.EnableReflectionMetadata)
if (IRGen.Opts.ReflectionMetadata != ReflectionMetadataMode::Runtime)
return;

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

void IRGenModule::emitFieldDescriptor(const NominalTypeDecl *D) {
if (!IRGen.Opts.EnableReflectionMetadata)
if (IRGen.Opts.ReflectionMetadata == ReflectionMetadataMode::None)
return;

auto T = D->getDeclaredTypeInContext()->getCanonicalType();
Expand Down
41 changes: 41 additions & 0 deletions test/IRGen/reflection-metadata-for-debugger-only.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -module-name main %s -emit-ir | %FileCheck %s --check-prefix=CHECK-REFL
// RUN: %target-swift-frontend -module-name main %s -emit-ir -reflection-metadata-for-debugger-only | %FileCheck %s --check-prefix=CHECK-REFLDEBUG
// RUN: %target-swift-frontend -module-name main %s -emit-ir -disable-reflection-metadata | %FileCheck %s --check-prefix=CHECK-NOREFL

public class Generic<T> {
public func m1(t: T) -> T { return t }
public func m2(t: T) -> T { return t }
}

protocol MyProtocol {
associatedtype T
func foo() -> T
}

public struct MyStruct<T>: MyProtocol {
func foo() -> T { fatalError() }
}

// CHECK-REFL: @"$s4main8MyStructVyxGAA0B8ProtocolAAMA"
// CHECK-REFL: @"$s4main7GenericCMn" = {{.*}} @"$s4main7GenericCMF" {{.*}}
// CHECK-REFL: @"$s4main7GenericCMF" =
// CHECK-REFL: @"$s4main10MyProtocol_pMF" =
// CHECK-REFL: @"$s4main8MyStructVMn" = {{.*}} @"$s4main8MyStructVMF" {{.*}}
// CHECK-REFL: @"$s4main8MyStructVMF" =

// CHECK-REFLDEBUG-NOT: @"$s4main8MyStructVyxGAA0B8ProtocolAAMA"
// CHECK-REFLDEBUG: @"$s4main7GenericCMn" =
// CHECK-REFLDEBUG-NOT: @"$s4main7GenericCMF"
// CHECK-REFLDEBUG-SAME: , align 4
// CHECK-REFLDEBUG: @"$s4main7GenericCMF" =
// CHECK-REFLDEBUG: @"$s4main10MyProtocol_pMF" =
// CHECK-REFLDEBUG: @"$s4main8MyStructVMn" =
// CHECK-REFLDEBUG-NOT: @"$s4main8MyStructVMF"
// CHECK-REFLDEBUG-SAME: , align 4
// CHECK-REFLDEBUG: @"$s4main8MyStructVMF" =

// CHECK-NOREFL-NOT: @"$s4main8MyStructVyxGAA0B8ProtocolAAMA"
// CHECK-NOREFL-NOT: @"$s4main10MyProtocol_pMF"
// CHECK-NOREFL-NOT: @"$s4main7GenericCMF"
// CHECK-NOREFL-NOT: @"$s4main8MyStructVMF"

0 comments on commit ee7e048

Please sign in to comment.