From edc382068be85ebbc4c8c434524af9891fc8d634 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 14 Mar 2019 00:00:38 -0400 Subject: [PATCH 1/2] SIL: Don't drop generic signatures where all parameters are concrete --- lib/AST/ASTContext.cpp | 6 +- lib/IRGen/Callee.h | 4 - lib/IRGen/GenFunc.cpp | 4 +- lib/SIL/SILVerifier.cpp | 2 +- lib/SIL/TypeLowering.cpp | 45 +++++------ lib/SILGen/SILGenType.cpp | 7 -- lib/SILOptimizer/IPO/CapturePromotion.cpp | 5 +- lib/SILOptimizer/IPO/ClosureSpecializer.cpp | 14 ++-- lib/SILOptimizer/Utils/Generics.cpp | 4 +- test/SILGen/capture-canonicalization.swift | 2 +- test/SILGen/conditional_conformance.swift | 2 +- test/SILGen/constrained_extensions.swift | 57 ++++++++----- .../SILGen/keypath_property_descriptors.swift | 10 +++ test/SILGen/subscript_accessor.swift | 2 +- .../closure_specialize_generic.sil | 80 +++++++++++++++++++ 15 files changed, 163 insertions(+), 81 deletions(-) create mode 100644 test/SILOptimizer/closure_specialize_generic.sil diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 36be948287b3b..d6a7799d470f7 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3971,12 +3971,8 @@ SILFunctionType::SILFunctionType(GenericSignature *genericSig, ExtInfo ext, assert(!WitnessMethodConformance && "non-witness_method SIL function with a conformance"); - // Make sure the interface types are sane. + // Make sure the interface types do not contain archetypes or error types. if (genericSig) { - assert(!genericSig->areAllParamsConcrete() && - "If all generic parameters are concrete, SILFunctionType should " - "not have a generic signature at all"); - for (auto gparam : genericSig->getGenericParams()) { (void)gparam; assert(gparam->isCanonical() && "generic signature is not canonicalized"); diff --git a/lib/IRGen/Callee.h b/lib/IRGen/Callee.h index a6e136a988657..f4b57cde0bbb9 100644 --- a/lib/IRGen/Callee.h +++ b/lib/IRGen/Callee.h @@ -157,10 +157,6 @@ namespace irgen { CanSILFunctionType getSubstFunctionType() const { return Info.SubstFnType; } - - bool hasSubstitutions() const { - return Info.Substitutions.hasAnySubstitutableParams(); - } SubstitutionMap getSubstitutions() const { return Info.Substitutions; } diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index f9af57b78bc24..321c9124d4dd1 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -876,9 +876,9 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM, Explosion polyArgs; // Emit the polymorphic arguments. - assert((subs.hasAnySubstitutableParams() + assert((!subs.empty() == hasPolymorphicParameters(origType) || - (!subs.hasAnySubstitutableParams() && origType->getRepresentation() == + (subs.empty() && origType->getRepresentation() == SILFunctionTypeRepresentation::WitnessMethod)) && "should have substitutions iff original function is generic"); WitnessMetadata witnessMetadata; diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp index 7969817ab6451..a6d7535de204e 100644 --- a/lib/SIL/SILVerifier.cpp +++ b/lib/SIL/SILVerifier.cpp @@ -1050,7 +1050,7 @@ class SILVerifier : public SILVerifierBase { auto fnTy = requireObjectType(SILFunctionType, calleeTy, "callee operand"); // If there are substitutions, verify them and apply them to the callee. - if (!subs.hasAnySubstitutableParams()) { + if (subs.empty()) { require(!fnTy->isPolymorphic(), "callee of apply without substitutions must not be polymorphic"); return fnTy; diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp index 76b92c5fd7b3f..afbd1f19c17a7 100644 --- a/lib/SIL/TypeLowering.cpp +++ b/lib/SIL/TypeLowering.cpp @@ -1727,8 +1727,7 @@ getTypeLoweringForExpansion(TypeKey key, } /// Get the type of a global variable accessor function, () -> RawPointer. -static CanAnyFunctionType getGlobalAccessorType(CanType varType) { - ASTContext &C = varType->getASTContext(); +static CanAnyFunctionType getGlobalAccessorType(ASTContext &C) { return CanFunctionType::get({}, C.TheRawPointerType); } @@ -1844,8 +1843,6 @@ TypeConverter::getEffectiveGenericEnvironment(AnyFunctionRef fn, CanGenericSignature TypeConverter::getEffectiveGenericSignature(DeclContext *dc) { if (auto sig = dc->getGenericSignatureOfContext()) { - if (sig->areAllParamsConcrete()) - return nullptr; return sig->getCanonicalSignature(); } @@ -1878,8 +1875,10 @@ TypeConverter::getFunctionInterfaceTypeWithCaptures(CanAnyFunctionType funcType, auto innerExtInfo = AnyFunctionType::ExtInfo(FunctionType::Representation::Thin, funcType->throws()); - return CanAnyFunctionType::get(genericSig, funcType.getParams(), - funcType.getResult(), innerExtInfo); + return CanAnyFunctionType::get(genericSig, + funcType.getParams(), + funcType.getResult(), + innerExtInfo); } CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) { @@ -1889,9 +1888,8 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) { case SILDeclRef::Kind::Func: { if (auto *ACE = c.loc.dyn_cast()) { // FIXME: Closures could have an interface type computed by Sema. - auto funcTy = cast(ACE->getType()->getCanonicalType()); - funcTy = cast( - funcTy->mapTypeOutOfContext() + auto funcTy = cast( + ACE->getType()->mapTypeOutOfContext() ->getCanonicalType()); return getFunctionInterfaceTypeWithCaptures(funcTy, ACE); } @@ -1899,31 +1897,24 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) { FuncDecl *func = cast(vd); auto funcTy = cast( func->getInterfaceType()->getCanonicalType()); + + // Fast path. + if (!func->getDeclContext()->isLocalContext()) + return funcTy; + return getFunctionInterfaceTypeWithCaptures(funcTy, func); } - case SILDeclRef::Kind::EnumElement: { - auto funcTy = cast( - vd->getInterfaceType()->getCanonicalType()); - auto sig = getEffectiveGenericSignature(vd->getDeclContext()); - return CanAnyFunctionType::get(sig, - funcTy->getParams(), - funcTy.getResult(), - funcTy->getExtInfo()); - } - + case SILDeclRef::Kind::EnumElement: case SILDeclRef::Kind::Allocator: { - auto *cd = cast(vd); - auto funcTy = cast( - cd->getInterfaceType()->getCanonicalType()); - return getFunctionInterfaceTypeWithCaptures(funcTy, cd); + return cast( + vd->getInterfaceType()->getCanonicalType()); } case SILDeclRef::Kind::Initializer: { auto *cd = cast(vd); - auto funcTy = cast( - cd->getInitializerInterfaceType()->getCanonicalType()); - return getFunctionInterfaceTypeWithCaptures(funcTy, cd); + return cast( + cd->getInitializerInterfaceType()->getCanonicalType()); } case SILDeclRef::Kind::Destroyer: @@ -1937,7 +1928,7 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) { VarDecl *var = cast(vd); assert(var->hasStorage() && "constant ref to computed global var"); - return getGlobalAccessorType(var->getInterfaceType()->getCanonicalType()); + return getGlobalAccessorType(Context); } case SILDeclRef::Kind::DefaultArgGenerator: return getDefaultArgGeneratorInterfaceType(*this, vd, vd->getDeclContext(), diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index 272344a525d0d..2570ebe3721a5 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -626,13 +626,6 @@ SILFunction *SILGenModule::emitProtocolWitness( reqtOrigTy->substGenericArgs(reqtSubMap) ->getCanonicalType(genericSig)); - // Generic signatures where all parameters are concrete are lowered away - // at the SILFunctionType level. - if (genericSig && genericSig->areAllParamsConcrete()) { - genericSig = nullptr; - genericEnv = nullptr; - } - // Rewrite the conformance in terms of the requirement environment's Self // type, which might have a different generic signature than the type // itself. diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp index f601c6df4c846..ea79a93e9f44f 100644 --- a/lib/SILOptimizer/IPO/CapturePromotion.cpp +++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp @@ -1260,9 +1260,8 @@ processPartialApplyInst(SILOptFunctionBuilder &FuncBuilder, // consideration any captures. auto CalleeFunctionTy = PAI->getCallee()->getType().castTo(); auto SubstCalleeFunctionTy = CalleeFunctionTy; - if (PAI->hasSubstitutions()) - SubstCalleeFunctionTy = - CalleeFunctionTy->substGenericArgs(M, PAI->getSubstitutionMap()); + SubstCalleeFunctionTy = + CalleeFunctionTy->substGenericArgs(M, PAI->getSubstitutionMap()); SILFunctionConventions calleeConv(SubstCalleeFunctionTy, M); auto CalleePInfo = SubstCalleeFunctionTy->getParameters(); SILFunctionConventions paConv(PAI->getType().castTo(), M); diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp index 855835d1f2650..22560acb8e97e 100644 --- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp +++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp @@ -222,7 +222,9 @@ class CallSiteDescriptor { createNewClosure(SILBuilder &B, SILValue V, llvm::SmallVectorImpl &Args) const { if (auto *PA = dyn_cast(getClosure())) - return B.createPartialApply(getClosure()->getLoc(), V, {}, Args, + return B.createPartialApply(getClosure()->getLoc(), V, + PA->getSubstitutionMap(), + Args, getClosure() ->getType() .getAs() @@ -436,8 +438,8 @@ static void rewriteApplyInst(const CallSiteDescriptor &CSDesc, case FullApplySiteKind::TryApplyInst: { auto *TAI = cast(AI); NewAI = Builder.createTryApply(AI.getLoc(), FRI, - SubstitutionMap(), NewArgs, - TAI->getNormalBB(), TAI->getErrorBB()); + TAI->getSubstitutionMap(), + NewArgs, TAI->getNormalBB(), TAI->getErrorBB()); // If we passed in the original closure as @owned, then insert a release // right after NewAI. This is to balance the +1 from being an @owned // argument to AI. @@ -457,7 +459,7 @@ static void rewriteApplyInst(const CallSiteDescriptor &CSDesc, case FullApplySiteKind::ApplyInst: { auto oldApply = cast(AI); auto newApply = Builder.createApply(oldApply->getLoc(), FRI, - SubstitutionMap(), + oldApply->getSubstitutionMap(), NewArgs, oldApply->isNonThrowing()); // If we passed in the original closure as @owned, then insert a release // right after NewAI. This is to balance the +1 from being an @owned @@ -733,7 +735,9 @@ SILValue ClosureSpecCloner::cloneCalleeConversion( auto FunRef = Builder.createFunctionRef(CallSiteDesc.getLoc(), PAI->getReferencedFunction()); auto NewPA = Builder.createPartialApply( - CallSiteDesc.getLoc(), FunRef, {}, {calleeValue}, + CallSiteDesc.getLoc(), FunRef, + PAI->getSubstitutionMap(), + {calleeValue}, PAI->getType().getAs()->getCalleeConvention(), PAI->isOnStack()); // If the partial_apply is on stack we will emit a dealloc_stack in the diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp index 7c6d724890dbd..4f494fd9f550a 100644 --- a/lib/SILOptimizer/Utils/Generics.cpp +++ b/lib/SILOptimizer/Utils/Generics.cpp @@ -731,9 +731,7 @@ ReabstractionInfo::createSubstitutedType(SILFunction *OrigF, SubstitutionMap SubstMap, bool HasUnboundGenericParams) { auto &M = OrigF->getModule(); - if ((SpecializedGenericSig && - SpecializedGenericSig->areAllParamsConcrete()) || - !HasUnboundGenericParams) { + if (!HasUnboundGenericParams) { SpecializedGenericSig = nullptr; SpecializedGenericEnv = nullptr; } diff --git a/test/SILGen/capture-canonicalization.swift b/test/SILGen/capture-canonicalization.swift index b704129a41eaa..cf6e19ea6b122 100644 --- a/test/SILGen/capture-canonicalization.swift +++ b/test/SILGen/capture-canonicalization.swift @@ -5,7 +5,7 @@ struct Bar {} extension Foo where T == Bar { func foo(x: T) -> Bar { - // CHECK-LABEL: sil private [ossa] @{{.*}}3foo{{.*}}4foo2{{.*}} : $@convention(thin) (Bar) -> Bar + // CHECK-LABEL: sil private [ossa] @{{.*}}3foo{{.*}}4foo2{{.*}} : $@convention(thin) (Bar) -> Bar func foo2() -> Bar { return x } diff --git a/test/SILGen/conditional_conformance.swift b/test/SILGen/conditional_conformance.swift index b8e9d2502f023..ee0d45b87b121 100644 --- a/test/SILGen/conditional_conformance.swift +++ b/test/SILGen/conditional_conformance.swift @@ -20,7 +20,7 @@ extension Conformance: P1 where A: P2 { // This is defined below but is emitted before any witness tables. // Just make sure it does not have a generic signature. // -// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s23conditional_conformance16SameTypeConcreteVyxGAA2P1AASiRszlAaEP6normalyyFTW : $@convention(witness_method: P1) (@in_guaranteed SameTypeConcrete) -> () +// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s23conditional_conformance16SameTypeConcreteVyxGAA2P1AASiRszlAaEP6normalyyFTW : $@convention(witness_method: P1) <τ_0_0 where τ_0_0 == Int> (@in_guaranteed SameTypeConcrete) -> () // CHECK-LABEL: sil_witness_table hidden Conformance: P1 module conditional_conformance { diff --git a/test/SILGen/constrained_extensions.swift b/test/SILGen/constrained_extensions.swift index 2f6b4f508243b..0e882cef87a68 100644 --- a/test/SILGen/constrained_extensions.swift +++ b/test/SILGen/constrained_extensions.swift @@ -4,14 +4,14 @@ // RUN: %target-swift-emit-ir -module-name constrained_extensions -primary-file %s > /dev/null extension Array where Element == Int { - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE1xSaySiGyt_tcfC : $@convention(method) (@thin Array.Type) -> @owned Array + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE1xSaySiGyt_tcfC : $@convention(method) (@thin Array.Type) -> @owned Array public init(x: ()) { self.init() } - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE16instancePropertySivg : $@convention(method) (@guaranteed Array) -> Int - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE16instancePropertySivs : $@convention(method) (Int, @inout Array) -> () - // CHECK-LABEL: sil [transparent] [serialized] [ossa] @$sSa22constrained_extensionsSiRszlE16instancePropertySivM : $@yield_once @convention(method) (@inout Array) -> @yields @inout Int + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE16instancePropertySivg : $@convention(method) (@guaranteed Array) -> Int + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE16instancePropertySivs : $@convention(method) (Int, @inout Array) -> () + // CHECK-LABEL: sil [transparent] [serialized] [ossa] @$sSa22constrained_extensionsSiRszlE16instancePropertySivM : $@yield_once @convention(method) (@inout Array) -> @yields @inout Int public var instanceProperty: Element { get { @@ -22,38 +22,38 @@ extension Array where Element == Int { } } - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE14instanceMethodSiyF : $@convention(method) (@guaranteed Array) -> Int + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE14instanceMethodSiyF : $@convention(method) (@guaranteed Array) -> Int public func instanceMethod() -> Element { return instanceProperty } - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE14instanceMethod1eS2i_tF : $@convention(method) (Int, @guaranteed Array) -> Int + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE14instanceMethod1eS2i_tF : $@convention(method) (Int, @guaranteed Array) -> Int public func instanceMethod(e: Element) -> Element { return e } - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE14staticPropertySivgZ : $@convention(method) (@thin Array.Type) -> Int + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE14staticPropertySivgZ : $@convention(method) (@thin Array.Type) -> Int public static var staticProperty: Element { return Array(x: ()).instanceProperty } - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE12staticMethodSiyFZ : $@convention(method) (@thin Array.Type) -> Int + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE12staticMethodSiyFZ : $@convention(method) (@thin Array.Type) -> Int public static func staticMethod() -> Element { return staticProperty } - // CHECK-LABEL: sil non_abi [serialized] [ossa] @$sSa22constrained_extensionsSiRszlE12staticMethod1eS2iSg_tFZfA_ : $@convention(thin) () -> Optional - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE12staticMethod1eS2iSg_tFZ : $@convention(method) (Optional, @thin Array.Type) -> Int + // CHECK-LABEL: sil non_abi [serialized] [ossa] @$sSa22constrained_extensionsSiRszlE12staticMethod1eS2iSg_tFZfA_ : $@convention(thin) () -> Optional + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE12staticMethod1eS2iSg_tFZ : $@convention(method) (Optional, @thin Array.Type) -> Int public static func staticMethod(e: Element? = nil) -> Element { return e! } - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlEySiyt_tcig : $@convention(method) (@guaranteed Array) -> Int + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlEySiyt_tcig : $@convention(method) (@guaranteed Array) -> Int public subscript(i: ()) -> Element { return self[0] } - // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE21inoutAccessOfPropertyyyF : $@convention(method) (@inout Array) -> () + // CHECK-LABEL: sil [ossa] @$sSa22constrained_extensionsSiRszlE21inoutAccessOfPropertyyyF : $@convention(method) (@inout Array) -> () public mutating func inoutAccessOfProperty() { func increment(x: inout Element) { x += 1 @@ -61,6 +61,21 @@ extension Array where Element == Int { increment(x: &instanceProperty) } + + public func closures() { + let a = 3 + + // Does not capture generic signature + _ = { + _ = a + } + + // Captures generic signature + _ = { + _ = a + _ = self[()] + } + } } extension Dictionary where Key == Int { @@ -186,11 +201,11 @@ extension AnythingGoes where T : VeryConstrained { extension Array where Element == Int { struct Nested { - // CHECK-LABEL: sil hidden [transparent] [ossa] @$sSa22constrained_extensionsSiRszlE6NestedV1eSiSgvpfi : $@convention(thin) () -> Optional + // CHECK-LABEL: sil hidden [transparent] [ossa] @$sSa22constrained_extensionsSiRszlE6NestedV1eSiSgvpfi : $@convention(thin) () -> Optional var e: Element? = nil - // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsSiRszlE6NestedV10hasDefault1eySiSg_tFfA_ : $@convention(thin) () -> Optional - // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsSiRszlE6NestedV10hasDefault1eySiSg_tF : $@convention(method) (Optional, @inout Array.Nested) -> () + // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsSiRszlE6NestedV10hasDefault1eySiSg_tFfA_ : $@convention(thin) () -> Optional + // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsSiRszlE6NestedV10hasDefault1eySiSg_tF : $@convention(method) (Optional, @inout Array.Nested) -> () mutating func hasDefault(e: Element? = nil) { self.e = e } @@ -199,17 +214,17 @@ extension Array where Element == Int { extension Array where Element == AnyObject { class NestedClass { - // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE11NestedClassCfd : $@convention(method) (@guaranteed Array.NestedClass) -> @owned Builtin.NativeObject - // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE11NestedClassCfD : $@convention(method) (@owned Array.NestedClass) -> () + // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE11NestedClassCfd : $@convention(method) (@guaranteed Array.NestedClass) -> @owned Builtin.NativeObject + // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE11NestedClassCfD : $@convention(method) (@owned Array.NestedClass) -> () deinit { } - // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE11NestedClassCACyyXl_GycfC : $@convention(method) (@thick Array.NestedClass.Type) -> @owned Array.NestedClass - // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE11NestedClassCACyyXl_Gycfc : $@convention(method) (@owned Array.NestedClass) -> @owned Array.NestedClass + // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE11NestedClassCACyyXl_GycfC : $@convention(method) (@thick Array.NestedClass.Type) -> @owned Array.NestedClass + // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE11NestedClassCACyyXl_Gycfc : $@convention(method) (@owned Array.NestedClass) -> @owned Array.NestedClass } class DerivedClass : NestedClass { - // CHECK-LABEL: sil hidden [transparent] [ossa] @$sSa22constrained_extensionsyXlRszlE12DerivedClassC1eyXlSgvpfi : $@convention(thin) () -> @owned Optional - // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE12DerivedClassCfE : $@convention(method) (@guaranteed Array.DerivedClass) -> () + // CHECK-LABEL: sil hidden [transparent] [ossa] @$sSa22constrained_extensionsyXlRszlE12DerivedClassC1eyXlSgvpfi : $@convention(thin) () -> @owned Optional + // CHECK-LABEL: sil hidden [ossa] @$sSa22constrained_extensionsyXlRszlE12DerivedClassCfE : $@convention(method) (@guaranteed Array.DerivedClass) -> () var e: Element? = nil } diff --git a/test/SILGen/keypath_property_descriptors.swift b/test/SILGen/keypath_property_descriptors.swift index 9aade3215e257..1195d8afbd346 100644 --- a/test/SILGen/keypath_property_descriptors.swift +++ b/test/SILGen/keypath_property_descriptors.swift @@ -131,3 +131,13 @@ public struct FixedLayout { // RESILIENT-LABEL: sil_property #FixedLayout.c (stored_property public var c: Int } + +public struct Generic {} + +extension Generic where T == Int { + public var k: Int { get { } set { } } + + public struct Nested { + public var k: Int = 0 + } +} \ No newline at end of file diff --git a/test/SILGen/subscript_accessor.swift b/test/SILGen/subscript_accessor.swift index 9bb45696d3203..511f3391d63a7 100644 --- a/test/SILGen/subscript_accessor.swift +++ b/test/SILGen/subscript_accessor.swift @@ -23,7 +23,7 @@ extension WillBeConcretelyConstrained where T == Int { } // CHECK-LABEL: sil hidden [transparent] @$s18subscript_accessor27WillBeConcretelyConstrainedVAASiRszlEySiSgSiciM -// CHECK-SAME: $@yield_once @convention(method) (Int, @inout WillBeConcretelyConstrained) -> @yields @inout Optional +// CHECK-SAME: $@yield_once @convention(method) (Int, @inout WillBeConcretelyConstrained) -> @yields @inout Optional // CHECK: sil{{.*}}s18subscript_accessor9testXRead1xxAA1XVyxG_tlF @_specialize(where T == (Int, Int)) diff --git a/test/SILOptimizer/closure_specialize_generic.sil b/test/SILOptimizer/closure_specialize_generic.sil new file mode 100644 index 0000000000000..9f33ca7b11e14 --- /dev/null +++ b/test/SILOptimizer/closure_specialize_generic.sil @@ -0,0 +1,80 @@ +// RUN: %target-sil-opt -enable-sil-verify-all -closure-specialize %s | %FileCheck %s + +import Builtin +import Swift + +// Note: currently only the fully constrained case is implemented. The general case is difficult, +// because both the caller and callee could have different generic signatures. + +sil @$callee : $@convention(thin) (@noescape @callee_guaranteed (Int) -> (), Int) -> () { +bb0(%0 : $@noescape @callee_guaranteed (Int) -> (), %1 : $Int): + %4 = apply %0(%1) : $@noescape @callee_guaranteed (Int) -> () + %5 = tuple () + return %5 : $() +} + +sil private @$closure1 : $@convention(thin) (Int, Int) -> () { +bb0(%0 : $Int, %1 : $Int): + %2 = tuple () + return %2 : $() +} + +sil private @$closure2 : $@convention(thin) (Int) -> () { +bb0(%0 : $Int): + %2 = tuple () + return %2 : $() +} + +sil @$caller1 : $@convention(thin) (Int) -> () { +bb0(%0 : $Int): + %2 = function_ref @$closure1 : $@convention(thin) (Int, Int) -> () + %3 = partial_apply [callee_guaranteed] [on_stack] %2(%0) : $@convention(thin) (Int, Int) -> () + %4 = function_ref @$callee : $@convention(thin) <τ_0_0 where τ_0_0 == Int> (@noescape @callee_guaranteed (Int) -> (), Int) -> () + %5 = apply %4(%3, %0) : $@convention(thin) <τ_0_0 where τ_0_0 == Int> (@noescape @callee_guaranteed (Int) -> (), Int) -> () + dealloc_stack %3 : $@noescape @callee_guaranteed (Int) -> () + %7 = tuple () + return %7 : $() +} + +sil @$caller2 : $@convention(thin) (Int) -> () { +bb0(%0 : $Int): + %2 = function_ref @$closure2 : $@convention(thin) <τ_0_0 where τ_0_0 == String> (Int) -> () + %3 = partial_apply [callee_guaranteed] [on_stack] %2() : $@convention(thin) <τ_0_0 where τ_0_0 == String> (Int) -> () + %4 = function_ref @$callee : $@convention(thin) <τ_0_0 where τ_0_0 == Int> (@noescape @callee_guaranteed (Int) -> (), Int) -> () + %5 = apply %4(%3, %0) : $@convention(thin) <τ_0_0 where τ_0_0 == Int> (@noescape @callee_guaranteed (Int) -> (), Int) -> () + dealloc_stack %3 : $@noescape @callee_guaranteed (Int) -> () + %7 = tuple () + return %7 : $() +} + +sil @$caller3 : $@convention(thin) (Int) -> () { +bb0(%0 : $Int): + %2 = function_ref @$closure1 : $@convention(thin) (Int, Int) -> () + %3 = partial_apply [callee_guaranteed] [on_stack] %2(%0) : $@convention(thin) (Int, Int) -> () + %4 = function_ref @$callee : $@convention(thin) <τ_0_0 where τ_0_0 == Int> (@noescape @callee_guaranteed (Int) -> (), Int) -> () + %5 = apply %4(%3, %0) : $@convention(thin) <τ_0_0 where τ_0_0 == Int> (@noescape @callee_guaranteed (Int) -> (), Int) -> () + dealloc_stack %3 : $@noescape @callee_guaranteed (Int) -> () + %7 = tuple () + return %7 : $() +} + +sil @$caller4 : $@convention(thin) (Int) -> () { +bb0(%0 : $Int): + %2 = function_ref @$closure2 : $@convention(thin) <τ_0_0 where τ_0_0 == String> (Int) -> () + %3 = partial_apply [callee_guaranteed] [on_stack] %2() : $@convention(thin) <τ_0_0 where τ_0_0 == String> (Int) -> () + %4 = function_ref @$callee : $@convention(thin) <τ_0_0 where τ_0_0 == Int> (@noescape @callee_guaranteed (Int) -> (), Int) -> () + %5 = apply %4(%3, %0) : $@convention(thin) <τ_0_0 where τ_0_0 == Int> (@noescape @callee_guaranteed (Int) -> (), Int) -> () + dealloc_stack %3 : $@noescape @callee_guaranteed (Int) -> () + %7 = tuple () + return %7 : $() +} + +// CHECK-LABEL: sil shared @$s7$callee9$closure1SiTf1cn_n : $@convention(thin) (Int, Int) -> () +// CHECK: [[FN:%.*]] = function_ref @$closure1 : $@convention(thin) (Int, Int) -> () +// CHECK: partial_apply [callee_guaranteed] [on_stack] [[FN]](%1) +// CHECK: return + +// CHECK-LABEL: sil shared @$s7$callee9$closure2Tf1cn_n : $@convention(thin) (Int) -> () +// CHECK: [[FN:%.*]] = function_ref @$closure2 : $@convention(thin) <τ_0_0 where τ_0_0 == String> (Int) -> () +// CHECK: partial_apply [callee_guaranteed] [on_stack] [[FN]]() +// CHECK: return From d7a04251cb269310d55c1628c1cbbd988bc7787a Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 14 Mar 2019 00:27:00 -0400 Subject: [PATCH 2/2] SIL: Remove obsolete SIL printer FIXME --- lib/SIL/SILPrinter.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp index c353d48f44f8c..8e35008918fac 100644 --- a/lib/SIL/SILPrinter.cpp +++ b/lib/SIL/SILPrinter.cpp @@ -1056,17 +1056,12 @@ class SILPrinter : public SILInstructionVisitor { printDebugVar(ABI->getVarInfo()); } - void printSubstitutions(SubstitutionMap Subs, - GenericSignature *Sig = nullptr) { - if (!Subs.hasAnySubstitutableParams()) return; - - // FIXME: This is a hack to cope with cases where the substitution map uses - // a generic signature that's close-to-but-not-the-same-as expected. - auto genericSig = Sig ? Sig : Subs.getGenericSignature(); + void printSubstitutions(SubstitutionMap Subs) { + if (Subs.empty()) return; *this << '<'; bool first = true; - for (auto gp : genericSig->getGenericParams()) { + for (auto gp : Subs.getGenericSignature()->getGenericParams()) { if (first) first = false; else *this << ", "; @@ -1078,8 +1073,7 @@ class SILPrinter : public SILInstructionVisitor { template void visitApplyInstBase(Inst *AI) { *this << Ctx.getID(AI->getCallee()); - printSubstitutions(AI->getSubstitutionMap(), - AI->getOrigCalleeType()->getGenericSignature()); + printSubstitutions(AI->getSubstitutionMap()); *this << '('; interleave(AI->getArguments(), [&](const SILValue &arg) { *this << Ctx.getID(arg); },