Skip to content

Weakly import declarations with conditional availability #22729

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 3 commits into from
Feb 20, 2019
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
4 changes: 4 additions & 0 deletions include/swift/AST/Availability.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@ class AvailabilityContext {
/// Creates a context that requires certain versions of the target OS.
explicit AvailabilityContext(VersionRange OSVersion) : OSVersion(OSVersion) {}

/// Creates a context that imposes the constraints of the ASTContext's
/// deployment target.
static AvailabilityContext forDeploymentTarget(ASTContext &Ctx);

/// Creates a context that imposes no constraints.
///
/// \see isAlwaysAvailable
Expand Down
4 changes: 3 additions & 1 deletion include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace swift {
enum class AccessSemantics : unsigned char;
class AccessorDecl;
class ApplyExpr;
class AvailabilityContext;
class GenericEnvironment;
class ArchetypeType;
class ASTContext;
Expand Down Expand Up @@ -940,7 +941,8 @@ class alignas(1 << DeclAlignInBits) Decl {
bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const;

/// Whether this declaration is weak-imported.
bool isWeakImported(ModuleDecl *fromModule) const;
bool isWeakImported(ModuleDecl *fromModule,
AvailabilityContext fromContext) const;

/// Returns true if the nature of this declaration allows overrides.
/// Note that this does not consider whether it is final or whether
Expand Down
3 changes: 2 additions & 1 deletion include/swift/AST/ProtocolConformance.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,8 @@ class RootProtocolConformance : public ProtocolConformance {
bool isInvalid() const;

/// Whether this conformance is weak-imported.
bool isWeakImported(ModuleDecl *fromModule) const;
bool isWeakImported(ModuleDecl *fromModule,
AvailabilityContext fromContext) const;

bool hasWitness(ValueDecl *requirement) const;
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const;
Expand Down
9 changes: 7 additions & 2 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class Triple;
}

namespace swift {
class AvailabilityContext;

namespace irgen {
class IRGenModule;
class Alignment;
Expand Down Expand Up @@ -1021,7 +1023,8 @@ class LinkEntity {
}

/// Determine whether this entity will be weak-imported.
bool isWeakImported(ModuleDecl *module) const;
bool isWeakImported(ModuleDecl *module,
AvailabilityContext fromContext) const;

/// Return the source file whose codegen should trigger emission of this
/// link entity, if one can be identified.
Expand Down Expand Up @@ -1089,7 +1092,9 @@ class LinkInfo {
ForDefinition_t forDefinition);

static LinkInfo get(const UniversalLinkageInfo &linkInfo,
ModuleDecl *swiftModule, const LinkEntity &entity,
ModuleDecl *swiftModule,
AvailabilityContext availabilityContext,
const LinkEntity &entity,
ForDefinition_t forDefinition);

static LinkInfo get(const UniversalLinkageInfo &linkInfo, StringRef name,
Expand Down
10 changes: 9 additions & 1 deletion include/swift/SIL/SILFunctionBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef SWIFT_SIL_SILFUNCTIONBUILDER_H
#define SWIFT_SIL_SILFUNCTIONBUILDER_H

#include "swift/AST/Availability.h"
#include "swift/SIL/SILModule.h"

namespace swift {
Expand Down Expand Up @@ -42,13 +43,20 @@ class SILGenFunctionBuilder;
/// code-reuse in between these different SILFunction creation sites.
class SILFunctionBuilder {
SILModule &mod;
AvailabilityContext availCtx;

friend class SILParserFunctionBuilder;
friend class SILSerializationFunctionBuilder;
friend class SILOptFunctionBuilder;
friend class Lowering::SILGenFunctionBuilder;

SILFunctionBuilder(SILModule &mod) : mod(mod) {}
SILFunctionBuilder(SILModule &mod)
: SILFunctionBuilder(mod,
AvailabilityContext::forDeploymentTarget(
mod.getASTContext())) {}

SILFunctionBuilder(SILModule &mod, AvailabilityContext availCtx)
: mod(mod), availCtx(availCtx) {}

/// Return the declaration of a utility function that can, but needn't, be
/// shared between different parts of a program.
Expand Down
6 changes: 6 additions & 0 deletions lib/AST/Availability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//
//===----------------------------------------------------------------------===//

#include "swift/AST/ASTContext.h"
#include "swift/AST/Attr.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Types.h"
Expand All @@ -24,6 +25,11 @@

using namespace swift;

AvailabilityContext AvailabilityContext::forDeploymentTarget(ASTContext &Ctx) {
return AvailabilityContext(
VersionRange::allGTE(Ctx.LangOpts.getMinPlatformVersion()));
}

namespace {

/// The inferred availability required to access a group of declarations
Expand Down
18 changes: 12 additions & 6 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,8 @@ bool Decl::isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic) const {
return false;
}

bool Decl::isWeakImported(ModuleDecl *fromModule) const {
bool Decl::isWeakImported(ModuleDecl *fromModule,
AvailabilityContext fromContext) const {
// For a Clang declaration, trust Clang.
if (auto clangDecl = getClangDecl()) {
return clangDecl->isWeakImported();
Expand All @@ -546,22 +547,27 @@ bool Decl::isWeakImported(ModuleDecl *fromModule) const {
if (containingModule == fromModule)
return false;

auto containingContext =
AvailabilityInference::availableRange(this, fromModule->getASTContext());
if (!fromContext.isContainedIn(containingContext))
return true;

if (getAttrs().hasAttribute<WeakLinkedAttr>())
return true;

if (auto *accessor = dyn_cast<AccessorDecl>(this))
return accessor->getStorage()->isWeakImported(fromModule);
return accessor->getStorage()->isWeakImported(fromModule, fromContext);

if (auto *dtor = dyn_cast<DestructorDecl>(this))
return cast<ClassDecl>(dtor->getDeclContext())->isWeakImported(fromModule);
return cast<ClassDecl>(dtor->getDeclContext())->isWeakImported(
fromModule, fromContext);

auto *dc = getDeclContext();
if (auto *ext = dyn_cast<ExtensionDecl>(dc))
return ext->isWeakImported(fromModule);
return ext->isWeakImported(fromModule, fromContext);
if (auto *ntd = dyn_cast<NominalTypeDecl>(dc))
return ntd->isWeakImported(fromModule);
return ntd->isWeakImported(fromModule, fromContext);

// FIXME: Also check availability when containingModule is resilient.
return false;
}

Expand Down
11 changes: 7 additions & 4 deletions lib/AST/ProtocolConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "ConformanceLookupTable.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Availability.h"
#include "swift/AST/Decl.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/GenericEnvironment.h"
Expand Down Expand Up @@ -383,24 +384,26 @@ SourceLoc RootProtocolConformance::getLoc() const {
ROOT_CONFORMANCE_SUBCLASS_DISPATCH(getLoc, ())
}

bool RootProtocolConformance::isWeakImported(ModuleDecl *fromModule) const {
bool
RootProtocolConformance::isWeakImported(ModuleDecl *fromModule,
AvailabilityContext fromContext) const {
auto *dc = getDeclContext();
if (dc->getParentModule() == fromModule)
return false;

// If the protocol is weak imported, so are any conformances to it.
if (getProtocol()->isWeakImported(fromModule))
if (getProtocol()->isWeakImported(fromModule, fromContext))
return true;

// If the conforming type is weak imported, so are any of its conformances.
if (auto *nominal = getType()->getAnyNominal())
if (nominal->isWeakImported(fromModule))
if (nominal->isWeakImported(fromModule, fromContext))
return true;

// If the conformance is declared in an extension with the @_weakLinked
// attribute, it is weak imported.
if (auto *ext = dyn_cast<ExtensionDecl>(dc))
if (ext->isWeakImported(fromModule))
if (ext->isWeakImported(fromModule, fromContext))
return true;

return false;
Expand Down
4 changes: 3 additions & 1 deletion lib/IRGen/AllocStackHoisting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define DEBUG_TYPE "alloc-stack-hoisting"

#include "swift/IRGen/IRGenSILPasses.h"
#include "swift/AST/Availability.h"
#include "swift/SILOptimizer/Analysis/Analysis.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
Expand Down Expand Up @@ -61,7 +62,8 @@ static bool isHoistable(AllocStackInst *Inst, irgen::IRGenModule &Mod) {
bool foundWeaklyImported =
SILTy.getASTType().findIf([&Mod](CanType type) -> bool {
if (auto nominal = type->getNominalOrBoundGenericNominal())
if (nominal->isWeakImported(Mod.getSILModule().getSwiftModule())) {
if (nominal->isWeakImported(Mod.getSwiftModule(),
Mod.getAvailabilityContext())) {
return true;
}
return false;
Expand Down
17 changes: 12 additions & 5 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1499,9 +1499,11 @@ void irgen::updateLinkageForDefinition(IRGenModule &IGM,
// TODO: there are probably cases where we can avoid redoing the
// entire linkage computation.
UniversalLinkageInfo linkInfo(IGM);
bool weakImported = entity.isWeakImported(IGM.getSwiftModule(),
IGM.getAvailabilityContext());
auto IRL =
getIRLinkage(linkInfo, entity.getLinkage(ForDefinition),
ForDefinition, entity.isWeakImported(IGM.getSwiftModule()));
ForDefinition, weakImported);
ApplyIRLinkage(IRL).to(global);

// Everything externally visible is considered used in Swift.
Expand All @@ -1516,12 +1518,16 @@ void irgen::updateLinkageForDefinition(IRGenModule &IGM,

LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity,
ForDefinition_t isDefinition) {
return LinkInfo::get(UniversalLinkageInfo(IGM), IGM.getSwiftModule(), entity,
isDefinition);
return LinkInfo::get(UniversalLinkageInfo(IGM),
IGM.getSwiftModule(),
IGM.getAvailabilityContext(),
entity, isDefinition);
}

LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
ModuleDecl *swiftModule, const LinkEntity &entity,
ModuleDecl *swiftModule,
AvailabilityContext availabilityContext,
const LinkEntity &entity,
ForDefinition_t isDefinition) {
LinkInfo result;
// FIXME: For anything in the standard library, we assume is locally defined.
Expand All @@ -1536,8 +1542,9 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
ForDefinition_t(swiftModule->isStdlibModule() || isDefinition);

entity.mangle(result.Name);
bool weakImported = entity.isWeakImported(swiftModule, availabilityContext);
result.IRL = getIRLinkage(linkInfo, entity.getLinkage(isStdlibOrDefinition),
isDefinition, entity.isWeakImported(swiftModule));
isDefinition, weakImported);
result.ForDefinition = isDefinition;
return result;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/IRGen/GenEnum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5429,7 +5429,8 @@ namespace {
llvm::BasicBlock *conditionalBlock = nullptr;
llvm::BasicBlock *afterConditionalBlock = nullptr;
llvm::BasicBlock *beforeNullPtrCheck = nullptr;
if (Case->isWeakImported(IGM.getSwiftModule())) {
if (Case->isWeakImported(IGM.getSwiftModule(),
IGM.getAvailabilityContext())) {
beforeNullPtrCheck = IGF.Builder.GetInsertBlock();
auto address = IGM.getAddrOfEnumCase(Case, NotForDefinition);
conditionalBlock = llvm::BasicBlock::Create(C);
Expand Down
5 changes: 5 additions & 0 deletions lib/IRGen/IRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//
//===----------------------------------------------------------------------===//

#include "swift/AST/Availability.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Module.h"
#include "swift/AST/DiagnosticsIRGen.h"
Expand Down Expand Up @@ -723,6 +724,10 @@ ModuleDecl *IRGenModule::getSwiftModule() const {
return IRGen.SIL.getSwiftModule();
}

AvailabilityContext IRGenModule::getAvailabilityContext() const {
return AvailabilityContext::forDeploymentTarget(Context);
}

Lowering::TypeConverter &IRGenModule::getSILTypes() const {
return IRGen.SIL.Types;
}
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/IRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ class IRGenModule {
const llvm::Triple Triple;
std::unique_ptr<llvm::TargetMachine> TargetMachine;
ModuleDecl *getSwiftModule() const;
AvailabilityContext getAvailabilityContext() const;
Lowering::TypeConverter &getSILTypes() const;
SILModule &getSILModule() const { return IRGen.SIL; }
const IRGenOptions &getOptions() const { return IRGen.Opts; }
Expand Down
22 changes: 13 additions & 9 deletions lib/IRGen/Linking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "IRGenMangler.h"
#include "IRGenModule.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/Availability.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/SIL/SILGlobalVariable.h"
#include "swift/SIL/FormalLinkage.h"
Expand Down Expand Up @@ -888,18 +889,21 @@ Alignment LinkEntity::getAlignment(IRGenModule &IGM) const {
}
}

bool LinkEntity::isWeakImported(ModuleDecl *module) const {
bool LinkEntity::isWeakImported(ModuleDecl *module,
AvailabilityContext context) const {
switch (getKind()) {
case Kind::SILGlobalVariable:
if (getSILGlobalVariable()->getDecl())
return getSILGlobalVariable()->getDecl()->isWeakImported(module);
if (getSILGlobalVariable()->getDecl()) {
return getSILGlobalVariable()->getDecl()
->isWeakImported(module, context);
}
return false;
case Kind::DynamicallyReplaceableFunctionKey:
case Kind::DynamicallyReplaceableFunctionVariable:
case Kind::SILFunction: {
// For imported functions check the Clang declaration.
if (auto clangOwner = getSILFunction()->getClangNodeOwner())
return clangOwner->isWeakImported(module);
return clangOwner->isWeakImported(module, context);

// For native functions check a flag on the SILFunction
// itself.
Expand All @@ -915,16 +919,16 @@ bool LinkEntity::isWeakImported(ModuleDecl *module) const {
// type stored in extra storage area is weak linked.
auto assocConformance = getAssociatedConformance();
auto *depMemTy = assocConformance.first->castTo<DependentMemberType>();
return depMemTy->getAssocType()->isWeakImported(module);
return depMemTy->getAssocType()->isWeakImported(module, context);
}

case Kind::BaseConformanceDescriptor:
return cast<ProtocolDecl>(getDecl())->isWeakImported(module);
return cast<ProtocolDecl>(getDecl())->isWeakImported(module, context);

case Kind::TypeMetadata:
case Kind::TypeMetadataAccessFunction: {
if (auto *nominalDecl = getType()->getAnyNominal())
return nominalDecl->isWeakImported(module);
return nominalDecl->isWeakImported(module, context);
return false;
}

Expand Down Expand Up @@ -952,12 +956,12 @@ bool LinkEntity::isWeakImported(ModuleDecl *module) const {
case Kind::DynamicallyReplaceableFunctionKeyAST:
case Kind::DynamicallyReplaceableFunctionVariableAST:
case Kind::DynamicallyReplaceableFunctionImpl:
return getDecl()->isWeakImported(module);
return getDecl()->isWeakImported(module, context);

case Kind::ProtocolWitnessTable:
case Kind::ProtocolConformanceDescriptor:
return getProtocolConformance()->getRootConformance()
->isWeakImported(module);
->isWeakImported(module, context);

// TODO: Revisit some of the below, for weak conformances.
case Kind::TypeMetadataPattern:
Expand Down
3 changes: 2 additions & 1 deletion lib/SIL/SILFunctionBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

#include "swift/SIL/SILFunctionBuilder.h"
#include "swift/AST/Availability.h"
#include "swift/AST/Decl.h"
using namespace swift;

Expand Down Expand Up @@ -154,7 +155,7 @@ SILFunctionBuilder::getOrCreateFunction(SILLocation loc, SILDeclRef constant,
if (constant.isForeign && decl->hasClangNode())
F->setClangNodeOwner(decl);

if (decl->isWeakImported(/*fromModule=*/nullptr))
if (decl->isWeakImported(mod.getSwiftModule(), availCtx))
F->setWeakLinked();

if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
Expand Down
Loading