diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index 34f8b40f2cc2d..e92f4c57d294f 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -363,6 +363,10 @@ class SILFunction /// The function's serialized attribute. bool Serialized : 1; + /// [serialized_for_package] attribute if package serialization + /// is enabled. + bool SerializedForPackage : 1; + /// Specifies if this function is a thunk or a reabstraction thunk. /// /// The inliner uses this information to avoid inlining (non-trivial) @@ -1138,6 +1142,22 @@ class SILFunction "too few bits for Serialized storage"); } + /// A [serialized_for_package] attribute is used to indicate that a function + /// is [serialized] because of package-cmo optimization. + /// Package-cmo allows serializing a function containing a loadable type in + /// a resiliently built module, which is normally illegal. During SIL deserialization, + /// this attribute can be used to check whether a loaded function that was serialized + /// can be allowed to have loadable types. This attribute is also used to determine + /// if a callee can be inlined into a caller that's serialized without package-cmo, for + /// example, by explicitly annotating the caller decl with `@inlinable`. + IsSerializedForPackage_t isSerializedForPackage() const { + return IsSerializedForPackage_t(SerializedForPackage); + } + void + setSerializedForPackage(IsSerializedForPackage_t isSerializedForPackage) { + SerializedForPackage = isSerializedForPackage; + } + /// Get this function's thunk attribute. IsThunk_t isThunk() const { return IsThunk_t(Thunk); } void setThunk(IsThunk_t isThunk) { diff --git a/include/swift/SIL/SILLinkage.h b/include/swift/SIL/SILLinkage.h index 71cddb79c6b91..f3cf4957d6134 100644 --- a/include/swift/SIL/SILLinkage.h +++ b/include/swift/SIL/SILLinkage.h @@ -162,6 +162,11 @@ enum IsSerialized_t : unsigned char { IsSerialized }; +enum IsSerializedForPackage_t : unsigned char { + IsNotSerializedForPackage, + IsSerializedForPackage +}; + /// The scope in which a subclassable class can be subclassed. enum class SubclassScope : uint8_t { /// This class can be subclassed in other modules. diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 46263924ce01c..64ac3f1e65ac4 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3060,7 +3060,7 @@ bool AbstractStorageDecl::isResilient(ModuleDecl *M, case ResilienceExpansion::Maximal: if (M == getModuleContext()) return false; - // Non-resilient if bypass optimization in package is enabled + // Access non-resiliently if package optimization is enabled if (bypassResilienceInPackage(M)) return false; return isResilient(); @@ -4271,13 +4271,23 @@ bool ValueDecl::hasOpenAccess(const DeclContext *useDC) const { } bool ValueDecl::bypassResilienceInPackage(ModuleDecl *accessingModule) const { - // Client needs to opt in to bypass resilience checks at the use site. - // Client and the loaded module both need to be in the same package. - // The loaded module needs to be built from source and opt in to allow - // non-resilient access. - return getASTContext().LangOpts.EnableBypassResilienceInPackage && - getModuleContext()->inSamePackage(accessingModule) && - getModuleContext()->allowNonResilientAccess(); + auto declModule = getModuleContext(); + if (declModule->inSamePackage(accessingModule) && + declModule->allowNonResilientAccess()) { + // If the defining module is built with package-cmo, + // allow direct access from the use site that belongs + // to accessingModule (client module). + if (declModule->isResilient() && + declModule->serializePackageEnabled()) + return true; + + // If not, check if the client can still opt in to + // have a direct access to this decl from the use + // site with a flag. + // FIXME: serialize this flag to Module and get it via accessingModule. + return getASTContext().LangOpts.EnableBypassResilienceInPackage; + } + return false; } /// Given the formal access level for using \p VD, compute the scope where @@ -5134,7 +5144,7 @@ bool NominalTypeDecl::isResilient(ModuleDecl *M, // non-resiliently in a maximal context. if (M == getModuleContext()) return false; - // Non-resilient if bypass optimization in package is enabled + // Access non-resiliently if package optimization is enabled if (bypassResilienceInPackage(M)) return false; diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index 346c21e44e6e3..e2cc7b35bb4b2 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -460,8 +460,12 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) { case Kind::EnumElement: return Limit::OnDemand; - case Kind::GlobalAccessor: - return cast(d)->isResilient() ? Limit::NeverPublic : Limit::None; + case Kind::GlobalAccessor: { + auto varDecl = cast(d); + return varDecl->isResilient() && + !varDecl->getModuleContext()->allowNonResilientAccess() ? + Limit::NeverPublic : Limit::None; + } case Kind::DefaultArgGenerator: // If the default argument is to be serialized, only use non-ABI public diff --git a/lib/SIL/IR/SILFunction.cpp b/lib/SIL/IR/SILFunction.cpp index b64195f794a33..b0c9cbc749164 100644 --- a/lib/SIL/IR/SILFunction.cpp +++ b/lib/SIL/IR/SILFunction.cpp @@ -251,6 +251,7 @@ void SILFunction::init( this->Bare = isBareSILFunction; this->Transparent = isTrans; this->Serialized = isSerialized; + this->SerializedForPackage = false; this->Thunk = isThunk; this->ClassSubclassScope = unsigned(classSubclassScope); this->GlobalInitFlag = false; @@ -523,12 +524,22 @@ ResilienceExpansion SILFunction::getResilienceExpansion() const { // source and is never used outside of its package; // Even if the module is built resiliently, return // maximal expansion here so aggregate types can be - // loadable in the same resilient domain (from a client - // module in the same package. + // treated as loadable in the same resilient domain + // (across modules in the same package). if (getModule().getSwiftModule()->serializePackageEnabled() && getModule().getSwiftModule()->isResilient()) return ResilienceExpansion::Maximal; + // If a function definition is in another module, and + // it was serialized due to package serialization opt, + // a new attribute [serialized_for_package] is added + // to the definition site. During deserialization, this + // attribute is preserved if the current module is in + // the same package, thus should be in the same resilience + // domain. + if (isSerializedForPackage() == IsSerializedForPackage) + return ResilienceExpansion::Maximal; + return (isSerialized() ? ResilienceExpansion::Minimal : ResilienceExpansion::Maximal); diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index 2a9a97d52994f..75f2b539a150d 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -3341,6 +3341,14 @@ void SILFunction::print(SILPrintContext &PrintCtx) const { case IsSerialized: OS << "[serialized] "; break; } + switch (isSerializedForPackage()) { + case IsNotSerializedForPackage: + break; + case IsSerializedForPackage: + OS << "[serialized_for_package] "; + break; + } + switch (isThunk()) { case IsNotThunk: break; case IsThunk: OS << "[thunk] "; break; @@ -3528,7 +3536,7 @@ void SILGlobalVariable::print(llvm::raw_ostream &OS, bool Verbose) const { if (isSerialized()) OS << "[serialized] "; - + if (isLet()) OS << "[let] "; @@ -3840,7 +3848,7 @@ void SILProperty::print(SILPrintContext &Ctx) const { OS << "sil_property "; if (isSerialized()) OS << "[serialized] "; - + OS << '#'; printValueDecl(getDecl(), OS); if (auto sig = getDecl()->getInnermostDeclContext() @@ -4019,6 +4027,7 @@ void SILVTable::print(llvm::raw_ostream &OS, bool Verbose) const { OS << "sil_vtable "; if (isSerialized()) OS << "[serialized] "; + if (SILType classTy = getClassType()) { OS << classTy; } else { diff --git a/lib/SIL/IR/TypeLowering.cpp b/lib/SIL/IR/TypeLowering.cpp index b9a1ee3edc685..287031086e118 100644 --- a/lib/SIL/IR/TypeLowering.cpp +++ b/lib/SIL/IR/TypeLowering.cpp @@ -2324,31 +2324,34 @@ namespace { if (D->isResilient()) { // If the type is resilient and defined in our module, make a note of // that, since our lowering now depends on the resilience expansion. + // The same should happen if the type was resilient and serialized in + // another module in the same package with package-cmo enabled, which + // treats those modules to be in the same resilience domain. auto declModule = D->getModuleContext(); bool sameModule = (declModule == &TC.M); - if (sameModule) + bool serializedPackage = declModule != &TC.M && + declModule->inSamePackage(&TC.M) && + declModule->isResilient() && + declModule->serializePackageEnabled(); + auto inSameResilienceDomain = sameModule || serializedPackage; + if (inSameResilienceDomain) properties.addSubobject(RecursiveProperties::forResilient()); - // If the type is in a different module, or if we're using a minimal + // If the type is in a different module and not in the same package + // resilience domain (with package-cmo), or if we're using a minimal // expansion, the type is address only and completely opaque to us. - // However, this is not true if the different module is in the same - // package and package serialization is enabled (resilience expansion - // is maximal), e.g. in case of package-cmo. // - // Note: if the type is in a different module, the lowering does - // not depend on the resilience expansion, so we do not need to set - // the isResilient() flag above. - bool serializedPackage = declModule->inSamePackage(&TC.M) && - declModule->isResilient() && - declModule->serializePackageEnabled(); - if ((!sameModule && !serializedPackage) || + // Note: if the type is in a different module and not in the same + // package resilience domain, the lowering does not depend on the + // resilience expansion, so we do not need to set the isResilient() + // flag above. + if (!inSameResilienceDomain || Expansion.getResilienceExpansion() == ResilienceExpansion::Minimal) { properties.addSubobject(RecursiveProperties::forOpaque()); return true; } } - return false; } diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 6c9fbf496fc8d..b8b50433580fd 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -665,7 +665,8 @@ void SILParser::convertRequirements(ArrayRef From, } static bool parseDeclSILOptional( - bool *isTransparent, IsSerialized_t *isSerialized, bool *isCanonical, + bool *isTransparent, IsSerialized_t *isSerialized, + IsSerializedForPackage_t *isSerializedForPackage, bool *isCanonical, bool *hasOwnershipSSA, bool *hasResultDependsOnSelf, IsThunk_t *isThunk, IsDynamicallyReplaceable_t *isDynamic, IsDistributed_t *isDistributed, IsRuntimeAccessible_t *isRuntimeAccessible, @@ -676,10 +677,9 @@ static bool parseDeclSILOptional( SILFunction **usedAdHocRequirementWitness, Identifier *objCReplacementFor, SILFunction::Purpose *specialPurpose, Inline_t *inlineStrategy, OptimizationMode *optimizationMode, PerformanceConstraints *perfConstraints, - bool *isPerformanceConstraint, - bool *markedAsUsed, StringRef *section, bool *isLet, bool *isWeakImported, - bool *needStackProtection, AvailabilityContext *availability, - bool *isWithoutActuallyEscapingThunk, + bool *isPerformanceConstraint, bool *markedAsUsed, StringRef *section, + bool *isLet, bool *isWeakImported, bool *needStackProtection, + AvailabilityContext *availability, bool *isWithoutActuallyEscapingThunk, SmallVectorImpl *Semantics, SmallVectorImpl *SpecAttrs, ValueDecl **ClangDecl, EffectsKind *MRK, SILParser &SP, SILModule &M) { @@ -697,6 +697,9 @@ static bool parseDeclSILOptional( *isTransparent = true; else if (isSerialized && SP.P.Tok.getText() == "serialized") *isSerialized = IsSerialized; + else if (isSerializedForPackage && + SP.P.Tok.getText() == "serialized_for_package") + *isSerializedForPackage = IsSerializedForPackage; else if (isDynamic && SP.P.Tok.getText() == "dynamically_replacable") *isDynamic = IsDynamic; else if (isDistributed && SP.P.Tok.getText() == "distributed") @@ -7106,6 +7109,7 @@ bool SILParserState::parseDeclSIL(Parser &P) { bool isTransparent = false; IsSerialized_t isSerialized = IsNotSerialized; + IsSerializedForPackage_t isSerializedForPackage = IsNotSerializedForPackage; bool isCanonical = false; IsDynamicallyReplaceable_t isDynamic = IsNotDynamic; IsDistributed_t isDistributed = IsNotDistributed; @@ -7138,17 +7142,17 @@ bool SILParserState::parseDeclSIL(Parser &P) { Identifier objCReplacementFor; if (parseSILLinkage(FnLinkage, P) || parseDeclSILOptional( - &isTransparent, &isSerialized, &isCanonical, &hasOwnershipSSA, - &hasResultDependsOnSelf, &isThunk, &isDynamic, &isDistributed, - &isRuntimeAccessible, &forceEnableLexicalLifetimes, + &isTransparent, &isSerialized, &isSerializedForPackage, &isCanonical, + &hasOwnershipSSA, &hasResultDependsOnSelf, &isThunk, &isDynamic, + &isDistributed, &isRuntimeAccessible, &forceEnableLexicalLifetimes, &useStackForPackMetadata, &hasUnsafeNonEscapableResult, &isExactSelfClass, &DynamicallyReplacedFunction, &AdHocWitnessFunction, &objCReplacementFor, &specialPurpose, &inlineStrategy, &optimizationMode, &perfConstr, - &isPerformanceConstraint, &markedAsUsed, - §ion, nullptr, &isWeakImported, &needStackProtection, - &availability, &isWithoutActuallyEscapingThunk, &Semantics, - &SpecAttrs, &ClangDecl, &MRK, FunctionState, M) || + &isPerformanceConstraint, &markedAsUsed, §ion, nullptr, + &isWeakImported, &needStackProtection, &availability, + &isWithoutActuallyEscapingThunk, &Semantics, &SpecAttrs, &ClangDecl, + &MRK, FunctionState, M) || P.parseToken(tok::at_sign, diag::expected_sil_function_name) || P.parseIdentifier(FnName, FnNameLoc, /*diagnoseDollarPrefix=*/false, diag::expected_sil_function_name) || @@ -7173,6 +7177,8 @@ bool SILParserState::parseDeclSIL(Parser &P) { FunctionState.F->setBare(IsBare); FunctionState.F->setTransparent(IsTransparent_t(isTransparent)); FunctionState.F->setSerialized(IsSerialized_t(isSerialized)); + FunctionState.F->setSerializedForPackage( + IsSerializedForPackage_t(isSerializedForPackage)); FunctionState.F->setWasDeserializedCanonical(isCanonical); if (!hasOwnershipSSA) FunctionState.F->setOwnershipEliminated(); @@ -7399,10 +7405,9 @@ bool SILParserState::parseSILGlobal(Parser &P) { parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, &isLet, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, State, M) || + nullptr, &isLet, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, State, M) || P.parseToken(tok::at_sign, diag::expected_sil_value_name) || P.parseIdentifier(GlobalName, NameLoc, /*diagnoseDollarPrefix=*/false, diag::expected_sil_value_name) || @@ -7454,7 +7459,7 @@ bool SILParserState::parseSILProperty(Parser &P) { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, SP, M)) + nullptr, nullptr, nullptr, nullptr, SP, M)) return true; ValueDecl *VD; @@ -7524,7 +7529,7 @@ bool SILParserState::parseSILVTable(Parser &P) { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, VTableState, M)) + nullptr, nullptr, nullptr, nullptr, VTableState, M)) return true; @@ -7647,7 +7652,8 @@ bool SILParserState::parseSILMoveOnlyDeinit(Parser &parser) { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, moveOnlyDeinitTableState, M)) + nullptr, nullptr, nullptr, nullptr, + moveOnlyDeinitTableState, M)) return true; // Parse the class name. @@ -8134,7 +8140,7 @@ bool SILParserState::parseSILWitnessTable(Parser &P) { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, WitnessState, M)) + nullptr, nullptr, nullptr, nullptr, WitnessState, M)) return true; // Parse the protocol conformance. diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 93d17abfa974d..cff0aabacfffa 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -156,12 +156,35 @@ namespace { /// When resilience is bypassed for debugging or package serialization is enabled, /// direct access is legal, but the decls are still resilient. template -bool checkResilience(DeclType *D, ModuleDecl *M, - ResilienceExpansion expansion) { - // Explicitly bypassed for debugging with `bypass-resilience-checks` - if (D->getModuleContext()->getBypassResilience()) +bool checkResilience(DeclType *D, ModuleDecl *accessingModule, + ResilienceExpansion expansion, + bool isSerializedForPackage) { + auto declModule = D->getModuleContext(); + + // For DEBUGGING: this check looks up + // `bypass-resilience-checks`, which is + // an old flag used for debugging, and + // has nothing to do with optimizations. + if (declModule->getBypassResilience()) return false; - return D->isResilient(M, expansion); + + // If the SIL function containing the decl D is + // [serialized_for_package], package-cmo had been + // enabled in its defining module, so direct access + // from a client module should be allowed. + if (accessingModule != declModule && + expansion == ResilienceExpansion::Maximal && + isSerializedForPackage) + return false; + + return D->isResilient(accessingModule, expansion); +} + +template +bool checkResilience(DeclType *D, const SILFunction &f) { + return checkResilience(D, f.getModule().getSwiftModule(), + f.getResilienceExpansion(), + f.isSerializedForPackage()); } bool checkTypeABIAccessible(SILFunction const &F, SILType ty) { @@ -195,6 +218,7 @@ namespace { /// Verify invariants on a key path component. void verifyKeyPathComponent(SILModule &M, TypeExpansionContext typeExpansionContext, + bool isSerializedForPackage, llvm::function_ref require, CanType &baseTy, CanType leafTy, @@ -302,7 +326,8 @@ 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(!checkResilience(property, M.getSwiftModule(), expansion), + require(!checkResilience(property, M.getSwiftModule(), + expansion, isSerializedForPackage), "cannot access storage of resilient property"); auto propertyTy = loweredBaseTy.getFieldType(property, M, typeExpansionContext); @@ -2454,8 +2479,7 @@ class SILVerifier : public SILVerifierBase { void checkAllocGlobalInst(AllocGlobalInst *AGI) { SILGlobalVariable *RefG = AGI->getReferencedGlobal(); if (auto *VD = RefG->getDecl()) { - require(!checkResilience(VD, F.getModule().getSwiftModule(), - F.getResilienceExpansion()), + require(!checkResilience(VD, F), "cannot access storage of resilient global"); } if (F.isSerialized()) { @@ -2475,8 +2499,7 @@ class SILVerifier : public SILVerifierBase { RefG->getLoweredTypeInContext(F.getTypeExpansionContext()), "global_addr/value must be the type of the variable it references"); if (auto *VD = RefG->getDecl()) { - require(!checkResilience(VD, F.getModule().getSwiftModule(), - F.getResilienceExpansion()), + require(!checkResilience(VD, F), "cannot access storage of resilient global"); } if (F.isSerialized()) { @@ -3403,8 +3426,7 @@ class SILVerifier : public SILVerifierBase { require(!structDecl->hasUnreferenceableStorage(), "Cannot build a struct with unreferenceable storage from elements " "using StructInst"); - require(!checkResilience(structDecl, F.getModule().getSwiftModule(), - F.getResilienceExpansion()), + require(!checkResilience(structDecl, F), "cannot access storage of resilient struct"); require(SI->getType().isObject(), "StructInst must produce an object"); @@ -3640,8 +3662,7 @@ class SILVerifier : public SILVerifierBase { auto *cd = DI->getOperand()->getType().getClassOrBoundGenericClass(); require(cd, "Operand of dealloc_ref must be of class type"); - require(!checkResilience(cd, F.getModule().getSwiftModule(), - F.getResilienceExpansion()), + require(!checkResilience(cd, F), "cannot directly deallocate resilient class"); } void checkDeallocPartialRefInst(DeallocPartialRefInst *DPRI) { @@ -3768,8 +3789,7 @@ class SILVerifier : public SILVerifierBase { "result of struct_extract cannot be address"); StructDecl *sd = operandTy.getStructOrBoundGenericStruct(); require(sd, "must struct_extract from struct"); - require(!checkResilience(sd, F.getModule().getSwiftModule(), - F.getResilienceExpansion()), + require(!checkResilience(sd, F), "cannot access storage of resilient struct"); require(!EI->getField()->isStatic(), "cannot get address of static property with struct_element_addr"); @@ -3824,8 +3844,7 @@ class SILVerifier : public SILVerifierBase { "must derive struct_element_addr from address"); StructDecl *sd = operandTy.getStructOrBoundGenericStruct(); require(sd, "struct_element_addr operand must be struct address"); - require(!checkResilience(sd, F.getModule().getSwiftModule(), - F.getResilienceExpansion()), + require(!checkResilience(sd, F), "cannot access storage of resilient struct"); require(EI->getType().isAddress(), "result of struct_element_addr must be address"); @@ -3866,8 +3885,7 @@ class SILVerifier : public SILVerifierBase { SILType operandTy = EI->getOperand()->getType(); ClassDecl *cd = operandTy.getClassOrBoundGenericClass(); require(cd, "ref_element_addr operand must be a class instance"); - require(!checkResilience(cd, F.getModule().getSwiftModule(), - F.getResilienceExpansion()), + require(!checkResilience(cd, F), "cannot access storage of resilient class"); require(EI->getField()->getDeclContext() == @@ -3892,8 +3910,7 @@ class SILVerifier : public SILVerifierBase { SILType operandTy = RTAI->getOperand()->getType(); ClassDecl *cd = operandTy.getClassOrBoundGenericClass(); require(cd, "ref_tail_addr operand must be a class instance"); - require(!checkResilience(cd, F.getModule().getSwiftModule(), - F.getResilienceExpansion()), + require(!checkResilience(cd, F), "cannot access storage of resilient class"); require(cd, "ref_tail_addr operand must be a class instance"); checkAddressWalkerCanVisitAllTransitiveUses(RTAI); @@ -3903,8 +3920,7 @@ class SILVerifier : public SILVerifierBase { SILType operandTy = DSI->getOperand()->getType(); StructDecl *sd = operandTy.getStructOrBoundGenericStruct(); require(sd, "must struct_extract from struct"); - require(!checkResilience(sd, F.getModule().getSwiftModule(), - F.getResilienceExpansion()), + require(!checkResilience(sd, F), "cannot access storage of resilient struct"); if (F.hasOwnership()) { // Make sure that all of our destructure results ownership kinds are @@ -5720,7 +5736,9 @@ class SILVerifier : public SILVerifierBase { break; } - verifyKeyPathComponent(F.getModule(), F.getTypeExpansionContext(), + verifyKeyPathComponent(F.getModule(), + F.getTypeExpansionContext(), + F.isSerializedForPackage(), [&](bool reqt, StringRef message) { _require(reqt, message); }, baseTy, leafTy, @@ -7197,6 +7215,7 @@ void SILProperty::verify(const SILModule &M) const { ResilienceExpansion::Maximal); verifyKeyPathComponent(const_cast(M), typeExpansionContext, + /* isSerializedForPackage */ false, // SILProperty doesn't get serialized require, baseTy, leafTy, diff --git a/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp b/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp index 5597a99b94031..45762034c55b6 100644 --- a/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp +++ b/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp @@ -571,17 +571,37 @@ bool CrossModuleOptimization::shouldSerialize(SILFunction *function) { return true; } +/// Adds [serialized_for_package] attribute to an already [serialized] function. +/// It's used to indicate that a function was [serialized] because of package-cmo. +/// Package-cmo allows serializing a function containing a loadable type in +/// a resiliently built module, which is normally illegal. During SIL deserialization, +/// this attribute can be used to check whether a loaded function that was serialized +/// can be allowed to have loadable types. This attribute is also used to determine +/// if a callee can be inlined into a caller that's serialized without package-cmo, for +/// example, by explicitly annotating the caller decl with `@inlinable`, where +/// the callee was serialized due to package-cmo. +static void addSerializedForPackageAttrIfEnabled(SILFunction *f, + const SILModule &mod) { + assert(f->isSerialized()); + auto shouldSet = mod.getSwiftModule()->serializePackageEnabled() && + mod.getSwiftModule()->isResilient(); + f->setSerializedForPackage(shouldSet ? IsSerializedForPackage + : IsNotSerializedForPackage); +} + /// Serialize \p function and recursively all referenced functions which are /// marked in \p canSerializeFlags. void CrossModuleOptimization::serializeFunction(SILFunction *function, const FunctionFlags &canSerializeFlags) { - if (function->isSerialized()) + if (function->isSerialized()) { + addSerializedForPackageAttrIfEnabled(function, M); return; - + } if (!canSerializeFlags.lookup(function)) return; function->setSerialized(IsSerialized); + addSerializedForPackageAttrIfEnabled(function, M); for (SILBasicBlock &block : *function) { for (SILInstruction &inst : block) { diff --git a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp index 7c7a586724a9c..6ddb982707f8d 100644 --- a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp +++ b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp @@ -857,6 +857,17 @@ SILFunction *swift::getEligibleFunction(FullApplySite AI, return nullptr; } + // If the caller is [serialized] due to explicit `@inlinable` but + // the callee was [serialized_for_package] due to package-cmo, the + // callee is [serialized] and might contain loadable types, which + // is normally disallowed. This check prevents such loadable types + // from being inlined. + if (Caller->isSerialized() && + !Caller->isSerializedForPackage() && + Callee->isSerializedForPackage()) { + return nullptr; + } + // Inlining self-recursive functions into other functions can result // in excessive code duplication since we run the inliner multiple // times in our pipeline diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 499c3b6558a5d..859dddec6cc36 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -563,16 +563,16 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, IdentifierID replacedFunctionID; IdentifierID usedAdHocWitnessFunctionID; GenericSignatureID genericSigID; - unsigned rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutActuallyEscapingThunk, specialPurpose, inlineStrategy, + unsigned rawLinkage, isTransparent, isSerialized, isSerializedForPackage, + isThunk, isWithoutActuallyEscapingThunk, specialPurpose, inlineStrategy, optimizationMode, perfConstr, subclassScope, hasCReferences, effect, numAttrs, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), isDynamic, isExactSelfClass, isDistributed, isRuntimeAccessible, forceEnableLexicalLifetimes; ArrayRef SemanticsIDs; SILFunctionLayout::readRecord( - scratch, rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutActuallyEscapingThunk, specialPurpose, inlineStrategy, + scratch, rawLinkage, isTransparent, isSerialized, isSerializedForPackage, + isThunk, isWithoutActuallyEscapingThunk, specialPurpose, inlineStrategy, optimizationMode, perfConstr, subclassScope, hasCReferences, effect, numAttrs, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), isDynamic, isExactSelfClass, @@ -656,13 +656,26 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, fn->setSerialized(IsSerialized_t(isSerialized)); + // If fn was serialized in a module with package serialization + // enabled, a new attribute [serialized_for_package] was added + // to its definition. Preserve the attribute here if the current + // module is in the same package, and use it to determine the + // resilience expansion for this function. + auto loadedModule = getFile()->getParentModule(); + if (isSerializedForPackage == IsSerializedForPackage && + loadedModule->isResilient() && + loadedModule != SILMod.getSwiftModule() && + loadedModule->serializePackageEnabled() && + loadedModule->inSamePackage(SILMod.getSwiftModule())) + fn->setSerializedForPackage(IsSerializedForPackage); + // If the serialized function comes from the same module, we're merging // modules, and can update the linkage directly. This is needed to // correctly update the linkage for forward declarations to entities defined // in another file of the same module – we want to ensure the linkage // reflects the fact that the entity isn't really external and shouldn't be // dropped from the resulting merged module. - if (getFile()->getParentModule() == SILMod.getSwiftModule()) + if (loadedModule == SILMod.getSwiftModule()) fn->setLinkage(linkage); // Don't override the transparency or linkage of a function with @@ -703,6 +716,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, fn->setLinkage(linkage); fn->setTransparent(IsTransparent_t(isTransparent == 1)); fn->setSerialized(IsSerialized_t(isSerialized)); + fn->setSerializedForPackage(IsSerializedForPackage_t(isSerializedForPackage)); fn->setThunk(IsThunk_t(isThunk)); fn->setWithoutActuallyEscapingThunk(bool(isWithoutActuallyEscapingThunk)); fn->setInlineStrategy(Inline_t(inlineStrategy)); @@ -3520,16 +3534,16 @@ bool SILDeserializer::hasSILFunction(StringRef Name, IdentifierID replacedFunctionID; IdentifierID usedAdHocWitnessFunctionID; GenericSignatureID genericSigID; - unsigned rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutActuallyEscapingThunk, isGlobal, inlineStrategy, + unsigned rawLinkage, isTransparent, isSerialized, isSerializedForPackage, + isThunk, isWithoutActuallyEscapingThunk, isGlobal, inlineStrategy, optimizationMode, perfConstr, subclassScope, hasCReferences, effect, numSpecAttrs, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), isDynamic, isExactSelfClass, isDistributed, isRuntimeAccessible, forceEnableLexicalLifetimes; ArrayRef SemanticsIDs; SILFunctionLayout::readRecord( - scratch, rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutActuallyEscapingThunk, isGlobal, inlineStrategy, + scratch, rawLinkage, isTransparent, isSerialized, isSerializedForPackage, + isThunk, isWithoutActuallyEscapingThunk, isGlobal, inlineStrategy, optimizationMode, perfConstr, subclassScope, hasCReferences, effect, numSpecAttrs, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), isDynamic, isExactSelfClass, @@ -3981,7 +3995,7 @@ SILProperty *SILDeserializer::readProperty(DeclID PId) { DeclID StorageID; ArrayRef ComponentValues; PropertyLayout::readRecord(scratch, StorageID, Serialized, ComponentValues); - + auto decl = cast(MF->getDecl(StorageID)); unsigned ComponentValueIndex = 0; auto component = readKeyPathComponent(ComponentValues, ComponentValueIndex); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 9ec878b7f1580..e496c998e2c46 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 872; // SerializePackageEnabled +const uint16_t SWIFTMODULE_VERSION_MINOR = 873; // [serialized_for_package] for SILFunctionLayout /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h index c2fea45db31cd..8a4d71a67ef61 100644 --- a/lib/Serialization/SILFormat.h +++ b/lib/Serialization/SILFormat.h @@ -292,6 +292,7 @@ namespace sil_block { BCRecordLayout, // transparent BCFixed<1>, // serialized + BCFixed<1>, // serializedForPackage BCFixed<2>, // thunks: signature optimized/reabstraction BCFixed<1>, // without_actually_escaping BCFixed<3>, // specialPurpose diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 8a11019c66073..2a31a3919767c 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -512,7 +512,8 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) { SILFunctionLayout::emitRecord( Out, ScratchRecord, abbrCode, toStableSILLinkage(Linkage), (unsigned)F.isTransparent(), (unsigned)F.isSerialized(), - (unsigned)F.isThunk(), (unsigned)F.isWithoutActuallyEscapingThunk(), + (unsigned)F.isSerializedForPackage(), (unsigned)F.isThunk(), + (unsigned)F.isWithoutActuallyEscapingThunk(), (unsigned)F.getSpecialPurpose(), (unsigned)F.getInlineStrategy(), (unsigned)F.getOptimizationMode(), (unsigned)F.getPerfConstraints(), (unsigned)F.getClassSubclassScope(), (unsigned)F.hasCReferences(), diff --git a/test/SILOptimizer/package-cmo-resilient-mode.swift b/test/SILOptimizer/package-cmo-resilient-mode.swift index a8516d0e98292..e1b7d6a8e2117 100644 --- a/test/SILOptimizer/package-cmo-resilient-mode.swift +++ b/test/SILOptimizer/package-cmo-resilient-mode.swift @@ -10,7 +10,7 @@ // RUN: %target-sil-opt %t/Lib.swiftmodule -sil-verify-all -o %t/Lib-non-res.sil // RUN: %FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-NONRES < %t/Lib-non-res.sil -// RUN: %target-build-swift -module-name=Main -package-name Pkg -I%t -emit-sil %t/main.swift -o %t/Main-non-res.sil +// RUN: %target-build-swift -module-name=Main -package-name Pkg -I%t -emit-sil -O %t/main.swift -o %t/Main-non-res.sil // RUN: %FileCheck %s --check-prefixes=CHECK-MAIN-COMMON,CHECK-MAIN-NONRES < %t/Main-non-res.sil // RUN: rm -rf %t/Lib.swiftmodule @@ -24,7 +24,7 @@ // RUN: %target-sil-opt %t/Lib.swiftmodule -sil-verify-all -o %t/Lib-res.sil // RUN: %FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-RES < %t/Lib-res.sil -// RUN: %target-build-swift -module-name=Main -package-name Pkg -I%t -emit-sil %t/main.swift -o %t/Main-res.sil +// RUN: %target-build-swift -module-name=Main -package-name Pkg -I%t -emit-sil -O %t/main.swift -o %t/Main-res.sil // RUN: %FileCheck %s --check-prefixes=CHECK-MAIN-COMMON,CHECK-MAIN-RES < %t/Main-res.sil // RUN: llvm-bcanalyzer --dump %t/Lib.swiftmodule | %FileCheck %s --check-prefix=CHECK-BC @@ -36,262 +36,297 @@ import Lib -// CHECK-MAIN-COMMON-NOT: s3Lib8PubKlassC4dataSivg -// CHECK-MAIN-COMMON-NOT: s3Lib8PubKlassC4dataSivs -// CHECK-MAIN-COMMON-NOT: s3Lib8PkgKlassC4dataSivg -// CHECK-MAIN-COMMON-NOT: s3Lib8PkgKlassC4dataSivs -// CHECK-MAIN-NONRES-NOT: s3Lib9PubStructV6fooVarSivg -// CHECK-MAIN-NONRES-NOT: s3Lib9PubStructV6fooVarSivs -// CHECK-MAIN-NONRES-NOT: s3Lib9PkgStructV6fooVarSivg -// CHECK-MAIN-NONRES-NOT: s3Lib9PubStructV6fooVarSivs - -// CHECK-MAIN-RES: function_ref @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> @out PubStruct -// CHECK-MAIN-NONRES: function_ref @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> PubStruct - -// CHECK-MAIN-RES: function_ref @$s3Lib9PubStructV6fooVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int -// CHECK-MAIN-NONRES: [[PUB_GET:%.*]] = begin_access [read] [dynamic] {{.*}} : $*PubStruct -// CHECK-MAIN-NONRES: struct_element_addr [[PUB_GET]] : $*PubStruct, #PubStruct.fooVar - -// CHECK-MAIN-RES: function_ref @$s3Lib9PubStructV6fooVarSivs : $@convention(method) (Int, @inout PubStruct) -> () -// CHECK-MAIN-NONRES: [[PUB_MODIFY:%.*]] = begin_access [modify] [dynamic] {{.*}} : $*PubStruct -// CHECK-MAIN-NONRES: struct_element_addr [[PUB_MODIFY]] : $*PubStruct, #PubStruct.fooVar - -// CHECK-MAIN-RES: function_ref @$s3Lib6runPubyyAA0C6StructVF : $@convention(thin) (@in_guaranteed PubStruct) -> () -// CHECK-MAIN-NONRES: function_ref @$s3Lib6runPubyyAA0C6StructVF : $@convention(thin) (PubStruct) -> () - -// CHECK-MAIN-COMMON: function_ref @$s3Lib11FrPubStructVyACSicfC : $@convention(method) (Int, @thin FrPubStruct.Type) -> FrPubStruct -// CHECK-MAIN-COMMON: begin_access [read] [dynamic] {{.*}} : $*FrPubStruct -// CHECK-MAIN-COMMON-NEXT: struct_element_addr {{.*}} : $*FrPubStruct, #FrPubStruct.fooVar -// CHECK-MAIN-COMMON-NEXT: copy_addr -// CHECK-MAIN-COMMON: begin_access [modify] [dynamic] {{.*}} : $*FrPubStruct -// CHECK-MAIN-COMMON-NEXT: struct_element_addr {{.*}} : $*FrPubStruct, #FrPubStruct.fooVar -// CHECK-MAIN-COMMON-NEXT: store -// CHECK-MAIN-COMMON: begin_access [read] [dynamic] {{.*}} : $*FrPubStruct -// CHECK-MAIN-COMMON-NEXT: load -// CHECK-MAIN-COMMON: function_ref @$s3Lib8runFrPubyyAA0cD6StructVF : $@convention(thin) (FrPubStruct) -> () - -// CHECK-MAIN-RES: function_ref @$s3Lib9PkgStructV6fooVarSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int -// CHECK-MAIN-NONRES: [[PKG_GET:%.*]] = begin_access [read] [dynamic] {{.*}} : $*PkgStruct -// CHECK-MAIN-NONRES: struct_element_addr [[PKG_GET]] : $*PkgStruct, #PkgStruct.fooVar - -// CHECK-MAIN-RES: function_ref @$s3Lib9PkgStructV6fooVarSivs : $@convention(method) (Int, @inout PkgStruct) -> () -// CHECK-MAIN-NONRES: [[PKG_MODIFY:%.*]] = begin_access [modify] [dynamic] {{.*}} : $*PkgStruct -// CHECK-MAIN-NONRES: struct_element_addr [[PKG_MODIFY]] : $*PkgStruct, #PkgStruct.fooVar - -// CHECK-MAIN-RES: function_ref @$s3Lib6runPkgyyAA0C6StructVF : $@convention(thin) (@in_guaranteed PkgStruct) -> () -// CHECK-MAIN-NONRES: function_ref @$s3Lib6runPkgyyAA0C6StructVF : $@convention(thin) (PkgStruct) -> () - -// CHECK-MAIN-COMMON: function_ref @$s3Lib8PubKlassCyACSicfC : $@convention(method) (Int, @thick PubKlass.Type) -> @owned PubKlass -// CHECK-MAIN-COMMON: begin_access [read] [dynamic] {{.*}} : $*PubKlass -// CHECK-MAIN-COMMON: class_method {{.*}} : $PubKlass, #PubKlass.data!getter : (PubKlass) -> () -> Int, $@convention(method) (@guaranteed PubKlass) -> Int -// CHECK-MAIN-COMMON: class_method {{.*}} : $PubKlass, #PubKlass.data!setter : (PubKlass) -> (Int) -> (), $@convention(method) (Int, @guaranteed PubKlass) -> () -// CHECK-MAIN-COMMON: function_ref @$s3Lib11runPubKlassyyAA0cD0CF : $@convention(thin) (@guaranteed PubKlass) -> () - -// CHECK-MAIN-COMMON: function_ref @$s3Lib8PkgKlassCyACSicfC : $@convention(method) (Int, @thick PkgKlass.Type) -> @owned PkgKlass -// CHECK-MAIN-COMMON: begin_access [read] [dynamic] {{.*}} : $*PkgKlass -// CHECK-MAIN-COMMON: class_method {{.*}} : $PkgKlass, #PkgKlass.data!getter : (PkgKlass) -> () -> Int, $@convention(method) (@guaranteed PkgKlass) -> Int -// CHECK-MAIN-COMMON: class_method {{.*}} : $PkgKlass, #PkgKlass.data!setter : (PkgKlass) -> (Int) -> (), $@convention(method) (Int, @guaranteed PkgKlass) -> () -// CHECK-MAIN-COMMON: function_ref @$s3Lib11runPkgKlassyyAA0cD0CF : $@convention(thin) (@guaranteed PkgKlass) -> () +// CHECK-MAIN-COMMON-NOT: s3Lib9PubStructVyACSicfC +// CHECK-MAIN-COMMON-NOT: s3Lib9PubStructV6fooVarSivg +// CHECK-MAIN-COMMON-NOT: s3Lib9PubStructV6fooVarSivs +// CHECK-MAIN-COMMON-NOT: s3Lib6runPubySiAA0C6StructVF +// CHECK-MAIN-COMMON-NOT: s3Lib9PkgStructVyACSicfC +// CHECK-MAIN-COMMON-NOT: s3Lib9PkgStructV6fooVarSivg +// CHECK-MAIN-COMMON-NOT: s3Lib9PkgStructV6fooVarSivs +// CHECK-MAIN-COMMON-NOT: s3Lib6runPkgySiAA0C6StructVF + +// CHECK-MAIN-COMMON: [[PUB_INIT:%.*]] = struct $PubStruct +// CHECK-MAIN-COMMON: store [[PUB_INIT]] to {{.*}} : $*PubStruct +// CHECK-MAIN-COMMON: [[PUB_ELEM_ADDR:%.*]] = struct_element_addr {{.*}} : $*PubStruct, #PubStruct.fooVar +// CHECK-MAIN-COMMON: [[PUB_GET:%.*]] = load [[PUB_ELEM_ADDR]] : $*Int +// CHECK-MAIN-COMMON: store [[PUB_GET]] to {{.*}} : $*Int + +// CHECK-MAIN-COMMON: [[FRPUB_INIT:%.*]] = struct $FrPubStruct +// CHECK-MAIN-COMMON: store [[FRPUB_INIT]] to {{.*}} : $*FrPubStruct +// CHECK-MAIN-COMMON: [[FRPUB_ELEM_ADDR:%.*]] = struct_element_addr {{.*}} : $*FrPubStruct, #FrPubStruct.fooVar +// CHECK-MAIN-COMMON: [[FRPUB_GET:%.*]] = load [[FRPUB_ELEM_ADDR]] : $*Int +// CHECK-MAIN-COMMON: store [[FRPUB_GET]] to {{.*}} : $*Int + +// CHECK-MAIN-COMMON: [[PKG_INIT:%.*]] = struct $PkgStruct +// CHECK-MAIN-COMMON: store [[PKG_INIT]] to {{.*}} : $*PkgStruct +// CHECK-MAIN-COMMON: [[PKG_ELEM_ADDR:%.*]] = struct_element_addr {{.*}} : $*PkgStruct, #PkgStruct.fooVar +// CHECK-MAIN-COMMON: [[PKG_GET:%.*]] = load [[PKG_ELEM_ADDR]] : $*Int +// CHECK-MAIN-COMMON: store [[PKG_GET]] to {{.*}} : $*Int + +// CHECK-MAIN-COMMON: [[PUB_ALLOC:%.*]] = alloc_ref $PubKlass +// CHECK-MAIN-COMMON-NEXT: [[PUB_INIT:%.*]] = end_init_let_ref [[PUB_ALLOC]] : $PubKlass +// CHECK-MAIN-COMMON-NEXT: [[PUB_REF_ELEM_ADDR:%.*]] = ref_element_addr [[PUB_INIT]] : $PubKlass, #PubKlass.data +// CHECK-MAIN-COMMON-NEXT: store {{.*}} to [[PUB_REF_ELEM_ADDR]] : $*Int +// CHECK-MAIN-COMMON-NEXT: store [[PUB_INIT]] to {{.*}} : $*PubKlass + +// CHECK-MAIN-COMMON: [[PUBK_GET:%.*]] = load {{.*}} : $*PubKlass +// CHECK-MAIN-COMMON: class_method [[PUBK_GET]] : $PubKlass, #PubKlass.data!getter : (PubKlass) -> () -> Int, $@convention(method) (@guaranteed PubKlass) -> Int +// CHECK-MAIN-COMMON: [[PUBK_SET:%.*]] = load {{.*}} : $*PubKlass +// CHECK-MAIN-COMMON: class_method [[PUBK_SET]] : $PubKlass, #PubKlass.data!setter : (PubKlass) -> (Int) -> (), $@convention(method) (Int, @guaranteed PubKlass) -> () + +// CHECK-MAIN-COMMON: [[PKG_ALLOC:%.*]] = alloc_ref $PkgKlass +// CHECK-MAIN-COMMON-NEXT: [[PKG_INIT:%.*]] = end_init_let_ref [[PKG_ALLOC]] : $PkgKlass +// CHECK-MAIN-COMMON-NEXT: [[PKG_REF_ELEM_ADDR:%.*]] = ref_element_addr [[PKG_INIT]] : $PkgKlass, #PkgKlass.data +// CHECK-MAIN-COMMON-NEXT: store {{.*}} to [[PKG_REF_ELEM_ADDR]] : $*Int +// CHECK-MAIN-COMMON-NEXT: store [[PKG_INIT]] to {{.*}} : $*PkgKlass + +// CHECK-MAIN-COMMON: [[PKGK_GET:%.*]] = load {{.*}} : $*PkgKlass +// CHECK-MAIN-COMMON: class_method [[PKGK_GET]] : $PkgKlass, #PkgKlass.data!getter : (PkgKlass) -> () -> Int, $@convention(method) (@guaranteed PkgKlass) -> Int + +// CHECK-MAIN-COMMON: [[PKGK_SET:%.*]] = load {{.*}} : $*PkgKlass +// CHECK-MAIN-COMMON: class_method [[PKGK_SET]] : $PkgKlass, #PkgKlass.data!setter : (PkgKlass) -> (Int) -> (), $@convention(method) (Int, @guaranteed PkgKlass) -> () + +// CHECK-MAIN-COMMON: [[FNL_PUB_ALLOC:%.*]] = alloc_ref $FinalPubKlass +// CHECK-MAIN-COMMON-NEXT: [[FNL_PUB_INIT:%.*]] = end_init_let_ref [[FNL_PUB_ALLOC]] : $FinalPubKlass +// CHECK-MAIN-COMMON-NEXT: [[FNL_PUB_REF_ELEM_ADDR:%.*]] = ref_element_addr [[FNL_PUB_INIT]] : $FinalPubKlass, #FinalPubKlass.data +// CHECK-MAIN-COMMON-NEXT: store {{.*}} to [[FNL_PUB_REF_ELEM_ADDR]] : $*Int +// CHECK-MAIN-COMMON: store [[FNL_PUB_INIT]] to {{.*}} : $*FinalPubKlass + +// CHECK-MAIN-COMMON: [[FNL_PUB_GET:%.*]] = load {{.*}} : $*FinalPubKlass +// CHECK-MAIN-COMMON: [[FNL_PUB_REF:%.*]] = ref_element_addr [[FNL_PUB_GET]] : $FinalPubKlass, #FinalPubKlass.data +// CHECK-MAIN-COMMON-NEXT: [[FNL_PUB_ACCESS:%.*]] = begin_access {{.*}} [[FNL_PUB_REF]] : $*Int +// CHECK-MAIN-COMMON-NEXT: [[FNL_PUB_LOAD:%.*]] = load [[FNL_PUB_ACCESS]] : $*Int +// CHECK-MAIN-COMMON-NEXT: store [[FNL_PUB_LOAD]] to {{.*}} : $*Int + +// CHECK-MAIN-COMMON: [[FNL_PKG_ALLOC:%.*]] = alloc_ref $FinalPkgKlass +// CHECK-MAIN-COMMON-NEXT: [[FNL_PKG_INIT:%.*]] = end_init_let_ref [[FNL_PKG_ALLOC]] : $FinalPkgKlass +// CHECK-MAIN-COMMON-NEXT: [[FNL_PKG_REF_ELEM_ADDR:%.*]] = ref_element_addr [[FNL_PKG_INIT]] : $FinalPkgKlass, #FinalPkgKlass.data +// CHECK-MAIN-COMMON-NEXT: store {{.*}} to [[FNL_PKG_REF_ELEM_ADDR]] : $*Int +// CHECK-MAIN-COMMON: store [[FNL_PKG_INIT]] to {{.*}} : $*FinalPkgKlass + +// CHECK-MAIN-COMMON: [[FNL_PKG_GET:%.*]] = load {{.*}} : $*FinalPkgKlass +// CHECK-MAIN-COMMON: [[FNL_PKG_REF:%.*]] = ref_element_addr [[FNL_PKG_GET]] : $FinalPkgKlass, #FinalPkgKlass.data +// CHECK-MAIN-COMMON-NEXT: [[FNL_PKG_ACCESS:%.*]] = begin_access {{.*}} [[FNL_PKG_REF]] : $*Int +// CHECK-MAIN-COMMON-NEXT: [[FNL_PKG_LOAD:%.*]] = load [[FNL_PKG_ACCESS]] : $*Int +// CHECK-MAIN-COMMON-NEXT: store [[FNL_PKG_LOAD]] to {{.*}} : $*Int + +// CHECK-MAIN-RES-DAG: sil public_external [serialized_for_package] @$s3Lib8PubKlassCyACSicfC : $@convention(method) (Int, @thick PubKlass.Type) -> @owned PubKlass { +// CHECK-MAIN-NONRES-DAG: sil public_external @$s3Lib8PubKlassCyACSicfC : $@convention(method) (Int, @thick PubKlass.Type) -> @owned PubKlass { + +// CHECK-MAIN-RES-DAG: sil package_external [serialized_for_package] @$s3Lib8PkgKlassCyACSicfC : $@convention(method) (Int, @thick PkgKlass.Type) -> @owned PkgKlass { +// CHECK-MAIN-NONRES-DAG: sil package_external @$s3Lib8PkgKlassCyACSicfC : $@convention(method) (Int, @thick PkgKlass.Type) -> @owned PkgKlass { + +// CHECK-MAIN-RES-DAG: sil public_external [serialized_for_package] @$s3Lib13FinalPubKlassCyACSicfC : $@convention(method) (Int, @thick FinalPubKlass.Type) -> @owned FinalPubKlass { +// CHECK-MAIN-NONRES-DAG: sil public_external @$s3Lib13FinalPubKlassCyACSicfC : $@convention(method) (Int, @thick FinalPubKlass.Type) -> @owned FinalPubKlass { + +// CHECK-MAIN-RES-DAG: sil public_external [serialized_for_package] @$s3Lib8PubKlassC4dataSivs : $@convention(method) (Int, @guaranteed PubKlass) -> () { +// CHECK-MAIN-NONRES-DAG: sil public_external [transparent] @$s3Lib8PubKlassC4dataSivs : $@convention(method) (Int, @guaranteed PubKlass) -> () { + +// CHECK-MAIN-RES-DAG: sil package_external [serialized_for_package] @$s3Lib13FinalPkgKlassCyACSicfC : $@convention(method) (Int, @thick FinalPkgKlass.Type) -> @owned FinalPkgKlass { +// CHECK-MAIN-NONRES-DAG: sil package_external @$s3Lib13FinalPkgKlassCyACSicfC : $@convention(method) (Int, @thick FinalPkgKlass.Type) -> @owned FinalPkgKlass { + +// CHECK-MAIN-RES-DAG: sil package_external [serialized_for_package] @$s3Lib8PkgKlassC4dataSivs : $@convention(method) (Int, @guaranteed PkgKlass) -> () { +// CHECK-MAIN-NONRES-DAG: sil package_external [transparent] @$s3Lib8PkgKlassC4dataSivs : $@convention(method) (Int, @guaranteed PkgKlass) -> () { + +// CHECK-MAIN-COMMON: sil_vtable PubKlass { +// CHECK-MAIN-COMMON: sil_vtable PkgKlass { +// CHECK-MAIN-COMMON: sil_vtable FinalPubKlass { +// CHECK-MAIN-COMMON: sil_vtable FinalPkgKlass { var pub = PubStruct(1) let prevPub = pub.fooVar pub.fooVar = 3 -runPub(pub) -print(prevPub) - -// PubStruct.init(_:) -// CHECK-MAIN-RES: sil @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> @out PubStruct -// CHECK-MAIN-NONRES: sil @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> PubStruct - -// PubStruct.fooVar.getter -// CHECK-MAIN-RES: sil @$s3Lib9PubStructV6fooVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int - -// PubStruct.fooVar.setter -// CHECK-MAIN-RES: sil @$s3Lib9PubStructV6fooVarSivs : $@convention(method) (Int, @inout PubStruct) -> () - -// runPub(_:) -// CHECK-MAIN-RES: sil @$s3Lib6runPubyyAA0C6StructVF : $@convention(thin) (@in_guaranteed PubStruct) -> () -// CHECK-MAIN-NONRES: sil @$s3Lib6runPubyyAA0C6StructVF : $@convention(thin) (PubStruct) -> () +let a = runPub(pub) var frpub = FrPubStruct(1) let prevFrPub = frpub.fooVar frpub.fooVar = 3 -runFrPub(frpub) -print(prevFrPub) - -// FrPubStruct.init(_:) -// CHECK-MAIN-COMMON: sil @$s3Lib11FrPubStructVyACSicfC : $@convention(method) (Int, @thin FrPubStruct.Type) -> FrPubStruct - -// runFrPub(_:) -// CHECK-MAIN-COMMON: sil @$s3Lib8runFrPubyyAA0cD6StructVF : $@convention(thin) (FrPubStruct) -> () +let b = runFrPub(frpub) var pkg = PkgStruct(1) let prevPkg = pkg.fooVar pkg.fooVar = 3 -runPkg(pkg) -print(prevPkg) - -// PkgStruct.init(_:) -// CHECK-MAIN-RES: sil package_external @$s3Lib9PkgStructVyACSicfC : $@convention(method) (Int, @thin PkgStruct.Type) -> @out PkgStruct -// CHECK-MAIN-NONRES: sil package_external @$s3Lib9PkgStructVyACSicfC : $@convention(method) (Int, @thin PkgStruct.Type) -> PkgStruct +let c = runPkg(pkg) -// PkgStruct.fooVar.getter -// CHECK-MAIN-RES: sil package_external @$s3Lib9PkgStructV6fooVarSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int - -// PkgStruct.fooVar.setter -// CHECK-MAIN-RES: sil package_external @$s3Lib9PkgStructV6fooVarSivs : $@convention(method) (Int, @inout PkgStruct) -> () +var pubKlass = PubKlass(5) +let prevPubData = pubKlass.data +pubKlass.data = 7 +let x = runPubKlass(pubKlass) -// runPkg(_:) -// CHECK-MAIN-RES: sil package_external @$s3Lib6runPkgyyAA0C6StructVF : $@convention(thin) (@in_guaranteed PkgStruct) -> () -// CHECK-MAIN-NONRES: sil package_external @$s3Lib6runPkgyyAA0C6StructVF : $@convention(thin) (PkgStruct) -> () +var pkgKlass = PkgKlass(7) +let prevPkgData = pkgKlass.data +pkgKlass.data = 7 +let y = runPkgKlass(pkgKlass) -var pubKlass = PubKlass(2) -let prevPubData = pubKlass.data -pubKlass.data = 5 -runPubKlass(pubKlass) -print(prevPubData) +var fnlPubKlass = FinalPubKlass(9) +let prevPubDataFnl = fnlPubKlass.data +fnlPubKlass.data = 11 -// PubKlass.__allocating_init(_:) -// CHECK-MAIN-COMMON: sil @$s3Lib8PubKlassCyACSicfC : $@convention(method) (Int, @thick PubKlass.Type) -> @owned PubKlass +var fnlPkgKlass = FinalPkgKlass(9) +let prevPkgDataFnl = fnlPkgKlass.data +fnlPkgKlass.data = 11 -// runPubKlass(_:) -// CHECK-MAIN-COMMON: sil @$s3Lib11runPubKlassyyAA0cD0CF : $@convention(thin) (@guaranteed PubKlass) -> () +print(a, b, c, x, y, + prevPub, prevFrPub, prevPkg, prevPubData, + prevPkgData, prevPubDataFnl, prevPkgDataFnl) -var pkgKlass = PkgKlass(2) -let prevPkgData = pkgKlass.data -pkgKlass.data = 5 -runPkgKlass(pkgKlass) -print(prevPkgData) +public func mainPub() { + print(PubStruct(1)) +} -// PkgKlass.__allocating_init(_:) -// CHECK-MAIN-COMMON: sil package_external @$s3Lib8PkgKlassCyACSicfC : $@convention(method) (Int, @thick PkgKlass.Type) -> @owned PkgKlass +@inlinable +public func mainPubInlinable() { + print(PubStruct(2)) +} -// runPkgKlass(_:) -// CHECK-MAIN-COMMON: sil package_external @$s3Lib11runPkgKlassyyAA0cD0CF : $@convention(thin) (@guaranteed PkgKlass) -> () +public func mainPubArgRet(_ arg: PubKlass) -> PubStruct { + return PubStruct(arg.data) +} +@inlinable +public func mainPubArgRetInlinable(_ arg: PubKlass) -> PubStruct { + return PubStruct(arg.data) +} //--- Lib.swift public struct PubStruct { // PubStruct.foovar.getter - // CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV6fooVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib9PubStructV6fooVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV6fooVarSivg : $@convention(method) (PubStruct) -> Int - // CHECK-RES-DAG: [[FIELD:%.*]] = struct_element_addr %0 : $*PubStruct, #PubStruct.fooVar - // CHECK-RES-DAG: load [[FIELD]] : $*Int - // CHECK-NONRES-DAG = struct_extract %0 : $PubStruct, #PubStruct.fooVar + // CHECK-RES-DAG: [[PUB_GET:%.*]] = struct_element_addr {{.*}} : $*PubStruct, #PubStruct.fooVar + // CHECK-RES-DAG: load [[PUB_GET]] : $*Int + // CHECK-NONRES-DAG = struct_extract {{.*}} : $PubStruct, #PubStruct.fooVar // PubStruct.foovar.setter - // CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV6fooVarSivs : $@convention(method) (Int, @inout PubStruct) -> () { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib9PubStructV6fooVarSivs : $@convention(method) (Int, @inout PubStruct) -> () { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV6fooVarSivs : $@convention(method) (Int, @inout PubStruct) -> () { /// NOTE: `struct $PubStruct` in [serialized] function is legal only if package serialization is enabled. - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct $PubStruct - // CHECK-RES-DAG: store [[FIELD]] to {{.*}} : $*PubStruct - // CHECK-NONRES-DAG: store [[FIELD]] to [trivial] {{.*}} : $*PubStruct + // CHECK-COMMON-DAG: [[PUB_SET:%.*]] = struct $PubStruct + // CHECK-RES-DAG: store [[PUB_SET]] to {{.*}} : $*PubStruct + // CHECK-NONRES-DAG: store [[PUB_SET]] to [trivial] {{.*}} : $*PubStruct // PubStruct.foovar.modify - // CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV6fooVarSivM : $@yield_once @convention(method) (@inout PubStruct) -> @yields @inout Int { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib9PubStructV6fooVarSivM : $@yield_once @convention(method) (@inout PubStruct) -> @yields @inout Int { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV6fooVarSivM : $@yield_once @convention(method) (@inout PubStruct) -> @yields @inout Int { - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct_element_addr %0 : $*PubStruct, #PubStruct.fooVar - // CHECK-COMMON-DAG: yield [[FIELD]] + // CHECK-COMMON-DAG: [[PUB_MODIFY:%.*]] = struct_element_addr {{.*}} : $*PubStruct, #PubStruct.fooVar + // CHECK-COMMON-DAG: yield [[PUB_MODIFY]] public var fooVar: Int public init(_ arg: Int) { - // CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> @out PubStruct { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> @out PubStruct { // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> PubStruct { - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct $PubStruct - // CHECK-RES-DAG: store [[FIELD]] to %0 : $*PubStruct - // CHECK-NONRES-DAG: return [[FIELD]] : $PubStruct + // CHECK-COMMON-DAG: [[PUB_INIT:%.*]] = struct $PubStruct + // CHECK-RES-DAG: store [[PUB_INIT]] to {{.*}} : $*PubStruct + // CHECK-NONRES-DAG: return [[PUB_INIT]] : $PubStruct fooVar = arg } - public func f() { - // CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV1fyyF : $@convention(method) (@in_guaranteed PubStruct) -> () { - // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV1fyyF : $@convention(method) (PubStruct) -> () { - print(fooVar) + public func f() -> Int { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib9PubStructV1fSiyF : $@convention(method) (@in_guaranteed PubStruct) -> Int { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV1fSiyF : $@convention(method) (PubStruct) -> Int { + return fooVar > 7 ? fooVar : fooVar + 11 } } -public func runPub(_ arg: PubStruct) { - // CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib6runPubyyAA0C6StructVF : $@convention(thin) (@in_guaranteed PubStruct) -> () { - // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib6runPubyyAA0C6StructVF : $@convention(thin) (PubStruct) -> () { - print(arg) +public func runPub(_ arg: PubStruct) -> Int { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib6runPubySiAA0C6StructVF : $@convention(thin) (@in_guaranteed PubStruct) -> Int { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib6runPubySiAA0C6StructVF : $@convention(thin) (PubStruct) -> Int { + return arg.f() > arg.fooVar ? arg.f() : arg.fooVar +} + +@inlinable +public func runPubInlinable(_ arg: Int) -> PubStruct { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib15runPubInlinableyAA0C6StructVSiF : $@convention(thin) (Int) -> @out PubStruct { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib15runPubInlinableyAA0C6StructVSiF : $@convention(thin) (Int) -> PubStruct { + // CHECK-RES-DAG: alloc_stack [var_decl] $PubStruct + // CHECK-RES-DAG: function_ref @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> @out PubStruct + // CHECK-NONRES-DAG: function_ref @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> PubStruct + var x = PubStruct(1) + x.fooVar = arg > 11 ? arg + 13 : arg + 17 + return x } @frozen public struct FrPubStruct { // FrPubStruct.fooVar.getter - // CHECK-COMMON-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib11FrPubStructV6fooVarSivg : $@convention(method) (FrPubStruct) -> Int { - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct_extract %0 : $FrPubStruct, #FrPubStruct.fooVar - // CHECK-COMMON-DAG: return [[FIELD]] : $Int + // CHECK-RES-DAG: sil [transparent] [serialized] [serialized_for_package] [canonical] [ossa] @$s3Lib11FrPubStructV6fooVarSivg : $@convention(method) (FrPubStruct) -> Int { + // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib11FrPubStructV6fooVarSivg : $@convention(method) (FrPubStruct) -> Int { + // CHECK-COMMON-DAG: [[FR_GET:%.*]] = struct_extract {{.*}} : $FrPubStruct, #FrPubStruct.fooVar + // CHECK-COMMON-DAG: return [[FR_GET]] : $Int // FrPubStruct.fooVar.setter - // CHECK-COMMON-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib11FrPubStructV6fooVarSivs : $@convention(method) (Int, @inout FrPubStruct) -> () { - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct $FrPubStruct - // CHECK-COMMON-DAG: store [[FIELD]] to [trivial] {{.*}} : $*FrPubStruct + // CHECK-RES-DAG: sil [transparent] [serialized] [serialized_for_package] [canonical] [ossa] @$s3Lib11FrPubStructV6fooVarSivs : $@convention(method) (Int, @inout FrPubStruct) -> () { + // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib11FrPubStructV6fooVarSivs : $@convention(method) (Int, @inout FrPubStruct) -> () { + // CHECK-COMMON-DAG: [[FR_SET:%.*]] = struct $FrPubStruct + // CHECK-COMMON-DAG: store [[FR_SET]] to [trivial] {{.*}} : $*FrPubStruct // FrPubStruct.fooVar.modify - // CHECK-COMMON-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib11FrPubStructV6fooVarSivM : $@yield_once @convention(method) (@inout FrPubStruct) -> @yields @inout Int { - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct_element_addr %0 : $*FrPubStruct, #FrPubStruct.fooVar + // CHECK-RES-DAG: sil [transparent] [serialized] [serialized_for_package] [canonical] [ossa] @$s3Lib11FrPubStructV6fooVarSivM : $@yield_once @convention(method) (@inout FrPubStruct) -> @yields @inout Int { + // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib11FrPubStructV6fooVarSivM : $@yield_once @convention(method) (@inout FrPubStruct) -> @yields @inout Int { + // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct_element_addr {{.*}} : $*FrPubStruct, #FrPubStruct.fooVar // CHECK-COMMON-DAG: yield [[FIELD]] public var fooVar: Int public init(_ arg: Int) { - // CHECK-COMMON-DAG: sil [serialized] [canonical] @$s3Lib11FrPubStructVyACSicfC : $@convention(method) (Int, @thin FrPubStruct.Type) -> FrPubStruct { - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct $FrPubStruct - // CHECK-COMMON-DAG: return [[FIELD]] : $FrPubStruct + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib11FrPubStructVyACSicfC : $@convention(method) (Int, @thin FrPubStruct.Type) -> FrPubStruct { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib11FrPubStructVyACSicfC : $@convention(method) (Int, @thin FrPubStruct.Type) -> FrPubStruct { + // CHECK-COMMON-DAG: [[FR_MODIFY:%.*]] = struct $FrPubStruct + // CHECK-COMMON-DAG: return [[FR_MODIFY]] : $FrPubStruct fooVar = arg } - public func f() { - // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib11FrPubStructV1fyyF : $@convention(method) (FrPubStruct) -> () { - print(fooVar) + public func f() -> Int { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib11FrPubStructV1fSiyF : $@convention(method) (FrPubStruct) -> Int { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib11FrPubStructV1fSiyF : $@convention(method) (FrPubStruct) -> Int { + return fooVar > 13 ? fooVar : fooVar + 17 } } -public func runFrPub(_ arg: FrPubStruct) { - // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib8runFrPubyyAA0cD6StructVF : $@convention(thin) (FrPubStruct) -> () { - print(arg) + +public func runFrPub(_ arg: FrPubStruct) -> Int { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib8runFrPubySiAA0cD6StructVF : $@convention(thin) (FrPubStruct) -> Int { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib8runFrPubySiAA0cD6StructVF : $@convention(thin) (FrPubStruct) -> Int { + return arg.f() > arg.fooVar ? arg.f() : arg.fooVar } package struct PkgStruct { // PkgStruct.fooVar.getter - // CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV6fooVarSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib9PkgStructV6fooVarSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int { // CHECK-NONRES-DAG: sil package [transparent] [serialized] [canonical] [ossa] @$s3Lib9PkgStructV6fooVarSivg : $@convention(method) (PkgStruct) -> Int { - // CHECK-RES-DAG: [[FIELD:%.*]] = struct_element_addr %0 : $*PkgStruct, #PkgStruct.fooVar - // CHECK-RES-DAG: load [[FIELD]] : $*Int - // CHECK-NONRES-DAG = struct_extract %0 : $PkgStruct, #PkgStruct.fooVar + // CHECK-COMMON-DAG: [[PKG_GET:%.*]] = struct_element_addr {{.*}} : $*PkgStruct, #PkgStruct.fooVar + // CHECK-RES-DAG: load [[PKG_GET]] : $*Int + // CHECK-NONRES-DAG = struct_extract {{.*}} : $PkgStruct, #PkgStruct.fooVar // PkgStruct.fooVar.setter - // CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV6fooVarSivs : $@convention(method) (Int, @inout PkgStruct) -> () { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib9PkgStructV6fooVarSivs : $@convention(method) (Int, @inout PkgStruct) -> () { // CHECK-NONRES-DAG: sil package [transparent] [serialized] [canonical] [ossa] @$s3Lib9PkgStructV6fooVarSivs : $@convention(method) (Int, @inout PkgStruct) -> () { - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct $PkgStruct - // CHECK-RES-DAG: store [[FIELD]] to {{.*}} : $*PkgStruct - // CHECK-NONRES-DAG: store [[FIELD]] to [trivial] {{.*}} : $*PkgStruct + // CHECK-COMMON-DAG: [[PKG_SET:%.*]] = struct $PkgStruct + // CHECK-RES-DAG: store [[PKG_SET]] to {{.*}} : $*PkgStruct + // CHECK-NONRES-DAG: store [[PKG_SET]] to [trivial] {{.*}} : $*PkgStruct // PkgStruct.fooVar.modify - // CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV6fooVarSivM : $@yield_once @convention(method) (@inout PkgStruct) -> @yields @inout Int { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib9PkgStructV6fooVarSivM : $@yield_once @convention(method) (@inout PkgStruct) -> @yields @inout Int { // CHECK-NONRES-DAG: sil package [transparent] [serialized] [canonical] [ossa] @$s3Lib9PkgStructV6fooVarSivM : $@yield_once @convention(method) (@inout PkgStruct) -> @yields @inout Int { - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct_element_addr %0 : $*PkgStruct, #PkgStruct.fooVar - // CHECK-COMMON-DAG: yield [[FIELD]] package var fooVar: Int package init(_ arg: Int) { - // CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructVyACSicfC : $@convention(method) (Int, @thin PkgStruct.Type) -> @out PkgStruct { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib9PkgStructVyACSicfC : $@convention(method) (Int, @thin PkgStruct.Type) -> @out PkgStruct { // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructVyACSicfC : $@convention(method) (Int, @thin PkgStruct.Type) -> PkgStruct { - // CHECK-COMMON-DAG: [[FIELD:%.*]] = struct $PkgStruct - // CHECK-RES-DAG: store [[FIELD]] to %0 : $*PkgStruct - // CHECK-NONRES-DAG: return [[FIELD]] : $PkgStruct + // CHECK-COMMON-DAG: [[PKG_INIT:%.*]] = struct $PkgStruct + // CHECK-RES-DAG: store [[PKG_INIT]] to {{.*}} : $*PkgStruct + // CHECK-NONRES-DAG: return [[PKG_INIT]] : $PkgStruct fooVar = arg } - package func f() { - // CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV1fyyF : $@convention(method) (@in_guaranteed PkgStruct) -> () { - // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV1fyyF : $@convention(method) (PkgStruct) -> () { - print(fooVar) + package func f() -> Int { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib9PkgStructV1fSiyF : $@convention(method) (@in_guaranteed PkgStruct) -> Int { + // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV1fSiyF : $@convention(method) (PkgStruct) -> Int { + return fooVar > 19 ? fooVar : fooVar + 23 } } -package func runPkg(_ arg: PkgStruct) { - // CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib6runPkgyyAA0C6StructVF : $@convention(thin) (@in_guaranteed PkgStruct) -> () { - // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib6runPkgyyAA0C6StructVF : $@convention(thin) (PkgStruct) -> () { - print(arg) +package func runPkg(_ arg: PkgStruct) -> Int { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib6runPkgySiAA0C6StructVF : $@convention(thin) (@in_guaranteed PkgStruct) -> Int { + // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib6runPkgySiAA0C6StructVF : $@convention(thin) (PkgStruct) -> Int { + return arg.f() > arg.fooVar ? arg.f() : arg.fooVar } public protocol PubProto { @@ -300,33 +335,57 @@ public protocol PubProto { } public class PubKlass: PubProto { - // CHECK-COMMON-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivgTW : $@convention(witness_method: PubProto) (@in_guaranteed PubKlass) -> Int { - // CHECK-COMMON-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivMTW : $@yield_once @convention(witness_method: PubProto) @substituted <τ_0_0> (@inout τ_0_0) -> @yields @inout Int for { - // CHECK-COMMON-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivsTW : $@convention(witness_method: PubProto) (Int, @inout PubKlass) -> () { - // CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassC4dataSivg : $@convention(method) (@guaranteed PubKlass) -> Int + // CHECK-RES-DAG: sil shared [transparent] [serialized] [serialized_for_package] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivgTW : $@convention(witness_method: PubProto) (@in_guaranteed PubKlass) -> Int { + // CHECK-RES-DAG: sil shared [transparent] [serialized] [serialized_for_package] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivMTW : $@yield_once @convention(witness_method: PubProto) @substituted <τ_0_0> (@inout τ_0_0) -> @yields @inout Int for { + // CHECK-RES-DAG: sil shared [transparent] [serialized] [serialized_for_package] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivsTW : $@convention(witness_method: PubProto) (Int, @inout PubKlass) -> () { + // CHECK-NONRES-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivgTW : $@convention(witness_method: PubProto) (@in_guaranteed PubKlass) -> Int { + // CHECK-NONRES-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivMTW : $@yield_once @convention(witness_method: PubProto) @substituted <τ_0_0> (@inout τ_0_0) -> @yields @inout Int for { + // CHECK-NONRES-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivsTW : $@convention(witness_method: PubProto) (Int, @inout PubKlass) -> () { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib8PubKlassC4dataSivg : $@convention(method) (@guaranteed PubKlass) -> Int // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib8PubKlassC4dataSivg : $@convention(method) (@guaranteed PubKlass) -> Int { - // CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassC4dataSivs : $@convention(method) (Int, @guaranteed PubKlass) -> () { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib8PubKlassC4dataSivs : $@convention(method) (Int, @guaranteed PubKlass) -> () { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib8PubKlassC4dataSivs : $@convention(method) (Int, @guaranteed PubKlass) -> () { public var data: Int public init(_ arg: Int = 1) { + // FIXME: default argument 0 of PubKlass.init(_:) gets non_abi so is not considered + // for package serialization, but should it? + // sil non_abi [serialized] [canonical] @$s3Lib8PubKlassCyACSicfcfA_ : $@convention(thin) () -> Int { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib8PubKlassCyACSicfc : $@convention(method) (Int, @owned PubKlass) -> @owned PubKlass { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [exact_self_class] [canonical] @$s3Lib8PubKlassCyACSicfC : $@convention(method) (Int, @thick PubKlass.Type) -> @owned PubKlass { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib8PubKlassCfD : $@convention(method) (@owned PubKlass) -> () { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib8PubKlassCfd : $@convention(method) (@guaranteed PubKlass) -> @owned Builtin.NativeObject { // default argument 0 of PubKlass.init(_:) - // CHECK-COMMON-DAG: sil non_abi [serialized] [canonical] @$s3Lib8PubKlassCyACSicfcfA_ : $@convention(thin) () -> Int { - // CHECK-COMMON-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassCyACSicfc : $@convention(method) (Int, @owned PubKlass) -> @owned PubKlass { - // CHECK-COMMON-DAG: sil [serialized] [exact_self_class] [canonical] @$s3Lib8PubKlassCyACSicfC : $@convention(method) (Int, @thick PubKlass.Type) -> @owned PubKlass { - // CHECK-COMMON-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassCfD : $@convention(method) (@owned PubKlass) -> () { - // CHECK-COMMON-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassCfd : $@convention(method) (@guaranteed PubKlass) -> @owned Builtin.NativeObject { + // CHECK-NONRES-DAG: sil non_abi [serialized] [canonical] @$s3Lib8PubKlassCyACSicfcfA_ : $@convention(thin) () -> Int { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassCyACSicfc : $@convention(method) (Int, @owned PubKlass) -> @owned PubKlass { + // CHECK-NONRES-DAG: sil [serialized] [exact_self_class] [canonical] @$s3Lib8PubKlassCyACSicfC : $@convention(method) (Int, @thick PubKlass.Type) -> @owned PubKlass { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassCfD : $@convention(method) (@owned PubKlass) -> () { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassCfd : $@convention(method) (@guaranteed PubKlass) -> @owned Builtin.NativeObject { self.data = arg } public func pubfunc(_ arg: Int) -> Int { - // CHECK-COMMON-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP7pubfuncyS2iFTW : $@convention(witness_method: PubProto) (Int, @in_guaranteed PubKlass) -> Int { - // CHECK-COMMON-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassC7pubfuncyS2iF : $@convention(method) (Int, @guaranteed PubKlass) -> Int { + // CHECK-RES-DAG: sil shared [transparent] [serialized] [serialized_for_package] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP7pubfuncyS2iFTW : $@convention(witness_method: PubProto) (Int, @in_guaranteed PubKlass) -> Int { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib8PubKlassC7pubfuncyS2iF : $@convention(method) (Int, @guaranteed PubKlass) -> Int { + // CHECK-NONRES-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PubKlassCAA0B5ProtoA2aDP7pubfuncyS2iFTW : $@convention(witness_method: PubProto) (Int, @in_guaranteed PubKlass) -> Int { + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib8PubKlassC7pubfuncyS2iF : $@convention(method) (Int, @guaranteed PubKlass) -> Int { return data + arg } } -public func runPubKlass(_ arg: PubKlass) { - // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib11runPubKlassyyAA0cD0CF : $@convention(thin) (@guaranteed PubKlass) -> () { - print(arg) +public func runPubKlass(_ arg: PubKlass) -> Int { + // CHECK-RES-DAG: sil [serialized] [serialized_for_package] [canonical] @$s3Lib11runPubKlassySiAA0cD0CF : $@convention(thin) (@guaranteed PubKlass) -> Int + // CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib11runPubKlassySiAA0cD0CF : $@convention(thin) (@guaranteed PubKlass) -> Int { + arg.data += 29 + return arg.pubfunc(31) +} + +final public class FinalPubKlass { + public var data = 1 + public init(_ arg: Int) { + data = arg + } + public func fnlPubFunc(_ arg: Int) -> Int { + data + arg + } } package protocol PkgProto { @@ -335,40 +394,62 @@ package protocol PkgProto { } package class PkgKlass: PkgProto { - // CHECK-COMMON-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP4dataSivgTW : $@convention(witness_method: PkgProto) (@in_guaranteed PkgKlass) -> Int { - // CHECK-COMMON-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP4dataSivsTW : $@convention(witness_method: PkgProto) (Int, @inout PkgKlass) -> () { - // CHECK-COMMON-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP4dataSivMTW : $@yield_once @convention(witness_method: PkgProto) @substituted <τ_0_0> (@inout τ_0_0) -> @yields @inout Int for { - // CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassC4dataSivM : $@yield_once @convention(method) (@guaranteed PkgKlass) -> @yields @inout Int { + // CHECK-RES-DAG: sil shared [transparent] [serialized] [serialized_for_package] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP4dataSivgTW : $@convention(witness_method: PkgProto) (@in_guaranteed PkgKlass) -> Int { + // CHECK-RES-DAG: sil shared [transparent] [serialized] [serialized_for_package] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP4dataSivsTW : $@convention(witness_method: PkgProto) (Int, @inout PkgKlass) -> () { + // CHECK-RES-DAG: sil shared [transparent] [serialized] [serialized_for_package] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP4dataSivMTW : $@yield_once @convention(witness_method: PkgProto) @substituted <τ_0_0> (@inout τ_0_0) -> @yields @inout Int for { + // CHECK-NONRES-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP4dataSivgTW : $@convention(witness_method: PkgProto) (@in_guaranteed PkgKlass) -> Int { + // CHECK-NONRES-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP4dataSivsTW : $@convention(witness_method: PkgProto) (Int, @inout PkgKlass) -> () { + // CHECK-NONRES-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP4dataSivMTW : $@yield_once @convention(witness_method: PkgProto) @substituted <τ_0_0> (@inout τ_0_0) -> @yields @inout Int for { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib8PkgKlassC4dataSivM : $@yield_once @convention(method) (@guaranteed PkgKlass) -> @yields @inout Int { // CHECK-NONRES-DAG: sil package [transparent] [serialized] [canonical] [ossa] @$s3Lib8PkgKlassC4dataSivM : $@yield_once @convention(method) (@guaranteed PkgKlass) -> @yields @inout Int { - // CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassC4dataSivg : $@convention(method) (@guaranteed PkgKlass) -> Int { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib8PkgKlassC4dataSivg : $@convention(method) (@guaranteed PkgKlass) -> Int { // CHECK-NONRES-DAG: sil package [transparent] [serialized] [canonical] [ossa] @$s3Lib8PkgKlassC4dataSivg : $@convention(method) (@guaranteed PkgKlass) -> Int { - // CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassC4dataSivs : $@convention(method) (Int, @guaranteed PkgKlass) -> () { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib8PkgKlassC4dataSivs : $@convention(method) (Int, @guaranteed PkgKlass) -> () { // CHECK-NONRES-DAG: sil package [transparent] [serialized] [canonical] [ossa] @$s3Lib8PkgKlassC4dataSivs : $@convention(method) (Int, @guaranteed PkgKlass) -> () { package var data: Int package init(_ arg: Int = 1) { // FIXME: package -> package_non_abi for default argument 0 of PkgKlass.init(_:) - // CHECK-COMMON-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassCyACSicfcfA_ : $@convention(thin) () -> Int { - // CHECK-COMMON-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassCyACSicfc : $@convention(method) (Int, @owned PkgKlass) -> @owned PkgKlass { - // CHECK-COMMON-DAG: sil package [serialized] [exact_self_class] [canonical] @$s3Lib8PkgKlassCyACSicfC : $@convention(method) (Int, @thick PkgKlass.Type) -> @owned PkgKlass { - // CHECK-COMMON-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassCfd : $@convention(method) (@guaranteed PkgKlass) -> @owned Builtin.NativeObject { - // CHECK-COMMON-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassCfD : $@convention(method) (@owned PkgKlass) -> () + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib8PkgKlassCyACSicfcfA_ : $@convention(thin) () -> Int { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib8PkgKlassCyACSicfc : $@convention(method) (Int, @owned PkgKlass) -> @owned PkgKlass { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [exact_self_class] [canonical] @$s3Lib8PkgKlassCyACSicfC : $@convention(method) (Int, @thick PkgKlass.Type) -> @owned PkgKlass { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib8PkgKlassCfd : $@convention(method) (@guaranteed PkgKlass) -> @owned Builtin.NativeObject { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib8PkgKlassCfD : $@convention(method) (@owned PkgKlass) -> () + // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassCyACSicfcfA_ : $@convention(thin) () -> Int { + // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassCyACSicfc : $@convention(method) (Int, @owned PkgKlass) -> @owned PkgKlass { + // CHECK-NONRES-DAG: sil package [serialized] [exact_self_class] [canonical] @$s3Lib8PkgKlassCyACSicfC : $@convention(method) (Int, @thick PkgKlass.Type) -> @owned PkgKlass { + // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassCfd : $@convention(method) (@guaranteed PkgKlass) -> @owned Builtin.NativeObject { + // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassCfD : $@convention(method) (@owned PkgKlass) -> () self.data = arg } package func pkgfunc(_ arg: Int) -> Int { - // CHECK-COMMON-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP7pkgfuncyS2iFTW : $@convention(witness_method: PkgProto) (Int, @in_guaranteed PkgKlass) -> Int { - // CHECK-COMMON-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassC7pkgfuncyS2iF : $@convention(method) (Int, @guaranteed PkgKlass) -> Int { + // CHECK-RES-DAG: sil shared [transparent] [serialized] [serialized_for_package] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP7pkgfuncyS2iFTW : $@convention(witness_method: PkgProto) (Int, @in_guaranteed PkgKlass) -> Int { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib8PkgKlassC7pkgfuncyS2iF : $@convention(method) (Int, @guaranteed PkgKlass) -> Int { + // CHECK-NONRES-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib8PkgKlassCAA0B5ProtoA2aDP7pkgfuncyS2iFTW : $@convention(witness_method: PkgProto) (Int, @in_guaranteed PkgKlass) -> Int { + // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib8PkgKlassC7pkgfuncyS2iF : $@convention(method) (Int, @guaranteed PkgKlass) -> Int { return data + arg } } -package func runPkgKlass(_ arg: PkgKlass) { - // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib11runPkgKlassyyAA0cD0CF : $@convention(thin) (@guaranteed PkgKlass) -> () { - print(arg) +package func runPkgKlass(_ arg: PkgKlass) -> Int { + // CHECK-RES-DAG: sil package [serialized] [serialized_for_package] [canonical] @$s3Lib11runPkgKlassySiAA0cD0CF : $@convention(thin) (@guaranteed PkgKlass) -> Int + // CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib11runPkgKlassySiAA0cD0CF : $@convention(thin) (@guaranteed PkgKlass) -> Int { + arg.data += 37 + return arg.pkgfunc(41) } +final package class FinalPkgKlass { + package var data = 1 + package init(_ arg: Int) { + data = arg + } + package func fnlPkgFunc(_ arg: Int) -> Int { + data + arg + } +} + // CHECK-COMMON-LABEL: sil_vtable [serialized] PubKlass { // CHECK-COMMON-NEXT: #PubKlass.data!getter: (PubKlass) -> () -> Int : @$s3Lib8PubKlassC4dataSivg // CHECK-COMMON-NEXT: #PubKlass.data!setter: (PubKlass) -> (Int) -> () : @$s3Lib8PubKlassC4dataSivs @@ -377,6 +458,10 @@ package func runPkgKlass(_ arg: PkgKlass) { // CHECK-COMMON-NEXT: #PubKlass.pubfunc: (PubKlass) -> (Int) -> Int : @$s3Lib8PubKlassC7pubfuncyS2iF // CHECK-COMMON-NEXT: #PubKlass.deinit!deallocator: @$s3Lib8PubKlassCfD +// CHECK-COMMON-LABEL: sil_vtable [serialized] FinalPubKlass { +// CHECK-COMMON-NEXT: #FinalPubKlass.init!allocator: (FinalPubKlass.Type) -> (Int) -> FinalPubKlass : @$s3Lib13FinalPubKlassCyACSicfC +// CHECK-COMMON-NEXT: #FinalPubKlass.deinit!deallocator: @$s3Lib13FinalPubKlassCfD + // CHECK-COMMON-LABEL: sil_vtable [serialized] PkgKlass { // CHECK-COMMON-NEXT: #PkgKlass.data!getter: (PkgKlass) -> () -> Int : @$s3Lib8PkgKlassC4dataSivg // CHECK-COMMON-NEXT: #PkgKlass.data!setter: (PkgKlass) -> (Int) -> () : @$s3Lib8PkgKlassC4dataSivs @@ -385,6 +470,10 @@ package func runPkgKlass(_ arg: PkgKlass) { // CHECK-COMMON-NEXT: #PkgKlass.pkgfunc: (PkgKlass) -> (Int) -> Int : @$s3Lib8PkgKlassC7pkgfuncyS2iF // CHECK-COMMON-NEXT: #PkgKlass.deinit!deallocator: @$s3Lib8PkgKlassCfD +// CHECK-COMMON-LABEL: sil_vtable [serialized] FinalPkgKlass { +// CHECK-COMMON-NEXT: #FinalPkgKlass.init!allocator: (FinalPkgKlass.Type) -> (Int) -> FinalPkgKlass : @$s3Lib13FinalPkgKlassCyACSicfC +// CHECK-COMMON-NEXT: #FinalPkgKlass.deinit!deallocator: @$s3Lib13FinalPkgKlassCfD + // CHECK-COMMON-LABEL: sil_witness_table [serialized] PubKlass: PubProto module Lib { // CHECK-COMMON-NEXT: method #PubProto.data!getter: (Self) -> () -> Int : @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivgTW // CHECK-COMMON-NEXT: method #PubProto.data!setter: (inout Self) -> (Int) -> () : @$s3Lib8PubKlassCAA0B5ProtoA2aDP4dataSivsTW