Skip to content

Commit

Permalink
Merge pull request swiftlang#39032 from adrian-prantl/79462915-5.5
Browse files Browse the repository at this point in the history
Disable resilience for modules imported by the MemoryBuffer loader.
  • Loading branch information
adrian-prantl authored Sep 20, 2021
2 parents 7e7333e + e754f5a commit fcc77a6
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 19 deletions.
9 changes: 9 additions & 0 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ class ModuleDecl

AccessNotesFile accessNotes;

/// Used by the debugger to bypass resilient access to fields.
bool BypassResilience = false;

ModuleDecl(Identifier name, ASTContext &ctx, ImplicitImportInfo importInfo);

public:
Expand Down Expand Up @@ -290,6 +293,12 @@ class ModuleDecl
AccessNotesFile &getAccessNotes() { return accessNotes; }
const AccessNotesFile &getAccessNotes() const { return accessNotes; }

/// Return whether the module was imported with resilience disabled. The
/// debugger does this to access private fields.
bool getBypassResilience() const { return BypassResilience; }
/// Only to be called by MemoryBufferSerializedModuleLoader.
void setBypassResilience() { BypassResilience = true; }

ArrayRef<FileUnit *> getFiles() {
assert(!Files.empty() || failedToLoad());
return Files;
Expand Down
13 changes: 8 additions & 5 deletions include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,11 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
MemoryBufferSerializedModuleLoader(ASTContext &ctx,
DependencyTracker *tracker,
ModuleLoadingMode loadMode,
bool IgnoreSwiftSourceInfo)
bool IgnoreSwiftSourceInfo,
bool BypassResilience)
: SerializedModuleLoaderBase(ctx, tracker, loadMode,
IgnoreSwiftSourceInfo) {}
IgnoreSwiftSourceInfo),
BypassResilience(BypassResilience) {}

std::error_code findModuleFilesInDirectory(
ImportPath::Element ModuleID,
Expand All @@ -279,6 +281,7 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
StringRef moduleName,
const SerializedModuleBaseName &BaseName) override;

bool BypassResilience;
public:
virtual ~MemoryBufferSerializedModuleLoader();

Expand Down Expand Up @@ -308,10 +311,10 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
static std::unique_ptr<MemoryBufferSerializedModuleLoader>
create(ASTContext &ctx, DependencyTracker *tracker = nullptr,
ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized,
bool IgnoreSwiftSourceInfo = false) {
bool IgnoreSwiftSourceInfo = false, bool BypassResilience = false) {
return std::unique_ptr<MemoryBufferSerializedModuleLoader>{
new MemoryBufferSerializedModuleLoader(ctx, tracker, loadMode,
IgnoreSwiftSourceInfo)};
new MemoryBufferSerializedModuleLoader(
ctx, tracker, loadMode, IgnoreSwiftSourceInfo, BypassResilience)};
}
};

Expand Down
2 changes: 1 addition & 1 deletion lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1916,7 +1916,7 @@ static bool isDirectToStorageAccess(const DeclContext *UseDC,
// If the storage is resilient, we cannot access it directly at all.
if (var->isResilient(UseDC->getParentModule(),
UseDC->getResilienceExpansion()))
return false;
return var->getModuleContext()->getBypassResilience();

if (isa<ConstructorDecl>(AFD) || isa<DestructorDecl>(AFD)) {
// The access must also be a member access on 'self' in all language modes.
Expand Down
5 changes: 4 additions & 1 deletion lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4982,7 +4982,10 @@ llvm::Constant *IRGenModule::getAddrOfGlobalUTF16String(StringRef utf8) {
/// - For enums, new cases can be added
/// - For classes, the superclass might change the size or number
/// of stored properties
bool IRGenModule::isResilient(NominalTypeDecl *D, ResilienceExpansion expansion) {
bool IRGenModule::isResilient(NominalTypeDecl *D,
ResilienceExpansion expansion) {
if (D->getModuleContext()->getBypassResilience())
return false;
if (expansion == ResilienceExpansion::Maximal &&
Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile) {
return false;
Expand Down
33 changes: 21 additions & 12 deletions lib/SIL/Verifier/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ static bool isArchetypeValidInFunction(ArchetypeType *A, const SILFunction *F) {

namespace {

/// When resilience is bypassed, direct access is legal, but the decls are still
/// resilient.
template <typename DeclType>
bool checkResilience(DeclType *D, ModuleDecl *M,
ResilienceExpansion expansion) {
return !D->getModuleContext()->getBypassResilience() &&
D->isResilient(M, expansion);
}

/// Metaprogramming-friendly base class.
template <class Impl>
class SILVerifierBase : public SILInstructionVisitor<Impl> {
Expand Down Expand Up @@ -234,7 +243,7 @@ void verifyKeyPathComponent(SILModule &M,
"property decl should be a member of the base with the same type "
"as the component");
require(property->hasStorage(), "property must be stored");
require(!property->isResilient(M.getSwiftModule(), expansion),
require(!checkResilience(property, M.getSwiftModule(), expansion),
"cannot access storage of resilient property");
auto propertyTy =
loweredBaseTy.getFieldType(property, M, typeExpansionContext);
Expand Down Expand Up @@ -2045,7 +2054,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
void checkAllocGlobalInst(AllocGlobalInst *AGI) {
SILGlobalVariable *RefG = AGI->getReferencedGlobal();
if (auto *VD = RefG->getDecl()) {
require(!VD->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(VD, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient global");
}
Expand All @@ -2064,7 +2073,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
RefG->getLoweredTypeInContext(F.getTypeExpansionContext()),
"global_addr/value must be the type of the variable it references");
if (auto *VD = RefG->getDecl()) {
require(!VD->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(VD, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient global");
}
Expand Down Expand Up @@ -2752,8 +2761,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
require(!structDecl->hasUnreferenceableStorage(),
"Cannot build a struct with unreferenceable storage from elements "
"using StructInst");
require(!structDecl->isResilient(F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
require(!checkResilience(structDecl, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient struct");
require(SI->getType().isObject(),
"StructInst must produce an object");
Expand Down Expand Up @@ -2954,8 +2963,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
require(cd, "Operand of dealloc_ref must be of class type");

if (!DI->canAllocOnStack()) {
require(!cd->isResilient(F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
require(!checkResilience(cd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot directly deallocate resilient class");
}
}
Expand Down Expand Up @@ -3071,7 +3080,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"result of struct_extract cannot be address");
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
require(sd, "must struct_extract from struct");
require(!sd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(sd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient struct");
require(!EI->getField()->isStatic(),
Expand Down Expand Up @@ -3120,7 +3129,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"must derive struct_element_addr from address");
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
require(sd, "struct_element_addr operand must be struct address");
require(!sd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(sd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient struct");
require(EI->getType().isAddress(),
Expand Down Expand Up @@ -3153,7 +3162,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
SILType operandTy = EI->getOperand()->getType();
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
require(cd, "ref_element_addr operand must be a class instance");
require(!cd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(cd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient class");

Expand All @@ -3177,7 +3186,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
SILType operandTy = RTAI->getOperand()->getType();
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
require(cd, "ref_tail_addr operand must be a class instance");
require(!cd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(cd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient class");
require(cd, "ref_tail_addr operand must be a class instance");
Expand All @@ -3187,7 +3196,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
SILType operandTy = DSI->getOperand()->getType();
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
require(sd, "must struct_extract from struct");
require(!sd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(sd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient struct");
if (F.hasOwnership()) {
Expand Down
5 changes: 5 additions & 0 deletions lib/Serialization/SerializedModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,11 @@ MemoryBufferSerializedModuleLoader::loadModule(SourceLoc importLoc,
if (!file)
return nullptr;

// The MemoryBuffer loader is used by LLDB during debugging. Modules imported
// from .swift_ast sections are never produced from textual interfaces. By
// disabling resilience the debugger can directly access private members.
if (BypassResilience)
M->setBypassResilience();
M->addFile(*file);
Ctx.addLoadedModule(M);
return M;
Expand Down

0 comments on commit fcc77a6

Please sign in to comment.