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
This commit is contained in:
Augusto Noronha
2024-08-13 14:53:41 -07:00
parent a07caa8ba5
commit ae98212c1a
4 changed files with 43 additions and 2 deletions

View File

@@ -576,6 +576,10 @@ struct SILDeclRef {
/// for e.g a lazy variable getter. /// for e.g a lazy variable getter.
bool hasUserWrittenCode() const; bool hasUserWrittenCode() const;
/// Returns true if this is a function that should be emitted because it is
/// accessible in the debugger.
bool shouldBeEmittedForDebugger() const;
/// Return the scope in which the parent class of a method (i.e. class /// Return the scope in which the parent class of a method (i.e. class
/// containing this declaration) can be subclassed, returning NotApplicable if /// containing this declaration) can be subclassed, returning NotApplicable if
/// this is not a method, there is no such class, or the class cannot be /// this is not a method, there is no such class, or the class cannot be

View File

@@ -387,6 +387,39 @@ bool SILDeclRef::hasUserWrittenCode() const {
llvm_unreachable("Unhandled case in switch!"); llvm_unreachable("Unhandled case in switch!");
} }
bool SILDeclRef::shouldBeEmittedForDebugger() const {
if (!isFunc())
return false;
if (getASTContext().SILOpts.OptMode != OptimizationMode::NoOptimization)
return false;;
if (!getASTContext().SILOpts.ShouldFunctionsBePreservedToDebugger)
return false;
if (getASTContext().LangOpts.hasFeature(Feature::Embedded))
return false;
ValueDecl *decl = getDecl();
DeclAttributes &attrs = decl->getAttrs();
if (attrs.hasSemanticsAttr("no.preserve.debugger"))
return false;
if (getLinkage(ForDefinition) == SILLinkage::Shared)
return false;
if (auto decl = getDecl())
if (!decl->isImplicit())
return true;
// Synthesized getters are still callable in the debugger.
if (auto *accessor = dyn_cast_or_null<AccessorDecl>(getFuncDecl())) {
return accessor->isSynthesized() && accessor->isGetterOrSetter();
};
return false;
}
namespace { namespace {
enum class LinkageLimit { enum class LinkageLimit {
/// No limit. /// No limit.

View File

@@ -1198,8 +1198,9 @@ void SILGenModule::emitOrDelayFunction(SILDeclRef constant) {
auto emitAfter = lastEmittedFunction; auto emitAfter = lastEmittedFunction;
// Implicit decls may be delayed if they can't be used externally. // Implicit decls may be delayed if they can't be used externally.
auto linkage = constant.getLinkage(ForDefinition); auto linkage = constant.getLinkage(ForDefinition);;
bool mayDelay = !constant.hasUserWrittenCode() && bool mayDelay = !constant.shouldBeEmittedForDebugger() &&
!constant.hasUserWrittenCode() &&
!constant.isDynamicallyReplaceable() && !constant.isDynamicallyReplaceable() &&
!isPossiblyUsedExternally(linkage, M.isWholeModule()); !isPossiblyUsedExternally(linkage, M.isWholeModule());

View File

@@ -55,6 +55,8 @@ class Baz: Foo {
struct Qux { struct Qux {
@Bar(wrappedValue: Baz()) private var baz: Baz @Bar(wrappedValue: Baz()) private var baz: Baz
// Baz instance that is never accessed.
@Bar(wrappedValue: Baz()) private var baz2: Baz
func f() { func f() {
print(self.baz) // break here print(self.baz) // break here
@@ -64,3 +66,4 @@ let qux = Qux()
qux.f() qux.f()
// CHECK: !DISubprogram(name: "baz.get" // CHECK: !DISubprogram(name: "baz.get"
// CHECK: !DISubprogram(name: "baz2.get"