Skip to content

Commit cef7ecc

Browse files
committed
Sema: Form all static member partial applications with one closure.
There was a special case here to type-check `T.init` as a single closure `{ args.. in T.init(args..) }`, but really, we can do that for any static member applied to a static metatype base, including operators. Also fix SILGen's function conversion peephole so it looks through `as (T...) -> U` coercions that don't involve bridging.
1 parent 6463d96 commit cef7ecc

File tree

7 files changed

+66
-62
lines changed

7 files changed

+66
-62
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,19 @@ RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e,
18191819
// TODO: Move this up when we can emit closures directly with C calling
18201820
// convention.
18211821
auto subExpr = e->getSubExpr()->getSemanticsProvidingExpr();
1822+
// Look through `as` type ascriptions that don't induce bridging too.
1823+
while (auto subCoerce = dyn_cast<CoerceExpr>(subExpr)) {
1824+
// Coercions that introduce bridging aren't simple type ascriptions.
1825+
// (Maybe we could still peephole through them eventually, though, by
1826+
// performing the bridging in the closure prolog/epilog and/or emitting
1827+
// the closure with the correct contextual block/closure/C function pointer
1828+
// representation.)
1829+
if (!subCoerce->getSubExpr()->getType()->isEqual(subCoerce->getType())) {
1830+
break;
1831+
}
1832+
subExpr = subCoerce->getSubExpr()->getSemanticsProvidingExpr();
1833+
}
1834+
18221835
if ((isa<AbstractClosureExpr>(subExpr) || isa<CaptureListExpr>(subExpr))
18231836
&& canPeepholeLiteralClosureConversion(subExpr->getType(),
18241837
e->getType())) {

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,11 +1745,12 @@ namespace {
17451745
memberLocator);
17461746
} else if (needsCurryThunk) {
17471747
// Another case where we want to build a single closure is when
1748-
// we have a partial application of a constructor on a statically-
1748+
// we have a partial application of a static member on a statically-
17491749
// derived metatype value. Again, there are no order of evaluation
17501750
// concerns here, and keeping the call and base together in the AST
17511751
// improves SILGen.
1752-
if (isa<ConstructorDecl>(member) &&
1752+
if ((isa<ConstructorDecl>(member)
1753+
|| member->isStatic()) &&
17531754
cs.isStaticallyDerivedMetatype(base)) {
17541755
// Add a useless ".self" to avoid downstream diagnostics.
17551756
base = new (context) DotSelfExpr(base, SourceLoc(), base->getEndLoc(),

test/SILGen/cf_members.swift

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,11 @@ public func foo(_ x: Double) {
154154
// CHECK: [[FN:%.*]] = function_ref @IAMStruct1StaticMethod
155155
// CHECK: apply [[FN]]()
156156
var y = Struct1.staticMethod()
157-
// CHECK: [[SELF:%.*]] = metatype
158-
// CHECK: [[THUNK:%.*]] = function_ref @$s10cf_members3fooyySdFs5Int32VycSo10IAMStruct1Vmcfu8_ : $@convention(thin) (@thin Struct1.Type) -> @owned @callee_guaranteed () -> Int32
159-
// CHECK: [[I:%.*]] = apply [[THUNK]]([[SELF]])
160-
// CHECK: [[BORROWED_I:%.*]] = begin_borrow [lexical] [[I]]
161-
// CHECK: [[I_COPY:%.*]] = copy_value [[BORROWED_I]]
162-
// CHECK: [[BORROWED_I2:%.*]] = begin_borrow [[I_COPY]]
157+
// CHECK: [[THUNK:%.*]] = function_ref @$s10cf_members3fooyySdFs5Int32Vycfu8_ : $@convention(thin) () -> Int32
158+
// CHECK: [[I2:%.*]] = thin_to_thick_function [[THUNK]]
163159
let i = Struct1.staticMethod
160+
// CHECK: [[BORROWED_I2:%.*]] = begin_borrow [[I2]]
164161
// CHECK: apply [[BORROWED_I2]]()
165-
// CHECK: destroy_value [[I_COPY]]
166162
y = i()
167163

168164
// TODO: Support @convention(c) references that only capture thin metatype
@@ -250,18 +246,18 @@ public func foo(_ x: Double) {
250246
// CHECK: [[RET:%.*]] = apply [[CFUNC]]([[SELF]], [[X]])
251247
// CHECK: return [[RET]]
252248

253-
// CHECK-LABEL: sil private [ossa] @$s10cf_members3fooyySdFs5Int32VycSo10IAMStruct1Vmcfu8_ADycfu9_ : $@convention(thin) (@thin Struct1.Type) -> Int32 {
254-
// CHECK: bb0([[SELF:%.*]] : $@thin Struct1.Type):
249+
// CHECK-LABEL: sil private [ossa] @$s10cf_members3fooyySdFs5Int32Vycfu8_ : $@convention(thin) () -> Int32
250+
// CHECK: bb0:
255251
// CHECK: [[CFUNC:%.*]] = function_ref @IAMStruct1StaticMethod
256252
// CHECK: [[RET:%.*]] = apply [[CFUNC]]()
257253
// CHECK: return [[RET]]
258254

259-
// CHECK-LABEL:sil private [ossa] @$s10cf_members3fooyySdFySdcSo10IAMStruct1Vcfu10_ySdcfu11_ : $@convention(thin) (Double, Struct1) -> () {
255+
// CHECK-LABEL:sil private [ossa] @$s10cf_members3fooyySdFySdcSo10IAMStruct1Vcfu11_ySdcfu12_ : $@convention(thin) (Double, Struct1) -> () {
260256
// CHECK: bb0([[X:%.*]] : $Double, [[SELF:%.*]] : $Struct1):
261257
// CHECK: [[CFUNC:%.*]] = function_ref @IAMStruct1SelfComesLast
262258
// CHECK: apply [[CFUNC]]([[X]], [[SELF]])
263259

264-
// CHECK-LABEL: sil private [ossa] @$s10cf_members3fooyySdFys5Int32V_SfSdtcSo10IAMStruct1Vcfu14_yAD_SfSdtcfu15_ : $@convention(thin) (Int32, Float, Double, Struct1) -> () {
260+
// CHECK-LABEL: sil private [ossa] @$s10cf_members3fooyySdFys5Int32V_SfSdtcSo10IAMStruct1Vcfu13_yAD_SfSdtcfu14_ : $@convention(thin) (Int32, Float, Double, Struct1) -> () {
265261
// CHECK: bb0([[X:%.*]] : $Int32, [[Y:%.*]] : $Float, [[Z:%.*]] : $Double, [[SELF:%.*]] : $Struct1):
266262
// CHECK: [[CFUNC:%.*]] = function_ref @IAMStruct1SelfComesThird
267263
// CHECK: apply [[CFUNC]]([[X]], [[Y]], [[SELF]], [[Z]])

test/SILGen/closure_literal_reabstraction.swift

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@
22

33
func gen<T, U>(f: (T) throws -> U) {}
44

5+
prefix operator !=<
6+
57
struct Butt {
68
var x: Int
9+
10+
func getX(plus y: Int) -> Int { return x + y }
11+
12+
static func create(x: Int) -> Butt { return Butt(x: x) }
13+
14+
static prefix func !=< (a: Butt) -> Butt { return a }
715
}
816

917
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractCaptureListExprArgument
@@ -25,10 +33,39 @@ func reabstractKeyPathFunctionArgument() {
2533
gen(f: \Butt.x)
2634
}
2735

28-
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractStaticMemberRef
36+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractInitializerRef
2937
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
3038
// CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[CLOSURE_FN]]
3139
// CHECK: apply {{.*}}<Int, Butt>([[CLOSURE]])
32-
func reabstractStaticMemberRef() {
40+
func reabstractInitializerRef() {
3341
gen(f: Butt.init)
3442
}
43+
44+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractInitializerRef
45+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
46+
// CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[CLOSURE_FN]]
47+
// CHECK: apply {{.*}}<Int, Butt>([[CLOSURE]])
48+
func reabstractStaticMemberRef() {
49+
gen(f: Butt.create)
50+
}
51+
52+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractMemberOperatorRef
53+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
54+
// CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[CLOSURE_FN]]
55+
// CHECK: apply {{.*}}<Butt, Butt>([[CLOSURE]])
56+
func reabstractMemberOperatorRef() {
57+
gen(f: !=<)
58+
}
59+
60+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractCoercedMemberOperatorRef
61+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
62+
// CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[CLOSURE_FN]]
63+
// CHECK: apply {{.*}}<Butt, Butt>([[CLOSURE]])
64+
func reabstractCoercedMemberOperatorRef() {
65+
gen(f: (!=<) as (Butt) -> Butt)
66+
}
67+
68+
// TODO
69+
func reabstractInstanceMethodRef(instance: Butt) {
70+
gen(f: instance.getX)
71+
}

test/SILGen/foreign_errors.swift

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -148,22 +148,7 @@ extension NSObject {
148148
}
149149

150150
let fn = ErrorProne.fail
151-
// CHECK-LABEL: sil private [ossa] @$s14foreign_errors2fnyyKcvpfiyyKcSo10ErrorProneCmcfu_ : $@convention(thin) (@thick ErrorProne.Type) -> @owned @callee_guaranteed () -> @error any Error {
152-
// CHECK: [[T0:%.*]] = function_ref @$s14foreign_errors2fnyyKcvpfiyyKcSo10ErrorProneCmcfu_yyKcfu0_ : $@convention(thin) (@thick ErrorProne.Type) -> @error any Error
153-
// CHECK-NEXT: [[T1:%.*]] = partial_apply [callee_guaranteed] [[T0]](%0)
154-
// CHECK-NEXT: return [[T1]]
155-
156-
// CHECK-LABEL: sil private [ossa] @$s14foreign_errors2fnyyKcvpfiyyKcSo10ErrorProneCmcfu_yyKcfu0_ : $@convention(thin) (@thick ErrorProne.Type) -> @error any Error {
157-
// CHECK: [[TEMP:%.*]] = alloc_stack [dynamic_lifetime] $Optional<NSError>
158-
// CHECK: [[SELF:%.*]] = thick_to_objc_metatype %0 : $@thick ErrorProne.Type to $@objc_metatype ErrorProne.Type
159-
// CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $@objc_metatype ErrorProne.Type, #ErrorProne.fail!foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
160-
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]({{%.*}}, [[SELF]])
161-
// CHECK: cond_br
162-
// CHECK: return
163-
// CHECK: [[T0:%.*]] = load [take] [[TEMP]]
164-
// CHECK: [[T1:%.*]] = apply {{%.*}}([[T0]])
165-
// CHECK: "willThrow"([[T1]] : $any Error)
166-
// CHECK: throw [[T1]]
151+
// CHECK-LABEL: sil private [ossa] @$s14foreign_errors2fnyyKcvpfiyyKcfu_ : $@convention(thin) () -> @error any Error
167152

168153
func testArgs() throws {
169154
try ErrorProne.consume(nil)

test/SILGen/partial_apply_operator.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func passGenericOp<T : Group>(_: T) {
2727
// takesGenericUnaryOp(-)
2828
}
2929

30-
// CHECK-LABEL: sil private [ossa] @$s22partial_apply_protocol6passOpyyFS2i_SitcSimcfu_S2i_Sitcfu0_ : $@convention(thin) (Int, Int, @thin Int.Type) -> Int
31-
// CHECK-LABEL: sil private [ossa] @$s22partial_apply_protocol6passOpyyFS2icSimcfu1_S2icfu2_ : $@convention(thin) (Int, @thin Int.Type) -> Int
30+
// CHECK-LABEL: sil private [ossa] @$s22partial_apply_protocol6passOpyyFS2i_Sitcfu_ : $@convention(thin) (Int, Int) -> Int
31+
// CHECK-LABEL: sil private [ossa] @$s22partial_apply_protocol6passOpyyFS2icfu0_ : $@convention(thin) (Int) -> Int
3232

33-
// CHECK-LABEL: sil private [ossa] @$s22partial_apply_protocol13passGenericOpyyxAA5GroupRzlFS2i_SitcSimcfu_S2i_Sitcfu0_ : $@convention(thin) (Int, Int, @thin Int.Type) -> Int
33+
// CHECK-LABEL: sil private [ossa] @$s22partial_apply_protocol13passGenericOpyyxAA5GroupRzlFS2i_Sitcfu_ : $@convention(thin) @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> @out τ_0_2 for <Int, Int, Int>

test/SILOptimizer/dead_partial_apply_arg.swift

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)