Skip to content

Use correct associated context for SIL parsing #31690

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 4 commits into from
May 13, 2020
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: 0 additions & 3 deletions include/swift/AST/SILGenRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ struct SILGenDescriptor {
/// If the module or file contains SIL that needs parsing, returns the file
/// to be parsed, or \c nullptr if parsing isn't required.
SourceFile *getSourceFileToParse() const;

/// Whether the SIL is being emitted for a whole module.
bool isWholeModule() const;
};

void simple_display(llvm::raw_ostream &out, const SILGenDescriptor &d);
Expand Down
42 changes: 12 additions & 30 deletions include/swift/SIL/SILModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ enum class SILStage {
/// when a Swift compilation context is lowered to SIL.
class SILModule {
friend class SILFunctionBuilder;
friend class SILGenSourceFileRequest;
friend class SILGenWholeModuleRequest;

public:
using FunctionListType = llvm::ilist<SILFunction>;
Expand Down Expand Up @@ -262,10 +260,6 @@ class SILModule {
/// The indexed profile data to be used for PGO, or nullptr.
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;

/// True if this SILModule really contains the whole module, i.e.
/// optimizations can assume that they see the whole module.
bool wholeModule;

/// The options passed into this SILModule.
const SILOptions &Options;

Expand All @@ -280,11 +274,8 @@ class SILModule {
/// invalidation message is sent.
llvm::SetVector<DeleteNotificationHandler*> NotificationHandlers;

// Intentionally marked private so that we need to use 'constructSIL()'
// to construct a SILModule.
SILModule(ModuleDecl *M, Lowering::TypeConverter &TC,
const SILOptions &Options, const DeclContext *associatedDC,
bool wholeModule);
SILModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
Lowering::TypeConverter &TC, const SILOptions &Options);

SILModule(const SILModule&) = delete;
void operator=(const SILModule&) = delete;
Expand Down Expand Up @@ -355,47 +346,38 @@ class SILModule {
/// Erase a global SIL variable from the module.
void eraseGlobalVariable(SILGlobalVariable *G);

/// Construct a SIL module from an AST module.
///
/// The module will be constructed in the Raw stage. The provided AST module
/// should contain source files.
/// Create and return an empty SIL module suitable for generating or parsing
/// SIL into.
///
/// If a source file is provided, SIL will only be emitted for decls in that
/// source file.
static std::unique_ptr<SILModule>
constructSIL(ModuleDecl *M, Lowering::TypeConverter &TC,
const SILOptions &Options, FileUnit *sf = nullptr);

/// Create and return an empty SIL module that we can
/// later parse SIL bodies directly into, without converting from an AST.
/// \param context The associated decl context. This should be a FileUnit in
/// single-file mode, and a ModuleDecl in whole-module mode.
static std::unique_ptr<SILModule>
createEmptyModule(ModuleDecl *M, Lowering::TypeConverter &TC,
const SILOptions &Options,
bool WholeModule = false);
createEmptyModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
Lowering::TypeConverter &TC, const SILOptions &Options);

/// Get the Swift module associated with this SIL module.
ModuleDecl *getSwiftModule() const { return TheSwiftModule; }
/// Get the AST context used for type uniquing etc. by this SIL module.
ASTContext &getASTContext() const;
SourceManager &getSourceManager() const { return getASTContext().SourceMgr; }

/// Get the Swift DeclContext associated with this SIL module.
/// Get the Swift DeclContext associated with this SIL module. This is never
/// null.
///
/// All AST declarations within this context are assumed to have been fully
/// processed as part of generating this module. This allows certain passes
/// to make additional assumptions about these declarations.
///
/// If this is the same as TheSwiftModule, the entire module is being
/// compiled as a single unit. If this is null, no context-based assumptions
/// can be made.
/// compiled as a single unit.
const DeclContext *getAssociatedContext() const {
return AssociatedDeclContext;
}

/// Returns true if this SILModule really contains the whole module, i.e.
/// optimizations can assume that they see the whole module.
bool isWholeModule() const {
return wholeModule;
return isa<ModuleDecl>(AssociatedDeclContext);
}

bool isStdlibModule() const;
Expand Down
11 changes: 3 additions & 8 deletions lib/IRGen/IRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1203,14 +1203,9 @@ static bool isFirstObjectFileInModule(IRGenModule &IGM) {
if (IGM.getSILModule().isWholeModule())
return IGM.IRGen.getPrimaryIGM() == &IGM;

const DeclContext *DC = IGM.getSILModule().getAssociatedContext();
if (!DC)
return false;

assert(!isa<ModuleDecl>(DC) && "that would be a whole module build");
assert(isa<FileUnit>(DC) && "compiling something smaller than a file?");
ModuleDecl *containingModule = cast<FileUnit>(DC)->getParentModule();
return containingModule->getFiles().front() == DC;
auto *file = cast<FileUnit>(IGM.getSILModule().getAssociatedContext());
auto *containingModule = file->getParentModule();
return containingModule->getFiles().front() == file;
}

void IRGenModule::emitAutolinkInfo() {
Expand Down
6 changes: 0 additions & 6 deletions lib/SIL/IR/SIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,6 @@ bool SILModule::isTypeMetadataAccessible(CanType type) {
// Private declarations are inaccessible from different files unless
// this is WMO and we're in the same module.
case FormalLinkage::Private: {
// The only time we don't have an associated DC is in the
// integrated REPL, where we also don't have a concept of other
// source files within the current module.
if (!AssociatedDeclContext)
return (decl->getModuleContext() != getSwiftModule());

// The associated DC should be either a SourceFile or, in WMO mode,
// a ModuleDecl. In the WMO modes, IRGen will ensure that private
// declarations are usable throughout the module. Therefore, in
Expand Down
28 changes: 16 additions & 12 deletions lib/SIL/IR/SILModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,18 @@ class SILModule::SerializationCallback final
}
};

SILModule::SILModule(ModuleDecl *SwiftModule, TypeConverter &TC,
const SILOptions &Options, const DeclContext *associatedDC,
bool wholeModule)
: TheSwiftModule(SwiftModule),
AssociatedDeclContext(associatedDC),
Stage(SILStage::Raw), wholeModule(wholeModule), Options(Options),
serialized(false), SerializeSILAction(), Types(TC) {
SILModule::SILModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
Lowering::TypeConverter &TC, const SILOptions &Options)
: Stage(SILStage::Raw), Options(Options), serialized(false),
SerializeSILAction(), Types(TC) {
assert(!context.isNull());
if (auto *file = context.dyn_cast<FileUnit *>()) {
AssociatedDeclContext = file;
} else {
AssociatedDeclContext = context.get<ModuleDecl *>();
}
TheSwiftModule = AssociatedDeclContext->getParentModule();

// We always add the base SILModule serialization callback.
std::unique_ptr<DeserializationNotificationHandler> callback(
new SILModule::SerializationCallback());
Expand All @@ -122,11 +127,10 @@ SILModule::~SILModule() {
}
}

std::unique_ptr<SILModule>
SILModule::createEmptyModule(ModuleDecl *M, TypeConverter &TC, const SILOptions &Options,
bool WholeModule) {
return std::unique_ptr<SILModule>(
new SILModule(M, TC, Options, M, WholeModule));
std::unique_ptr<SILModule> SILModule::createEmptyModule(
llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
Lowering::TypeConverter &TC, const SILOptions &Options) {
return std::unique_ptr<SILModule>(new SILModule(context, TC, Options));
}

ASTContext &SILModule::getASTContext() const {
Expand Down
8 changes: 3 additions & 5 deletions lib/SIL/Parser/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,8 @@ ParseSILModuleRequest::evaluate(Evaluator &evaluator,
auto bufferID = SF->getBufferID();
assert(bufferID);

auto *mod = SF->getParentModule();
auto silMod = SILModule::createEmptyModule(mod, desc.conv, desc.opts,
desc.isWholeModule());
auto silMod = SILModule::createEmptyModule(desc.context, desc.conv,
desc.opts);
SILParserState parserState(silMod.get());
Parser parser(*bufferID, *SF, parserState.Impl.get());
PrettyStackTraceParser StackTrace(parser);
Expand All @@ -126,8 +125,7 @@ ParseSILModuleRequest::evaluate(Evaluator &evaluator,
if (hadError) {
// The rest of the SIL pipeline expects well-formed SIL, so if we encounter
// a parsing error, just return an empty SIL module.
return SILModule::createEmptyModule(mod, desc.conv, desc.opts,
desc.isWholeModule());
return SILModule::createEmptyModule(desc.context, desc.conv, desc.opts);
}
return silMod;
}
Expand Down
6 changes: 2 additions & 4 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1867,8 +1867,7 @@ SILGenSourceFileRequest::evaluate(Evaluator &evaluator,

auto *unit = desc.context.get<FileUnit *>();
auto *mod = unit->getParentModule();
auto M = std::unique_ptr<SILModule>(
new SILModule(mod, desc.conv, desc.opts, unit, /*wholeModule*/ false));
auto M = SILModule::createEmptyModule(desc.context, desc.conv, desc.opts);
SILGenModuleRAII scope(*M, mod);

if (auto *file = dyn_cast<SourceFile>(unit)) {
Expand All @@ -1890,8 +1889,7 @@ SILGenWholeModuleRequest::evaluate(Evaluator &evaluator,
}

auto *mod = desc.context.get<ModuleDecl *>();
auto M = std::unique_ptr<SILModule>(
new SILModule(mod, desc.conv, desc.opts, mod, /*wholeModule*/ true));
auto M = SILModule::createEmptyModule(desc.context, desc.conv, desc.opts);
SILGenModuleRAII scope(*M, mod);

for (auto file : mod->getFiles()) {
Expand Down
2 changes: 0 additions & 2 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4099,8 +4099,6 @@ static bool isVerbatimNullableTypeInC(SILModule &M, Type ty) {

// Other types like UnsafePointer can also be nullable.
const DeclContext *DC = M.getAssociatedContext();
if (!DC)
DC = M.getSwiftModule();
ty = OptionalType::get(ty);
return ty->isTriviallyRepresentableIn(ForeignLanguage::C, DC);
}
Expand Down
4 changes: 0 additions & 4 deletions lib/SILGen/SILGenRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ ArrayRef<FileUnit *> SILGenDescriptor::getFiles() const {
return llvm::makeArrayRef(*context.getAddrOfPtr1());
}

bool SILGenDescriptor::isWholeModule() const {
return context.is<ModuleDecl *>();
}

SourceFile *SILGenDescriptor::getSourceFileToParse() const {
#ifndef NDEBUG
auto sfCount = llvm::count_if(getFiles(), [](FileUnit *file) {
Expand Down
9 changes: 1 addition & 8 deletions lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,6 @@ static bool isDefaultCaseKnown(ClassHierarchyAnalysis *CHA,
auto *Method = CMI->getMember().getAbstractFunctionDecl();
assert(Method && "not a function");

const DeclContext *DC = AI.getModule().getAssociatedContext();

if (CD->isFinal())
return true;

Expand All @@ -295,13 +293,8 @@ static bool isDefaultCaseKnown(ClassHierarchyAnalysis *CHA,
if (CD->checkAncestry(AncestryFlags::ObjC))
return false;

// Without an associated context we cannot perform any
// access-based optimizations.
if (!DC)
return false;

// Only handle classes defined within the SILModule's associated context.
if (!CD->isChildContextOf(DC))
if (!CD->isChildContextOf(AI.getModule().getAssociatedContext()))
return false;

if (!CD->hasAccess())
Expand Down
16 changes: 1 addition & 15 deletions lib/SILOptimizer/Utils/Devirtualize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,6 @@ static bool isEffectivelyFinalMethod(FullApplySite applySite, CanType classType,
if (cd && cd->isFinal())
return true;

const DeclContext *dc = applySite.getModule().getAssociatedContext();

// Without an associated context we cannot perform any
// access-based optimizations.
if (!dc)
return false;

auto *cmi = cast<MethodInst>(applySite.getCallee());

if (!calleesAreStaticallyKnowable(applySite.getModule(), cmi->getMember()))
Expand Down Expand Up @@ -149,18 +142,11 @@ static bool isEffectivelyFinalMethod(FullApplySite applySite, CanType classType,
/// it is a whole-module compilation.
static bool isKnownFinalClass(ClassDecl *cd, SILModule &module,
ClassHierarchyAnalysis *cha) {
const DeclContext *dc = module.getAssociatedContext();

if (cd->isFinal())
return true;

// Without an associated context we cannot perform any
// access-based optimizations.
if (!dc)
return false;

// Only handle classes defined within the SILModule's associated context.
if (!cd->isChildContextOf(dc))
if (!cd->isChildContextOf(module.getAssociatedContext()))
return false;

if (!cd->hasAccess())
Expand Down
12 changes: 2 additions & 10 deletions lib/SILOptimizer/Utils/InstOptUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1815,12 +1815,8 @@ bool swift::calleesAreStaticallyKnowable(SILModule &module, SILDeclRef decl) {
/// knowable based on the Decl and the compilation mode?
bool swift::calleesAreStaticallyKnowable(SILModule &module,
AbstractFunctionDecl *afd) {
const DeclContext *assocDC = module.getAssociatedContext();
if (!assocDC)
return false;

// Only handle members defined within the SILModule's associated context.
if (!afd->isChildContextOf(assocDC))
if (!afd->isChildContextOf(module.getAssociatedContext()))
return false;

if (afd->isDynamic()) {
Expand Down Expand Up @@ -1859,12 +1855,8 @@ bool swift::calleesAreStaticallyKnowable(SILModule &module,
// FIXME: Merge this with calleesAreStaticallyKnowable above
bool swift::calleesAreStaticallyKnowable(SILModule &module,
EnumElementDecl *eed) {
const DeclContext *assocDC = module.getAssociatedContext();
if (!assocDC)
return false;

// Only handle members defined within the SILModule's associated context.
if (!eed->isChildContextOf(assocDC))
if (!eed->isChildContextOf(module.getAssociatedContext()))
return false;

if (eed->isDynamic()) {
Expand Down
3 changes: 0 additions & 3 deletions lib/Serialization/SerializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2645,9 +2645,6 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
// Go through all SILVTables in SILMod and write them if we should
// serialize everything.
// FIXME: Resilience: could write out vtable for fragile classes.
const DeclContext *assocDC = SILMod->getAssociatedContext();
assert(assocDC && "cannot serialize SIL without an associated DeclContext");
(void)assocDC;
for (const SILVTable &vt : SILMod->getVTables()) {
if ((ShouldSerializeAll || vt.isSerialized()) &&
SILMod->shouldSerializeEntitiesAssociatedWithDeclContext(vt.getClass()))
Expand Down
5 changes: 5 additions & 0 deletions test/IRGen/multi_file_resilience.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

// RUN: %target-swift-frontend -module-name main -I %t -emit-ir -primary-file %s %S/Inputs/OtherModule.swift | %FileCheck %s -DINT=i%target-ptrsize

// Check that we correctly handle resilience when parsing as SIL + SIB.
// RUN: %target-swift-frontend -emit-sib -module-name main %S/Inputs/OtherModule.swift -I %t -o %t/other.sib
// RUN: %target-swift-frontend -emit-silgen -module-name main -primary-file %s %S/Inputs/OtherModule.swift -I %t -o %t/main.sil
// RUN: %target-swift-frontend -emit-ir -module-name main -primary-file %t/main.sil %t/other.sib -I %t | %FileCheck %s -DINT=i%target-ptrsize

// This is a single-module version of the test case in
// multi_module_resilience.
// rdar://39763787
Expand Down