Skip to content

[TBDGen] Fix check for global accessors #18883

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4528,6 +4528,9 @@ class VarDecl : public AbstractStorageDecl {
ParentPattern = S;
}

/// True if the global stored property requires lazy initialization.
bool isLazilyInitializedGlobal() const;

/// Return the initializer involved in this VarDecl. Recall that the
/// initializer may be involved in initializing more than just this one
/// vardecl though. For example, if this is a VarDecl for "x", the pattern
Expand Down
21 changes: 21 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4481,6 +4481,27 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
return false;
}

bool VarDecl::isLazilyInitializedGlobal() const {
assert(!getDeclContext()->isLocalContext() &&
"not a global variable!");
assert(hasStorage() && "not a stored global variable!");

// Imports from C are never lazily initialized.
if (hasClangNode())
return false;

if (isDebuggerVar())
return false;

// Top-level global variables in the main source file and in the REPL are not
// lazily initialized.
auto sourceFileContext = dyn_cast<SourceFile>(getDeclContext());
if (!sourceFileContext)
return true;

return !sourceFileContext->isScriptMode();
}

bool SubscriptDecl::isSettable() const {
return supportsMutation();
}
Expand Down
25 changes: 1 addition & 24 deletions lib/SILGen/SILGenGlobalVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,34 +58,11 @@ SILGlobalVariable *SILGenModule::getSILGlobalVariable(VarDecl *gDecl,
return silGlobal;
}

/// True if the global stored property requires lazy initialization.
static bool isGlobalLazilyInitialized(VarDecl *var) {
assert(!var->getDeclContext()->isLocalContext() &&
"not a global variable!");
assert(var->hasStorage() &&
"not a stored global variable!");

// Imports from C are never lazily initialized.
if (var->hasClangNode())
return false;

if (var->isDebuggerVar())
return false;

// Top-level global variables in the main source file and in the REPL are not
// lazily initialized.
auto sourceFileContext = dyn_cast<SourceFile>(var->getDeclContext());
if (!sourceFileContext)
return true;

return !sourceFileContext->isScriptMode();
}

ManagedValue
SILGenFunction::emitGlobalVariableRef(SILLocation loc, VarDecl *var) {
assert(!VarLocs.count(var));

if (isGlobalLazilyInitialized(var)) {
if (var->isLazilyInitializedGlobal()) {
// Call the global accessor to get the variable's address.
SILFunction *accessorFn = SGM.getFunction(
SILDeclRef(var, SILDeclRef::Kind::GlobalAccessor),
Expand Down
6 changes: 2 additions & 4 deletions lib/TBDGen/TBDGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,7 @@ void TBDGenVisitor::visitVarDecl(VarDecl *VD) {
addSymbol(mangler.mangleEntity(VD, false));
}

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

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

visitor.setFileHasEntryPoint(file->hasEntryPoint());
visitor.addMainIfNecessary(file);

for (auto d : decls)
visitor.visit(d);
Expand Down
11 changes: 5 additions & 6 deletions lib/TBDGen/TBDGenVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
const TBDGenOptions &Opts;

private:
bool FileHasEntryPoint = false;

void addSymbol(StringRef name, tapi::internal::SymbolKind kind =
tapi::internal::SymbolKind::GlobalSymbol);

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

void setFileHasEntryPoint(bool hasEntryPoint) {
FileHasEntryPoint = hasEntryPoint;

if (hasEntryPoint)
void addMainIfNecessary(FileUnit *file) {
// HACK: 'main' is a special symbol that's always emitted in SILGen if
// the file has an entry point. Since it doesn't show up in the
// module until SILGen, we need to explicitly add it here.
if (file->hasEntryPoint())
addSymbol("main");
}

Expand Down
14 changes: 14 additions & 0 deletions test/TBD/objc-entry-point.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 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
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir -o /dev/null -validate-tbd-against-ir=all -parse-as-library -verify %s

// REQUIRES: objc_interop
import AppKit

// Globals in non-script mode files that still have entry points
// (via NSApplicationMain) _do_ have lazy initializers. Ensure the symbols are
// present in the TBD.
let globalConstantWithLazyInitializer: String = "hello, world"

@NSApplicationMain
class MyDelegate: NSObject, NSApplicationDelegate {
}