@@ -7,8 +7,17 @@ import Swift
7
7
// Declarations //
8
8
//////////////////
9
9
10
+ typealias AnyObject = Builtin.AnyObject
11
+
10
12
class Klass {}
11
13
14
+ class X {}
15
+
16
+ struct S {
17
+ var v1: AnyObject
18
+ var v2: AnyObject
19
+ }
20
+
12
21
struct SmallCodesizeStruct {
13
22
var cls1 : Klass
14
23
var cls2 : Klass
@@ -40,6 +49,10 @@ public enum FakeOptional<T> {
40
49
case none
41
50
}
42
51
52
+ struct UInt8 {
53
+ var _value : Builtin.Int8
54
+ }
55
+
43
56
sil [ossa] @get_nontrivialstruct : $@convention(thin) () -> @owned NonTrivialStruct
44
57
sil [ossa] @get_nontrivialenum : $@convention(thin) () -> @owned NonTrivialEnum
45
58
sil [ossa] @get_optionalnontrivialstruct : $@convention(thin) () -> @owned FakeOptional<NonTrivialStruct>
@@ -1114,3 +1127,102 @@ bb9:
1114
1127
return %res : $()
1115
1128
}
1116
1129
1130
+ // Test that a load [take] of an unchecked_addr_cast doesn't get promoted.
1131
+ //
1132
+ // CHECK-LABEL: sil [ossa] @load_take_unchecked_addr_cast : {{.*}} {
1133
+ // CHECK: load [take]
1134
+ // CHECK-LABEL: } // end sil function 'load_take_unchecked_addr_cast'
1135
+ sil [ossa] @load_take_unchecked_addr_cast : $@convention(thin) (@guaranteed AnyObject) -> () {
1136
+ entry(%instance : @guaranteed $AnyObject):
1137
+ %copy = copy_value %instance : $AnyObject
1138
+ %storage = alloc_stack $AnyObject
1139
+ store %copy to [init] %storage : $*AnyObject
1140
+ %cast_addr = unchecked_addr_cast %storage : $*AnyObject to $*Klass
1141
+ %value = load [take] %cast_addr : $*Klass
1142
+ dealloc_stack %storage : $*AnyObject
1143
+ destroy_value %value : $Klass
1144
+ %retval = tuple ()
1145
+ return %retval : $()
1146
+ }
1147
+
1148
+ // Don't bail if the original address is destroyed even if we see a cast.
1149
+ //
1150
+ // CHECK-LABEL: sil [ossa] @destroy_original_storage : {{.*}} {
1151
+ // CHECK: destroy_value
1152
+ // CHECK-LABEL: } // end sil function 'destroy_original_storage'
1153
+ sil [ossa] @destroy_original_storage : $@convention(thin) (@guaranteed AnyObject) -> () {
1154
+ entry(%instance : @guaranteed $AnyObject):
1155
+ %copy = copy_value %instance : $AnyObject
1156
+ %storage = alloc_stack $AnyObject
1157
+ store %copy to [init] %storage : $*AnyObject
1158
+ %cast_addr = unchecked_addr_cast %storage : $*AnyObject to $*Klass
1159
+ %value = load [copy] %cast_addr : $*Klass
1160
+ destroy_addr %storage : $*AnyObject
1161
+ dealloc_stack %storage : $*AnyObject
1162
+ destroy_value %value : $Klass
1163
+ %retval = tuple ()
1164
+ return %retval : $()
1165
+ }
1166
+
1167
+ // Bail if the address produced by an unchecked_addr_cast is destroyed.
1168
+ //
1169
+ // CHECK-LABEL: sil [ossa] @destroy_addr_unchecked_addr_cast : {{.*}} {
1170
+ // CHECK: unchecked_addr_cast
1171
+ // CHECK: load [copy]
1172
+ // CHECK-LABEL: } // end sil function 'destroy_addr_unchecked_addr_cast'
1173
+ sil [ossa] @destroy_addr_unchecked_addr_cast : $@convention(thin) (@guaranteed AnyObject) -> () {
1174
+ entry(%instance : @guaranteed $AnyObject):
1175
+ %copy = copy_value %instance : $AnyObject
1176
+ %storage = alloc_stack $AnyObject
1177
+ store %copy to [init] %storage : $*AnyObject
1178
+ %cast_addr = unchecked_addr_cast %storage : $*AnyObject to $*Klass
1179
+ %value = load [copy] %cast_addr : $*Klass
1180
+ destroy_addr %cast_addr : $*Klass
1181
+ dealloc_stack %storage : $*AnyObject
1182
+ destroy_value %value : $Klass
1183
+ %retval = tuple ()
1184
+ return %retval : $()
1185
+ }
1186
+
1187
+ // Bail if there's a load [take] of one of multiple non-trivial fields.
1188
+ //
1189
+ // CHECK-LABEL: sil [ossa] @load_take_one_of_two_nontrivial_struct_fields : {{.*}} {
1190
+ // CHECK: load [take]
1191
+ // CHECK: destroy_addr
1192
+ // CHECK-LABEL: } // end sil function 'load_take_one_of_two_nontrivial_struct_fields'
1193
+ sil [ossa] @load_take_one_of_two_nontrivial_struct_fields : $@convention(thin) (@guaranteed S) -> () {
1194
+ entry(%instance : @guaranteed $S):
1195
+ %copy = copy_value %instance : $S
1196
+ %storage = alloc_stack $S
1197
+ store %copy to [init] %storage : $*S
1198
+ %v1_addr = struct_element_addr %storage : $*S, #S.v1
1199
+ %cast_addr = unchecked_addr_cast %v1_addr : $*AnyObject to $*Klass
1200
+ %value = load [take] %cast_addr : $*Klass
1201
+ %v2_addr = struct_element_addr %storage : $*S, #S.v2
1202
+ destroy_addr %v2_addr : $*AnyObject
1203
+ //destroy_addr %storage : $*S
1204
+ dealloc_stack %storage : $*S
1205
+ destroy_value %value : $Klass
1206
+ %retval = tuple ()
1207
+ return %retval : $()
1208
+ }
1209
+
1210
+ // Don't bail if we happen to see an unchecked_addr_cast but then load [take]
1211
+ // the original address.
1212
+ //
1213
+ // CHECK-LABEL: sil [ossa] @load_take_original_despite_cast : {{.*}} {
1214
+ // CHECK: unchecked_bitwise_cast
1215
+ // CHECK: destroy_value
1216
+ // CHECK-LABEL: } // end sil function 'load_take_original_despite_cast'
1217
+ sil [ossa] @load_take_original_despite_cast : $@convention(thin) (@owned AnyObject) -> () {
1218
+ entry(%instance : @owned $AnyObject):
1219
+ %74 = alloc_stack $AnyObject
1220
+ store %instance to [init] %74 : $*AnyObject
1221
+ %76 = unchecked_addr_cast %74 : $*AnyObject to $*UInt8
1222
+ %77 = load [trivial] %76 : $*UInt8
1223
+ %79 = load [take] %74 : $*AnyObject
1224
+ destroy_value %79 : $AnyObject
1225
+ dealloc_stack %74 : $*AnyObject
1226
+ %82 = tuple ()
1227
+ return %82 : $()
1228
+ }
0 commit comments