1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
// RUN: %target-swift-emit-silgen -Xllvm -sil-full-demangle %s | %FileCheck %s
struct Foo {
mutating // used to test writeback.
func foo() {}
subscript(x: Int) -> Foo {
get {
return Foo()
}
set {}
}
}
var x: Foo {
get {
return Foo()
}
set {}
}
var y: Foo {
get {
return Foo()
}
set {}
}
var z: Foo {
get {
return Foo()
}
set {}
}
var readonly: Foo {
get {
return Foo()
}
}
func bar(x x: inout Foo) {}
// Writeback to value type 'self' argument
x.foo()
// CHECK: [[X_TEMP:%.*]] = alloc_stack $Foo
// CHECK: [[GET_X:%.*]] = function_ref @$s9writeback1xAA3FooVvg : $@convention(thin) () -> Foo
// CHECK: [[X:%.*]] = apply [[GET_X]]() : $@convention(thin) () -> Foo
// CHECK: store [[X]] to [trivial] [[X_TEMP]]
// CHECK: [[FOO:%.*]] = function_ref @$s9writeback3FooV3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout Foo) -> ()
// CHECK: apply [[FOO]]([[X_TEMP]]) : $@convention(method) (@inout Foo) -> ()
// CHECK: [[X1:%.*]] = load [trivial] [[X_TEMP]] : $*Foo
// CHECK: [[SET_X:%.*]] = function_ref @$s9writeback1xAA3FooVvs : $@convention(thin) (Foo) -> ()
// CHECK: apply [[SET_X]]([[X1]]) : $@convention(thin) (Foo) -> ()
// CHECK: dealloc_stack [[X_TEMP]] : $*Foo
// Writeback to inout argument
bar(x: &x)
// CHECK: [[X_TEMP:%.*]] = alloc_stack $Foo
// CHECK: [[GET_X:%.*]] = function_ref @$s9writeback1xAA3FooVvg : $@convention(thin) () -> Foo
// CHECK: [[X:%.*]] = apply [[GET_X]]() : $@convention(thin) () -> Foo
// CHECK: store [[X]] to [trivial] [[X_TEMP]] : $*Foo
// CHECK: [[BAR:%.*]] = function_ref @$s9writeback3bar1xyAA3FooVz_tF : $@convention(thin) (@inout Foo) -> ()
// CHECK: apply [[BAR]]([[X_TEMP]]) : $@convention(thin) (@inout Foo) -> ()
// CHECK: [[X1:%.*]] = load [trivial] [[X_TEMP]] : $*Foo
// CHECK: [[SET_X:%.*]] = function_ref @$s9writeback1xAA3FooVvs : $@convention(thin) (Foo) -> ()
// CHECK: apply [[SET_X]]([[X1]]) : $@convention(thin) (Foo) -> ()
// CHECK: dealloc_stack [[X_TEMP]] : $*Foo
func zang(x x: Foo) {}
// No writeback for pass-by-value argument
zang(x: x)
// CHECK: function_ref @$s9writeback4zang1xyAA3FooV_tF : $@convention(thin) (Foo) -> ()
// CHECK-NOT: @$s9writeback1xAA3FooVvs
zang(x: readonly)
// CHECK: function_ref @$s9writeback4zang1xyAA3FooV_tF : $@convention(thin) (Foo) -> ()
// CHECK-NOT: @$s9writeback8readonlyAA3FooVvs
func zung() -> Int { return 0 }
// Ensure that subscripts are only evaluated once.
bar(x: &x[zung()])
// CHECK: [[ZUNG:%.*]] = function_ref @$s9writeback4zungSiyF : $@convention(thin) () -> Int
// CHECK: [[INDEX:%.*]] = apply [[ZUNG]]() : $@convention(thin) () -> Int
// CHECK: [[GET_X:%.*]] = function_ref @$s9writeback1xAA3FooVvg : $@convention(thin) () -> Foo
// CHECK: [[GET_SUBSCRIPT:%.*]] = function_ref @$s9writeback3FooV{{[_0-9a-zA-Z]*}}ig : $@convention(method) (Int, Foo) -> Foo
// CHECK: apply [[GET_SUBSCRIPT]]([[INDEX]], {{%.*}}) : $@convention(method) (Int, Foo) -> Foo
// CHECK: [[BAR:%.*]] = function_ref @$s9writeback3bar1xyAA3FooVz_tF : $@convention(thin) (@inout Foo) -> ()
// CHECK: apply [[BAR]]({{%.*}}) : $@convention(thin) (@inout Foo) -> ()
// CHECK: [[SET_SUBSCRIPT:%.*]] = function_ref @$s9writeback3FooV{{[_0-9a-zA-Z]*}}is : $@convention(method) (Foo, Int, @inout Foo) -> ()
// CHECK: apply [[SET_SUBSCRIPT]]({{%.*}}, [[INDEX]], {{%.*}}) : $@convention(method) (Foo, Int, @inout Foo) -> ()
// CHECK: function_ref @$s9writeback1xAA3FooVvs : $@convention(thin) (Foo) -> ()
protocol Fungible {}
extension Foo : Fungible {}
var addressOnly: Fungible {
get {
return Foo()
}
set {}
}
func funge(x x: inout Fungible) {}
funge(x: &addressOnly)
// CHECK: [[TEMP:%.*]] = alloc_stack $any Fungible
// CHECK: [[GET:%.*]] = function_ref @$s9writeback11addressOnlyAA8Fungible_pvg : $@convention(thin) () -> @out any Fungible
// CHECK: apply [[GET]]([[TEMP]]) : $@convention(thin) () -> @out any Fungible
// CHECK: [[FUNGE:%.*]] = function_ref @$s9writeback5funge1xyAA8Fungible_pz_tF : $@convention(thin) (@inout any Fungible) -> ()
// CHECK: apply [[FUNGE]]([[TEMP]]) : $@convention(thin) (@inout any Fungible) -> ()
// CHECK: [[SET:%.*]] = function_ref @$s9writeback11addressOnlyAA8Fungible_pvs : $@convention(thin) (@in any Fungible) -> ()
// CHECK: apply [[SET]]([[TEMP]]) : $@convention(thin) (@in any Fungible) -> ()
// CHECK: dealloc_stack [[TEMP]] : $*any Fungible
// Test that writeback occurs with generic properties.
// <rdar://problem/16525257>
protocol Runcible {
associatedtype Frob: Frobable
var frob: Frob { get set }
}
protocol Frobable {
associatedtype Anse
var anse: Anse { get set }
}
// CHECK-LABEL: sil hidden [ossa] @$s9writeback12test_generic{{[_0-9a-zA-Z]*}}F
// CHECK: witness_method $Runce, #Runcible.frob!modify
// CHECK: witness_method $Runce.Frob, #Frobable.anse!setter
func test_generic<Runce: Runcible>(runce runce: inout Runce, anse: Runce.Frob.Anse) {
runce.frob.anse = anse
}
// We should *not* write back when referencing decls or members as rvalues.
// <rdar://problem/16530235>
// CHECK-LABEL: sil hidden [ossa] @$s9writeback15loadAddressOnlyAA8Fungible_pyF : $@convention(thin) () -> @out any Fungible {
func loadAddressOnly() -> Fungible {
// CHECK: function_ref writeback.addressOnly.getter
// CHECK-NOT: function_ref writeback.addressOnly.setter
return addressOnly
}
// CHECK-LABEL: sil hidden [ossa] @$s9writeback10loadMember{{[_0-9a-zA-Z]*}}F
// CHECK: witness_method $Runce, #Runcible.frob!getter
// CHECK: witness_method $Runce.Frob, #Frobable.anse!getter
// CHECK-NOT: witness_method $Runce.Frob, #Frobable.anse!setter
// CHECK-NOT: witness_method $Runce, #Runcible.frob!setter
func loadMember<Runce: Runcible>(runce runce: Runce) -> Runce.Frob.Anse {
return runce.frob.anse
}
|