diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index a774dae0811..fa404558bfc 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -1234,6 +1234,18 @@ public: llvm::Optional> getSemanticUnavailableAttr() const; + /// Returns true if this declaration should be considered available during + /// SIL/IR lowering. A declaration would not be available during lowering if, + /// for example, it is annotated as unavailable with \c @available and + /// optimization settings require that it be omitted. + bool isAvailableDuringLowering() const; + + /// Returns true if ABI compatibility stubs must be emitted for the given + /// declaration. Decls marked unavailable with \c @available require these + /// stubs if the compiler flags have enabled unavailable declaration ABI + /// compatibility mode. + bool requiresUnavailableDeclABICompatibilityStubs() const; + // List the SPI groups declared with @_spi or inherited by this decl. // // SPI groups are inherited from the parent contexts only if the local decl diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h index 2f3aed40cbc..590c5c38440 100644 --- a/include/swift/SIL/SILModule.h +++ b/include/swift/SIL/SILModule.h @@ -1078,15 +1078,6 @@ namespace Lowering { /// Determine whether the given class will be allocated/deallocated using the /// Objective-C runtime, i.e., +alloc and -dealloc. LLVM_LIBRARY_VISIBILITY bool usesObjCAllocator(ClassDecl *theClass); - -/// Returns true if SIL/IR lowering for the given declaration should be skipped. -/// A declaration may not require lowering if, for example, it is annotated as -/// unavailable and optimization settings allow it to be omitted. -LLVM_LIBRARY_VISIBILITY bool shouldSkipLowering(const Decl *D); - -/// Returns true if SIL/IR lowering for the given declaration should produce -/// a stub that traps at runtime because the code ought to be unreachable. -LLVM_LIBRARY_VISIBILITY bool shouldLowerToUnavailableCodeStub(const Decl *D); } // namespace Lowering /// Apply the given function to each ABI member of \c D skipping the members @@ -1094,7 +1085,7 @@ LLVM_LIBRARY_VISIBILITY bool shouldLowerToUnavailableCodeStub(const Decl *D); template void forEachMemberToLower(IterableDeclContext *D, F &&f) { for (auto *member : D->getABIMembers()) { - if (!Lowering::shouldSkipLowering(member)) + if (member->isAvailableDuringLowering()) f(member); } } diff --git a/lib/AST/Availability.cpp b/lib/AST/Availability.cpp index 38a0732da61..7db4aee6cc6 100644 --- a/lib/AST/Availability.cpp +++ b/lib/AST/Availability.cpp @@ -298,6 +298,33 @@ llvm::Optional Decl::getSemanticUnavailableAttr() const { llvm::None); } +static bool isUnconditionallyUnavailable(const Decl *D) { + if (auto unavailableAttrAndDecl = D->getSemanticUnavailableAttr()) + return unavailableAttrAndDecl->first->isUnconditionallyUnavailable(); + + return false; +} + +bool Decl::isAvailableDuringLowering() const { + // Unconditionally unavailable declarations should be skipped during lowering + // when -unavailable-decl-optimization=complete is specified. + if (getASTContext().LangOpts.UnavailableDeclOptimizationMode != + UnavailableDeclOptimization::Complete) + return true; + + return !isUnconditionallyUnavailable(this); +} + +bool Decl::requiresUnavailableDeclABICompatibilityStubs() const { + // Code associated with unavailable declarations should trap at runtime if + // -unavailable-decl-optimization=stub is specified. + if (getASTContext().LangOpts.UnavailableDeclOptimizationMode != + UnavailableDeclOptimization::Stub) + return false; + + return isUnconditionallyUnavailable(this); +} + bool UnavailabilityReason::requiresDeploymentTargetOrEarlier( ASTContext &Ctx) const { return RequiredDeploymentRange.getLowerEndpoint() <= diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp index 5b034a60a59..d3d0d40e64e 100644 --- a/lib/IRGen/GenClass.cpp +++ b/lib/IRGen/GenClass.cpp @@ -1841,7 +1841,7 @@ namespace { void buildMethod(ConstantArrayBuilder &descriptors, AbstractFunctionDecl *method) { - if (Lowering::shouldSkipLowering(method)) + if (!method->isAvailableDuringLowering()) return; auto accessor = dyn_cast(method); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 36fc6b6b104..532eaeaf46e 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -1563,7 +1563,7 @@ void IRGenerator::noteUseOfTypeGlobals(NominalTypeDecl *type, if (!type) return; - assert(!Lowering::shouldSkipLowering(type)); + assert(type->isAvailableDuringLowering()); // Force emission of ObjC protocol descriptors used by type refs. if (auto proto = dyn_cast(type)) { @@ -2473,7 +2473,7 @@ void swift::irgen::disableAddressSanitizer(IRGenModule &IGM, llvm::GlobalVariabl /// Emit a global declaration. void IRGenModule::emitGlobalDecl(Decl *D) { - if (Lowering::shouldSkipLowering(D)) + if (!D->isAvailableDuringLowering()) return; D->visitAuxiliaryDecls([&](Decl *decl) { @@ -5552,7 +5552,7 @@ static Address getAddrOfSimpleVariable(IRGenModule &IGM, /// The result is always a GlobalValue. Address IRGenModule::getAddrOfFieldOffset(VarDecl *var, ForDefinition_t forDefinition) { - assert(!Lowering::shouldSkipLowering(var)); + assert(var->isAvailableDuringLowering()); LinkEntity entity = LinkEntity::forFieldOffset(var); return getAddrOfSimpleVariable(*this, GlobalVars, entity, @@ -5561,7 +5561,7 @@ Address IRGenModule::getAddrOfFieldOffset(VarDecl *var, Address IRGenModule::getAddrOfEnumCase(EnumElementDecl *Case, ForDefinition_t forDefinition) { - assert(!Lowering::shouldSkipLowering(Case)); + assert(Case->isAvailableDuringLowering()); LinkEntity entity = LinkEntity::forEnumCase(Case); auto addr = getAddrOfSimpleVariable(*this, GlobalVars, entity, forDefinition); @@ -5574,7 +5574,7 @@ Address IRGenModule::getAddrOfEnumCase(EnumElementDecl *Case, void IRGenModule::emitNestedTypeDecls(DeclRange members) { for (Decl *member : members) { - if (Lowering::shouldSkipLowering(member)) + if (!member->isAvailableDuringLowering()) continue; member->visitAuxiliaryDecls([&](Decl *decl) { diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp index 3a7642d3a99..729d5f787b0 100644 --- a/lib/IRGen/GenEnum.cpp +++ b/lib/IRGen/GenEnum.cpp @@ -263,7 +263,7 @@ EnumImplStrategy::getTagIndex(EnumElementDecl *Case) const { static void emitResilientTagIndex(IRGenModule &IGM, const EnumImplStrategy *strategy, EnumElementDecl *Case) { - if (Lowering::shouldSkipLowering(Case)) + if (!Case->isAvailableDuringLowering()) return; auto resilientIdx = strategy->getTagIndex(Case); @@ -6175,7 +6175,7 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) { // For the purposes of memory layout, treat unavailable cases as if they do // not have a payload. - if (Lowering::shouldSkipLowering(elt)) { + if (!elt->isAvailableDuringLowering()) { elementsWithNoPayload.push_back({elt, nullptr, nullptr}); continue; } diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp index 69f9c8fd4a4..450382be265 100644 --- a/lib/IRGen/GenReflection.cpp +++ b/lib/IRGen/GenReflection.cpp @@ -846,9 +846,9 @@ private: if (hasPayload && (decl->isIndirect() || enumDecl->isIndirect())) flags.setIsIndirectCase(); - Type interfaceType = Lowering::shouldSkipLowering(decl) - ? nullptr - : decl->getArgumentInterfaceType(); + Type interfaceType = decl->isAvailableDuringLowering() + ? decl->getArgumentInterfaceType() + : nullptr; addField(flags, interfaceType, decl->getBaseIdentifier().str()); } diff --git a/lib/IRGen/GenStruct.cpp b/lib/IRGen/GenStruct.cpp index e4d96c81aaa..d26650161cc 100644 --- a/lib/IRGen/GenStruct.cpp +++ b/lib/IRGen/GenStruct.cpp @@ -1578,7 +1578,7 @@ void IRGenModule::emitStructDecl(StructDecl *st) { } void IRGenModule::maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *opaque) { - if (Lowering::shouldSkipLowering(opaque)) + if (!opaque->isAvailableDuringLowering()) return; if (IRGen.Opts.EnableAnonymousContextMangledNames) { diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index 9d4523bbfd6..1d864c8b141 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -456,7 +456,7 @@ public: } void noteLazyReemissionOfNominalTypeDescriptor(NominalTypeDecl *decl) { - assert(!Lowering::shouldSkipLowering(decl)); + assert(decl->isAvailableDuringLowering()); LazilyReemittedTypeContextDescriptors.insert(decl); } @@ -466,7 +466,7 @@ public: } void noteUseOfMetadataAccessor(NominalTypeDecl *decl) { - assert(!Lowering::shouldSkipLowering(decl)); + assert(decl->isAvailableDuringLowering()); if (LazyMetadataAccessors.count(decl) == 0) { LazyMetadataAccessors.insert(decl); } diff --git a/lib/IRGen/TBDGen.cpp b/lib/IRGen/TBDGen.cpp index fc5d8618d60..38eecb97153 100644 --- a/lib/IRGen/TBDGen.cpp +++ b/lib/IRGen/TBDGen.cpp @@ -414,7 +414,7 @@ void TBDGenVisitor::addSymbol(StringRef name, SymbolSource source, } bool TBDGenVisitor::willVisitDecl(Decl *D) { - if (Lowering::shouldSkipLowering(D)) + if (!D->isAvailableDuringLowering()) return false; // A @_silgen_name("...") function without a body only exists to diff --git a/lib/SIL/IR/SILModule.cpp b/lib/SIL/IR/SILModule.cpp index ad33e1c2081..c9879163258 100644 --- a/lib/SIL/IR/SILModule.cpp +++ b/lib/SIL/IR/SILModule.cpp @@ -953,30 +953,3 @@ bool Lowering::usesObjCAllocator(ClassDecl *theClass) { // allocation methods because they may have been overridden. return theClass->getObjectModel() == ReferenceCounting::ObjC; } - -static bool isUnconditionallyUnavailable(const Decl *D) { - if (auto unavailableAttrAndDecl = D->getSemanticUnavailableAttr()) - return unavailableAttrAndDecl->first->isUnconditionallyUnavailable(); - - return false; -} - -bool Lowering::shouldSkipLowering(const Decl *D) { - if (D->getASTContext().LangOpts.UnavailableDeclOptimizationMode != - UnavailableDeclOptimization::Complete) - return false; - - // Unavailable declarations should be skipped if - // -unavailable-decl-optimization=complete is specified. - return isUnconditionallyUnavailable(D); -} - -bool Lowering::shouldLowerToUnavailableCodeStub(const Decl *D) { - if (D->getASTContext().LangOpts.UnavailableDeclOptimizationMode != - UnavailableDeclOptimization::Stub) - return false; - - // Unavailable declarations should trap at runtime if - // -unavailable-decl-optimization=stub is specified. - return isUnconditionallyUnavailable(D); -} diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 3072304e5f5..164f3a6db65 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -763,7 +763,7 @@ bool SILGenModule::hasFunction(SILDeclRef constant) { } void SILGenModule::visit(Decl *D) { - if (Lowering::shouldSkipLowering(D)) + if (!D->isAvailableDuringLowering()) return; ASTVisitor::visit(D); diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index aed4d9498d6..34920f3d1a9 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -1553,7 +1553,7 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) { SILDeclRef native = thunk.asForeign(false); if (thunk.hasDecl()) { - if (shouldLowerToUnavailableCodeStub(thunk.getDecl())) + if (thunk.getDecl()->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); } @@ -2068,7 +2068,7 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) { auto nativeFnTy = F.getLoweredFunctionType(); assert(nativeFnTy == nativeCI.SILFnType); - if (shouldLowerToUnavailableCodeStub(fd)) + if (fd->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); // Use the same generic environment as the native entry point. diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index eed3d244e66..922b4e5ea91 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -333,7 +333,7 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, RegularLocation Loc(ctor); Loc.markAutoGenerated(); - if (shouldLowerToUnavailableCodeStub(ctor)) + if (ctor->requiresUnavailableDeclABICompatibilityStubs()) SGF.emitApplyOfUnavailableCodeReached(); AssertingManualScope functionLevelScope(SGF.Cleanups, @@ -612,7 +612,7 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) { bool isDelegating = ctor->getDelegatingOrChainedInitKind().initKind == BodyInitKind::Delegating; - if (shouldLowerToUnavailableCodeStub(ctor)) + if (ctor->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); // Get the 'self' decl and type. @@ -839,7 +839,7 @@ void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) { auto &enumTI = SGM.Types.getTypeLowering(enumTy, TypeExpansionContext::minimal()); - if (shouldLowerToUnavailableCodeStub(element)) + if (element->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); RegularLocation Loc(element); @@ -918,7 +918,7 @@ void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) { SmallVector args; bindParametersForForwarding(ctor->getParameters(), args); - if (shouldLowerToUnavailableCodeStub(ctor)) + if (ctor->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); SILValue selfMetaValue = emitConstructorMetatypeArg(*this, ctor); @@ -1036,7 +1036,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) { assert(ctor->getTypecheckedBody() && "Class constructor without a body?"); - if (shouldLowerToUnavailableCodeStub(ctor)) + if (ctor->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); // True if this constructor delegates to a peer constructor with self.init(). diff --git a/lib/SILGen/SILGenDestructor.cpp b/lib/SILGen/SILGenDestructor.cpp index 9cb8c96d375..cde5b030195 100644 --- a/lib/SILGen/SILGenDestructor.cpp +++ b/lib/SILGen/SILGenDestructor.cpp @@ -35,7 +35,7 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) { if (dd->isImplicit()) Loc.markAutoGenerated(); - if (shouldLowerToUnavailableCodeStub(dd)) + if (dd->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); auto cd = cast(dd->getDeclContext()->getSelfNominalTypeDecl()); @@ -181,7 +181,7 @@ void SILGenFunction::emitDeallocatingClassDestructor(DestructorDecl *dd) { RegularLocation loc(dd); loc.markAutoGenerated(); - if (shouldLowerToUnavailableCodeStub(dd)) + if (dd->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); // Emit the prolog. @@ -239,7 +239,7 @@ void SILGenFunction::emitDeallocatingMoveOnlyDestructor(DestructorDecl *dd) { if (dd->isImplicit()) loc.markAutoGenerated(); - if (shouldLowerToUnavailableCodeStub(dd)) + if (dd->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); // Emit the prolog. @@ -561,7 +561,7 @@ void SILGenFunction::emitObjCDestructor(SILDeclRef dtor) { if (dd->isImplicit()) loc.markAutoGenerated(); - if (shouldLowerToUnavailableCodeStub(dd)) + if (dd->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); SILValue selfValue = emitSelfDeclForDestructor(dd->getImplicitSelfDecl()); diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 8ab7af57ce9..70d937781dd 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -1017,7 +1017,7 @@ void SILGenFunction::emitFunction(FuncDecl *fd) { prepareEpilog(fd->getResultInterfaceType(), fd->hasThrows(), CleanupLocation(fd)); - if (shouldLowerToUnavailableCodeStub(fd)) + if (fd->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); emitProfilerIncrement(fd->getTypecheckedBody()); diff --git a/lib/SILGen/SILGenGlobalVariable.cpp b/lib/SILGen/SILGenGlobalVariable.cpp index f98d7d35761..cc216829697 100644 --- a/lib/SILGen/SILGenGlobalVariable.cpp +++ b/lib/SILGen/SILGenGlobalVariable.cpp @@ -250,7 +250,7 @@ void SILGenFunction::emitLazyGlobalInitializer(PatternBindingDecl *binding, // Add unused context pointer argument required to pass to `Builtin.once` SILBasicBlock &entry = *F.begin(); - if (shouldLowerToUnavailableCodeStub(binding)) + if (binding->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); SILType rawPointerSILTy = @@ -292,7 +292,7 @@ static void emitOnceCall(SILGenFunction &SGF, VarDecl *global, void SILGenFunction::emitGlobalAccessor(VarDecl *global, SILGlobalVariable *onceToken, SILFunction *onceFunc) { - if (shouldLowerToUnavailableCodeStub(global)) + if (global->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); emitOnceCall(*this, global, onceToken, onceFunc); diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index 6ec1119ebe8..8592b56b0a0 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -6025,7 +6025,7 @@ void SILGenFunction::emitProtocolWitness( SmallVector origParams; collectThunkParams(loc, origParams); - if (shouldLowerToUnavailableCodeStub(witness.getDecl())) + if (witness.getDecl()->requiresUnavailableDeclABICompatibilityStubs()) emitApplyOfUnavailableCodeReached(); if (enterIsolation) {