Skip to content

Commit 096e6ad

Browse files
author
Harlan
authored
[TBDGen] Fix check for global accessors (#18883)
Previously, TBDGen skipped emitting lazy initializers for globals that appeared in any file with an entry point. This breaks, however on files that have an NSApplicationMain/UIApplicationMain class in them, where the entry point is synthesized but top-level globals are not locally scoped. This change re-uses SILGen's check and only skips variable declarations that appear at top level in a script mode file. Resolves rdar://43549749
1 parent 98e95bd commit 096e6ad

File tree

6 files changed

+46
-34
lines changed

6 files changed

+46
-34
lines changed

include/swift/AST/Decl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4528,6 +4528,9 @@ class VarDecl : public AbstractStorageDecl {
45284528
ParentPattern = S;
45294529
}
45304530

4531+
/// True if the global stored property requires lazy initialization.
4532+
bool isLazilyInitializedGlobal() const;
4533+
45314534
/// Return the initializer involved in this VarDecl. Recall that the
45324535
/// initializer may be involved in initializing more than just this one
45334536
/// vardecl though. For example, if this is a VarDecl for "x", the pattern

lib/AST/Decl.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4481,6 +4481,27 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
44814481
return false;
44824482
}
44834483

4484+
bool VarDecl::isLazilyInitializedGlobal() const {
4485+
assert(!getDeclContext()->isLocalContext() &&
4486+
"not a global variable!");
4487+
assert(hasStorage() && "not a stored global variable!");
4488+
4489+
// Imports from C are never lazily initialized.
4490+
if (hasClangNode())
4491+
return false;
4492+
4493+
if (isDebuggerVar())
4494+
return false;
4495+
4496+
// Top-level global variables in the main source file and in the REPL are not
4497+
// lazily initialized.
4498+
auto sourceFileContext = dyn_cast<SourceFile>(getDeclContext());
4499+
if (!sourceFileContext)
4500+
return true;
4501+
4502+
return !sourceFileContext->isScriptMode();
4503+
}
4504+
44844505
bool SubscriptDecl::isSettable() const {
44854506
return supportsMutation();
44864507
}

lib/SILGen/SILGenGlobalVariable.cpp

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,34 +58,11 @@ SILGlobalVariable *SILGenModule::getSILGlobalVariable(VarDecl *gDecl,
5858
return silGlobal;
5959
}
6060

61-
/// True if the global stored property requires lazy initialization.
62-
static bool isGlobalLazilyInitialized(VarDecl *var) {
63-
assert(!var->getDeclContext()->isLocalContext() &&
64-
"not a global variable!");
65-
assert(var->hasStorage() &&
66-
"not a stored global variable!");
67-
68-
// Imports from C are never lazily initialized.
69-
if (var->hasClangNode())
70-
return false;
71-
72-
if (var->isDebuggerVar())
73-
return false;
74-
75-
// Top-level global variables in the main source file and in the REPL are not
76-
// lazily initialized.
77-
auto sourceFileContext = dyn_cast<SourceFile>(var->getDeclContext());
78-
if (!sourceFileContext)
79-
return true;
80-
81-
return !sourceFileContext->isScriptMode();
82-
}
83-
8461
ManagedValue
8562
SILGenFunction::emitGlobalVariableRef(SILLocation loc, VarDecl *var) {
8663
assert(!VarLocs.count(var));
8764

88-
if (isGlobalLazilyInitialized(var)) {
65+
if (var->isLazilyInitializedGlobal()) {
8966
// Call the global accessor to get the variable's address.
9067
SILFunction *accessorFn = SGM.getFunction(
9168
SILDeclRef(var, SILDeclRef::Kind::GlobalAccessor),

lib/TBDGen/TBDGen.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,7 @@ void TBDGenVisitor::visitVarDecl(VarDecl *VD) {
208208
addSymbol(mangler.mangleEntity(VD, false));
209209
}
210210

211-
// Top-level variables (*not* statics) in the main file don't get accessors,
212-
// despite otherwise looking like globals.
213-
if (!FileHasEntryPoint || VD->isStatic())
211+
if (VD->isLazilyInitializedGlobal())
214212
addSymbol(SILDeclRef(VD, SILDeclRef::Kind::GlobalAccessor));
215213
}
216214

@@ -459,7 +457,7 @@ static void enumeratePublicSymbolsAndWrite(ModuleDecl *M, FileUnit *singleFile,
459457
SmallVector<Decl *, 16> decls;
460458
file->getTopLevelDecls(decls);
461459

462-
visitor.setFileHasEntryPoint(file->hasEntryPoint());
460+
visitor.addMainIfNecessary(file);
463461

464462
for (auto d : decls)
465463
visitor.visit(d);

lib/TBDGen/TBDGenVisitor.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
5151
const TBDGenOptions &Opts;
5252

5353
private:
54-
bool FileHasEntryPoint = false;
55-
5654
void addSymbol(StringRef name, tapi::internal::SymbolKind kind =
5755
tapi::internal::SymbolKind::GlobalSymbol);
5856

@@ -73,10 +71,11 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
7371
UniversalLinkInfo(universalLinkInfo), SwiftModule(swiftModule),
7472
Opts(opts) {}
7573

76-
void setFileHasEntryPoint(bool hasEntryPoint) {
77-
FileHasEntryPoint = hasEntryPoint;
78-
79-
if (hasEntryPoint)
74+
void addMainIfNecessary(FileUnit *file) {
75+
// HACK: 'main' is a special symbol that's always emitted in SILGen if
76+
// the file has an entry point. Since it doesn't show up in the
77+
// module until SILGen, we need to explicitly add it here.
78+
if (file->hasEntryPoint())
8079
addSymbol("main");
8180
}
8281

test/TBD/objc-entry-point.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir -o /dev/null -validate-tbd-against-ir=all -parse-as-library -verify -enable-testing %s
2+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir -o /dev/null -validate-tbd-against-ir=all -parse-as-library -verify %s
3+
4+
// REQUIRES: objc_interop
5+
import AppKit
6+
7+
// Globals in non-script mode files that still have entry points
8+
// (via NSApplicationMain) _do_ have lazy initializers. Ensure the symbols are
9+
// present in the TBD.
10+
let globalConstantWithLazyInitializer: String = "hello, world"
11+
12+
@NSApplicationMain
13+
class MyDelegate: NSObject, NSApplicationDelegate {
14+
}

0 commit comments

Comments
 (0)