Skip to content

Commit 184bb5f

Browse files
committed
Keep certain function that are potentially used in the debugger
Currently, when compiling with no optimizations on, we still delete functions that are sometimes used in the debugger. For example, users might want to call functions which are unused, or compiler generated setters/getters. rdar://101046198
1 parent 30e66ab commit 184bb5f

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,10 @@ class SILFunction
845845
/// current SILModule.
846846
bool isPossiblyUsedExternally() const;
847847

848+
/// Helper method which returns whether this function should be preserved so
849+
/// it can potentially be used in the debugger.
850+
bool shouldBePreservedForDebugger() const;
851+
848852
/// In addition to isPossiblyUsedExternally() it returns also true if this
849853
/// is a (private or internal) vtable method which can be referenced by
850854
/// vtables of derived classes outside the compilation unit.

lib/IRGen/GenDecl.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,12 +1252,6 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
12521252
if (f.getDynamicallyReplacedFunction())
12531253
return false;
12541254

1255-
// Needed by lldb to print global variables which are propagated by the
1256-
// mandatory GlobalOpt.
1257-
if (m.getOptions().OptMode == OptimizationMode::NoOptimization &&
1258-
f.isGlobalInit())
1259-
return false;
1260-
12611255
return true;
12621256
}
12631257

@@ -3554,9 +3548,15 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
35543548
// Mark as llvm.used if @_used, set section if @_section
35553549
if (f->markedAsUsed())
35563550
addUsedGlobal(fn);
3551+
35573552
if (!f->section().empty())
35583553
fn->setSection(f->section());
35593554

3555+
// Also mark as llvm.used any functions that should be kept for the debugger.
3556+
// Only definitions should be kept.
3557+
if (f->shouldBePreservedForDebugger() && !fn->isDeclaration())
3558+
addUsedGlobal(fn);
3559+
35603560
// If `hasCReferences` is true, then the function is either marked with
35613561
// @_silgen_name OR @_cdecl. If it is the latter, it must have a definition
35623562
// associated with it. The combination of the two allows us to identify the

lib/SIL/IR/SILFunction.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,9 @@ SILFunction::isPossiblyUsedExternally() const {
862862
if (markedAsUsed())
863863
return true;
864864

865+
if (shouldBePreservedForDebugger())
866+
return true;
867+
865868
// Declaration marked as `@_alwaysEmitIntoClient` that
866869
// returns opaque result type with availability conditions
867870
// has to be kept alive to emit opaque type metadata descriptor.
@@ -872,6 +875,35 @@ SILFunction::isPossiblyUsedExternally() const {
872875
return swift::isPossiblyUsedExternally(linkage, getModule().isWholeModule());
873876
}
874877

878+
bool SILFunction::shouldBePreservedForDebugger() const {
879+
// Only preserve for the debugger at Onone.
880+
if (getEffectiveOptimizationMode() != OptimizationMode::NoOptimization)
881+
return false;
882+
883+
// Only keep functions defined in this module.
884+
if (!isDefinition())
885+
return false;
886+
887+
// Needed by lldb to print global variables which are propagated by the
888+
// mandatory GlobalOpt.
889+
if (isGlobalInit())
890+
return true;
891+
892+
// Preserve any user-written functions.
893+
if (auto declContext = getDeclContext())
894+
if (auto decl = declContext->getAsDecl())
895+
if (!decl->isImplicit())
896+
return true;
897+
898+
// Keep any setters/getters, even compiler generated ones.
899+
if (auto *accessorDecl =
900+
llvm::dyn_cast_or_null<swift::AccessorDecl>(getDeclContext()))
901+
if (accessorDecl->isGetterOrSetter())
902+
return true;
903+
904+
return false;
905+
}
906+
875907
bool SILFunction::isExternallyUsedSymbol() const {
876908
return swift::isPossiblyUsedExternally(getEffectiveSymbolLinkage(),
877909
getModule().isWholeModule());
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swiftc_driver %s -g -Onone -emit-ir | %FileCheck %s
2+
3+
// Check that unused functions are preserved at Onone.
4+
func unused() {
5+
}
6+
7+
// Property wrappers generate transparent getters, which we would like to check still exist at Onone.
8+
@propertyWrapper
9+
struct IntWrapper {
10+
private var storage = 42
11+
var wrappedValue: Int {
12+
return storage
13+
}
14+
}
15+
16+
public class User {
17+
@IntWrapper private var number: Int
18+
19+
func f() {
20+
// Force the generation of the getter
21+
_ = self.number
22+
}
23+
}
24+
let c = User()
25+
c.f()
26+
27+
// CHECK: !DISubprogram(name: "unused", linkageName: "$s21preserve_for_debugger6unusedyyF"
28+
// CHECK: !DISubprogram(name: "number.get"

0 commit comments

Comments
 (0)