Skip to content

Commit f0d5b4c

Browse files
Merge pull request swiftlang#73678 from augusto2112/keep-for-deb-def-6
Fix functions not being kept for debugger
2 parents 5ccf00a + c5ea0c3 commit f0d5b4c

13 files changed

+111
-29
lines changed

include/swift/AST/SILOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,10 @@ class SILOptions {
298298
/// The format used for serializing remarks (default: YAML)
299299
llvm::remarks::Format OptRecordFormat = llvm::remarks::Format::YAML;
300300

301+
/// Are there any options that indicate that functions should not be preserved
302+
/// for the debugger?
303+
bool ShouldFunctionsBePreservedToDebugger = true;
304+
301305
SILOptions() {}
302306

303307
/// Return a hash code of any components from these options that should

include/swift/SIL/SILGlobalVariable.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ class SILGlobalVariable
147147
/// might be referenced from outside the current compilation unit.
148148
bool isPossiblyUsedExternally() const;
149149

150+
/// Returns true if this global variable should be preserved so it can
151+
/// potentially be inspected by the debugger.
152+
bool shouldBePreservedForDebugger() const;
153+
150154
/// Get this global variable's serialized attribute.
151155
IsSerialized_t isSerialized() const;
152156
void setSerialized(IsSerialized_t isSerialized);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,6 +2248,22 @@ void parseExclusivityEnforcementOptions(const llvm::opt::Arg *A,
22482248
}
22492249
}
22502250

2251+
static std::optional<IRGenLLVMLTOKind>
2252+
ParseLLVMLTOKind(const ArgList &Args, DiagnosticEngine &Diags) {
2253+
std::optional<IRGenLLVMLTOKind> LLVMLTOKind;
2254+
if (const Arg *A = Args.getLastArg(options::OPT_lto)) {
2255+
LLVMLTOKind =
2256+
llvm::StringSwitch<std::optional<IRGenLLVMLTOKind>>(A->getValue())
2257+
.Case("llvm-thin", IRGenLLVMLTOKind::Thin)
2258+
.Case("llvm-full", IRGenLLVMLTOKind::Full)
2259+
.Default(std::nullopt);
2260+
if (!LLVMLTOKind)
2261+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
2262+
A->getAsString(Args), A->getValue());
2263+
}
2264+
return LLVMLTOKind;
2265+
}
2266+
22512267
static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
22522268
IRGenOptions &IRGenOpts, const FrontendOptions &FEOpts,
22532269
const TypeCheckerOptions &TCOpts,
@@ -2635,6 +2651,16 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
26352651

26362652
Opts.NoAllocations = Args.hasArg(OPT_no_allocations);
26372653

2654+
// If these optimizations are enabled never preserve functions for the
2655+
// debugger.
2656+
Opts.ShouldFunctionsBePreservedToDebugger =
2657+
!Args.hasArg(OPT_enable_llvm_wme);
2658+
Opts.ShouldFunctionsBePreservedToDebugger &=
2659+
!Args.hasArg(OPT_enable_llvm_vfe);
2660+
if (auto LTOKind = ParseLLVMLTOKind(Args, Diags))
2661+
Opts.ShouldFunctionsBePreservedToDebugger &=
2662+
LTOKind.value() == IRGenLLVMLTOKind::None;
2663+
26382664
return false;
26392665
}
26402666

@@ -2981,18 +3007,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
29813007
}
29823008
}
29833009

2984-
if (const Arg *A = Args.getLastArg(options::OPT_lto)) {
2985-
auto LLVMLTOKind =
2986-
llvm::StringSwitch<std::optional<IRGenLLVMLTOKind>>(A->getValue())
2987-
.Case("llvm-thin", IRGenLLVMLTOKind::Thin)
2988-
.Case("llvm-full", IRGenLLVMLTOKind::Full)
2989-
.Default(std::nullopt);
2990-
if (LLVMLTOKind)
2991-
Opts.LLVMLTOKind = LLVMLTOKind.value();
2992-
else
2993-
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
2994-
A->getAsString(Args), A->getValue());
2995-
}
3010+
if (auto LTOKind = ParseLLVMLTOKind(Args, Diags))
3011+
Opts.LLVMLTOKind = LTOKind.value();
29963012

29973013
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_coverage_EQ)) {
29983014
Opts.SanitizeCoverage =

lib/IRGen/GenDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2826,6 +2826,8 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
28262826
// Mark as llvm.used if @_used, set section if @_section
28272827
if (var->markedAsUsed())
28282828
addUsedGlobal(gvar);
2829+
else if (var->shouldBePreservedForDebugger() && forDefinition)
2830+
addUsedGlobal(gvar);
28292831
if (auto *sectionAttr = var->getSectionAttr())
28302832
gvar->setSection(sectionAttr->Name);
28312833
}
@@ -3695,7 +3697,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
36953697

36963698
// Also mark as llvm.used any functions that should be kept for the debugger.
36973699
// Only definitions should be kept.
3698-
if (f->shouldBePreservedForDebugger() && !fn->isDeclaration())
3700+
if (f->shouldBePreservedForDebugger() && forDefinition)
36993701
addUsedGlobal(fn);
37003702

37013703
// If `hasCReferences` is true, then the function is either marked with

lib/SIL/IR/SILFunction.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,12 @@ bool SILFunction::shouldBePreservedForDebugger() const {
942942
if (getEffectiveOptimizationMode() != OptimizationMode::NoOptimization)
943943
return false;
944944

945+
if (!getModule().getOptions().ShouldFunctionsBePreservedToDebugger)
946+
return false;
947+
948+
if (getModule().getASTContext().LangOpts.hasFeature(Feature::Embedded))
949+
return false;
950+
945951
if (isAvailableExternally())
946952
return false;
947953

lib/SIL/IR/SILGlobalVariable.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,20 @@ SILGlobalVariable::~SILGlobalVariable() {
6161
}
6262

6363
bool SILGlobalVariable::isPossiblyUsedExternally() const {
64+
if (shouldBePreservedForDebugger())
65+
return true;
66+
6467
SILLinkage linkage = getLinkage();
6568
return swift::isPossiblyUsedExternally(linkage, getModule().isWholeModule());
6669
}
6770

71+
bool SILGlobalVariable::shouldBePreservedForDebugger() const {
72+
if (getModule().getOptions().OptMode != OptimizationMode::NoOptimization)
73+
return false;
74+
// Keep any language-level global variables for the debugger.
75+
return VDecl != nullptr;
76+
}
77+
6878
/// Get this global variable's fragile attribute.
6979
IsSerialized_t SILGlobalVariable::isSerialized() const {
7080
return Serialized ? IsSerialized : IsNotSerialized;

test/IRGen/conditional-dead-strip-exec.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
@inline(never) func func1_used() { print("func1_used") }
2626

2727
// (2) unused
28+
@_semantics("no.preserve.debugger")
2829
@inline(never) func func2_dead() { print("func2_dead") }
2930

3031
// (3) completely unused
@@ -35,6 +36,7 @@ protocol TheProtocol { }
3536

3637
// (5) unused class
3738
class MyClass: TheProtocol {
39+
@_semantics("no.preserve.debugger")
3840
func unused_method() {}
3941
}
4042

test/IRGen/objc_pointers.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import Foundation
2020
}
2121

2222
// CHECK-LABEL: s13objc_pointers14returnNSObject3objSo0D0CAE_tF
23+
@_semantics("no.preserve.debugger")
2324
func returnNSObject(obj: NSObject) -> NSObject {
2425
// CHECK-NOT: return
2526
// CHECK: @llvm.objc.retain

test/IRGen/preserve_for_debugger.swift

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
// RUN: %target-swiftc_driver %s -g -Onone -emit-ir | %FileCheck %s
22

3+
4+
// Check that unused globals are preserved at Onone.
5+
6+
private let number = 42
7+
// CHECK: distinct !DIGlobalVariable(name: "number",
8+
39
// Check that unused functions are preserved at Onone.
410
func unused() {
511
}
12+
// CHECK: !DISubprogram(name: "unused", linkageName: "$s21preserve_for_debugger6unusedyyF"
613

714
// Property wrappers generate transparent getters, which we would like to check still exist at Onone.
815
@propertyWrapper
@@ -24,5 +31,36 @@ public class User {
2431
let c = User()
2532
c.f()
2633

27-
// CHECK: !DISubprogram(name: "unused", linkageName: "$s21preserve_for_debugger6unusedyyF"
2834
// CHECK: !DISubprogram(name: "number.get"
35+
36+
protocol Foo {}
37+
38+
@propertyWrapper
39+
struct Bar<ObjectType: Foo> {
40+
var storage: ObjectType
41+
42+
public init(wrappedValue: ObjectType) {
43+
storage = wrappedValue
44+
}
45+
46+
public var wrappedValue: ObjectType {
47+
return storage
48+
}
49+
50+
}
51+
52+
class Baz: Foo {
53+
let x = 42
54+
}
55+
56+
struct Qux {
57+
@Bar(wrappedValue: Baz()) private var baz: Baz
58+
59+
func f() {
60+
print(self.baz) // break here
61+
}
62+
}
63+
let qux = Qux()
64+
qux.f()
65+
66+
// CHECK: !DISubprogram(name: "baz.get"

test/IRGen/section.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
@_section("__DATA,__mysection") public var g3: Bool = true
1010
@_section("__DATA,__mysection") var g4: UnsafeMutablePointer<Int>? = nil
1111
@_section("__DATA,__mysection") var g5: UnsafeMutablePointer<Int>? = UnsafeMutablePointer(bitPattern: 0x42424242)
12-
@_section("__TEXT,__mysection") func foo() {}
12+
@_section("__TEXT,__mysection") @_used func foo() {}
1313

1414
struct MyStruct {
1515
@_section("__DATA,__mysection") static var static0: Int = 1
16-
@_section("__TEXT,__mysection") func foo() {}
16+
@_section("__TEXT,__mysection") @_used func foo() {}
1717
}
1818

1919
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue var g0: Int { get set }
@@ -22,10 +22,10 @@ struct MyStruct {
2222
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue public var g3: Bool { get set }
2323
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue var g4: UnsafeMutablePointer<Int>? { get set }
2424
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue var g5: UnsafeMutablePointer<Int>? { get set }
25-
// SIL: @_section("__TEXT,__mysection") func foo()
25+
// SIL: @_section("__TEXT,__mysection") @_used func foo()
2626
// SIL: struct MyStruct {
2727
// SIL: @_section("__DATA,__mysection") @_hasStorage @_hasInitialValue static var static0: Int { get set }
28-
// SIL: @_section("__TEXT,__mysection") func foo()
28+
// SIL: @_section("__TEXT,__mysection") @_used func foo()
2929

3030
// SIL: sil private [global_init_once_fn] [perf_constraint] @$s7section2g0_WZ : $@convention(c)
3131
// SIL: sil hidden [global_init] @$s7section2g0Sivau : $@convention(thin)
@@ -39,10 +39,10 @@ struct MyStruct {
3939
// SIL: sil hidden [global_init] @$s7section2g4SpySiGSgvau : $@convention(thin)
4040
// SIL: sil private [global_init_once_fn] [perf_constraint] @$s7section2g5_WZ : $@convention(c)
4141
// SIL: sil hidden [global_init] @$s7section2g5SpySiGSgvau : $@convention(thin)
42-
// SIL: sil hidden [section "__TEXT,__mysection"] @$s7section3fooyyF : $@convention(thin)
42+
// SIL: sil hidden [used] [section "__TEXT,__mysection"] @$s7section3fooyyF : $@convention(thin)
4343
// SIL: sil private [global_init_once_fn] [perf_constraint] @$s7section8MyStructV7static0_WZ : $@convention(c)
4444
// SIL: sil hidden [global_init] @$s7section8MyStructV7static0Sivau : $@convention(thin)
45-
// SIL: sil hidden [section "__TEXT,__mysection"] @$s7section8MyStructV3fooyyF : $@convention(method)
45+
// SIL: sil hidden [used] [section "__TEXT,__mysection"] @$s7section8MyStructV3fooyyF : $@convention(method)
4646

4747
// IR: @"$s7section2g0Sivp" = hidden global %TSi <{ {{(i64|i32)}} 1 }>, section "__DATA,__mysection"
4848
// IR: @"$s7section2g1Si_Sitvp" = hidden global <{ %TSi, %TSi }> <{ %TSi <{ {{(i64|i32)}} 42 }>, %TSi <{ {{(i64|i32)}} 43 }> }>, section "__DATA,__mysection"

0 commit comments

Comments
 (0)