Skip to content

Commit ae98212

Browse files
committed
Eagerly emit getters at Onone.
Force SILGen to also eagerly emit getters when compiling at Onone. The reason for this is that getters (even not user-written ones, generated by result builders) can, and are often called by users debugging swift programs, and should be available for that reason. rdar://133329303
1 parent a07caa8 commit ae98212

File tree

4 files changed

+43
-2
lines changed

4 files changed

+43
-2
lines changed

include/swift/SIL/SILDeclRef.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,10 @@ struct SILDeclRef {
576576
/// for e.g a lazy variable getter.
577577
bool hasUserWrittenCode() const;
578578

579+
/// Returns true if this is a function that should be emitted because it is
580+
/// accessible in the debugger.
581+
bool shouldBeEmittedForDebugger() const;
582+
579583
/// Return the scope in which the parent class of a method (i.e. class
580584
/// containing this declaration) can be subclassed, returning NotApplicable if
581585
/// this is not a method, there is no such class, or the class cannot be

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,39 @@ bool SILDeclRef::hasUserWrittenCode() const {
387387
llvm_unreachable("Unhandled case in switch!");
388388
}
389389

390+
bool SILDeclRef::shouldBeEmittedForDebugger() const {
391+
if (!isFunc())
392+
return false;
393+
394+
if (getASTContext().SILOpts.OptMode != OptimizationMode::NoOptimization)
395+
return false;;
396+
397+
if (!getASTContext().SILOpts.ShouldFunctionsBePreservedToDebugger)
398+
return false;
399+
400+
if (getASTContext().LangOpts.hasFeature(Feature::Embedded))
401+
return false;
402+
403+
ValueDecl *decl = getDecl();
404+
DeclAttributes &attrs = decl->getAttrs();
405+
if (attrs.hasSemanticsAttr("no.preserve.debugger"))
406+
return false;
407+
408+
if (getLinkage(ForDefinition) == SILLinkage::Shared)
409+
return false;
410+
411+
if (auto decl = getDecl())
412+
if (!decl->isImplicit())
413+
return true;
414+
415+
// Synthesized getters are still callable in the debugger.
416+
if (auto *accessor = dyn_cast_or_null<AccessorDecl>(getFuncDecl())) {
417+
return accessor->isSynthesized() && accessor->isGetterOrSetter();
418+
};
419+
420+
return false;
421+
}
422+
390423
namespace {
391424
enum class LinkageLimit {
392425
/// No limit.

lib/SILGen/SILGen.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,8 +1198,9 @@ void SILGenModule::emitOrDelayFunction(SILDeclRef constant) {
11981198
auto emitAfter = lastEmittedFunction;
11991199

12001200
// Implicit decls may be delayed if they can't be used externally.
1201-
auto linkage = constant.getLinkage(ForDefinition);
1202-
bool mayDelay = !constant.hasUserWrittenCode() &&
1201+
auto linkage = constant.getLinkage(ForDefinition);;
1202+
bool mayDelay = !constant.shouldBeEmittedForDebugger() &&
1203+
!constant.hasUserWrittenCode() &&
12031204
!constant.isDynamicallyReplaceable() &&
12041205
!isPossiblyUsedExternally(linkage, M.isWholeModule());
12051206

test/IRGen/preserve_for_debugger.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class Baz: Foo {
5555

5656
struct Qux {
5757
@Bar(wrappedValue: Baz()) private var baz: Baz
58+
// Baz instance that is never accessed.
59+
@Bar(wrappedValue: Baz()) private var baz2: Baz
5860

5961
func f() {
6062
print(self.baz) // break here
@@ -64,3 +66,4 @@ let qux = Qux()
6466
qux.f()
6567

6668
// CHECK: !DISubprogram(name: "baz.get"
69+
// CHECK: !DISubprogram(name: "baz2.get"

0 commit comments

Comments
 (0)