Skip to content

Commit 5298450

Browse files
committed
Fix functions not being kept for debugger
At Onone, many types of functions (anything user written, compiler generated setters and getters, etc), should be kept in the final binary so they're accessible by the debugger. rdar://126763340
1 parent dae1e84 commit 5298450

11 files changed

+85
-17
lines changed

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/IRGen/GenDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2841,6 +2841,8 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
28412841
// Mark as llvm.used if @_used, set section if @_section
28422842
if (var->markedAsUsed())
28432843
addUsedGlobal(gvar);
2844+
else if (var->shouldBePreservedForDebugger() && forDefinition)
2845+
addUsedGlobal(gvar);
28442846
if (auto *sectionAttr = var->getSectionAttr())
28452847
gvar->setSection(sectionAttr->Name);
28462848
}
@@ -3710,7 +3712,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
37103712

37113713
// Also mark as llvm.used any functions that should be kept for the debugger.
37123714
// Only definitions should be kept.
3713-
if (f->shouldBePreservedForDebugger() && !fn->isDeclaration())
3715+
if (f->shouldBePreservedForDebugger() && forDefinition)
37143716
addUsedGlobal(fn);
37153717

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

lib/SIL/IR/SILFunction.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/AST/Availability.h"
1717
#include "swift/AST/Expr.h"
1818
#include "swift/AST/GenericEnvironment.h"
19+
#include "swift/AST/IRGenOptions.h"
1920
#include "swift/AST/Module.h"
2021
#include "swift/AST/Stmt.h"
2122
#include "swift/Basic/OptimizationMode.h"
@@ -959,6 +960,17 @@ bool SILFunction::shouldBePreservedForDebugger() const {
959960
if (getEffectiveOptimizationMode() != OptimizationMode::NoOptimization)
960961
return false;
961962

963+
if (getModule().getASTContext().LangOpts.hasFeature(Feature::Embedded))
964+
return false;
965+
966+
if (const IRGenOptions *options = getModule().getIRGenOptionsOrNull()) {
967+
if (options->WitnessMethodElimination ||
968+
options->VirtualFunctionElimination ||
969+
options->LLVMLTOKind != IRGenLLVMLTOKind::None) {
970+
return false;
971+
}
972+
}
973+
962974
if (isAvailableExternally())
963975
return false;
964976

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"

test/IRGen/section_asm.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,22 @@
2727
// CHECK-NOT: .section
2828
// CHECK: $s7section8MyStructV7static0SivpZ:
2929

30-
// CHECKELF: .section{{.*}}"__TEXT,__mysection","ax"
30+
// CHECKELF: .section{{.*}}"__TEXT,__mysection","axR"
3131
// CHECKELF-NOT: .section
3232
// CHECKELF: $s7section3fooyyF:
3333

34-
// CHECKELF: .section{{.*}}"__TEXT,__mysection","ax"
34+
// CHECKELF: .section{{.*}}"__TEXT,__mysection","axR"
3535
// CHECKELF-NOT: .section
3636
// CHECKELF: $s7section8MyStructV3fooyyF:
3737

38-
// CHECKELF: .section{{.*}}"__DATA,__mysection","aw"
38+
// CHECKELF: .section{{.*}}"__DATA,__mysection","awR"
3939
// CHECKELF-NOT: .section
4040
// CHECKELF: $s7section2g0Sivp:
41-
// CHECKELF-NOT: .section
4241
// CHECKELF: $s7section2g1Si_Sitvp:
43-
// CHECKELF-NOT: .section
4442
// CHECKELF: $s7section2g2Sbvp:
4543
// CHECKELF: .section{{.*}}"__DATA,__mysection","awR"
4644
// CHECKELF: $s7section2g3Sbvp:
47-
// CHECKELF: .section{{.*}}"__DATA,__mysection","aw"
45+
// CHECKELF: .section{{.*}}"__DATA,__mysection","awR"
4846
// CHECKELF: $s7section2g4SpySiGSgvp:
49-
// CHECKELF-NOT: .section
5047
// CHECKELF: $s7section2g5SpySiGSgvp:
51-
// CHECKELF-NOT: .section
5248
// CHECKELF: $s7section8MyStructV7static0SivpZ:

test/embedded/accessor-unavailable.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@ struct Foo {
1515
}
1616
}
1717

18+
let foo = Foo()
19+
let _ = foo[5]
20+
1821
// CHECK: $s4main3FooVyS2icig
1922
// CHECK-NOT: $s4main3FooVyS2icis

0 commit comments

Comments
 (0)