@@ -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>
@@ -1113,3 +1126,102 @@ bb9:
1113
1126
return %res : $()
1114
1127
}
1115
1128
1129
+ // Test that a load [take] of an unchecked_addr_cast doesn't get promoted.
1130
+ //
1131
+ // CHECK-LABEL: sil [ossa] @load_take_unchecked_addr_cast : {{.*}} {
1132
+ // CHECK: load [take]
1133
+ // CHECK-LABEL: } // end sil function 'load_take_unchecked_addr_cast'
1134
+ sil [ossa] @load_take_unchecked_addr_cast : $@convention(thin) (@guaranteed AnyObject) -> () {
1135
+ entry(%instance : @guaranteed $AnyObject):
1136
+ %copy = copy_value %instance : $AnyObject
1137
+ %storage = alloc_stack $AnyObject
1138
+ store %copy to [init] %storage : $*AnyObject
1139
+ %cast_addr = unchecked_addr_cast %storage : $*AnyObject to $*Klass
1140
+ %value = load [take] %cast_addr : $*Klass
1141
+ dealloc_stack %storage : $*AnyObject
1142
+ destroy_value %value : $Klass
1143
+ %retval = tuple ()
1144
+ return %retval : $()
1145
+ }
1146
+
1147
+ // Don't bail if the original address is destroyed even if we see a cast.
1148
+ //
1149
+ // CHECK-LABEL: sil [ossa] @destroy_original_storage : {{.*}} {
1150
+ // CHECK: destroy_value
1151
+ // CHECK-LABEL: } // end sil function 'destroy_original_storage'
1152
+ sil [ossa] @destroy_original_storage : $@convention(thin) (@guaranteed AnyObject) -> () {
1153
+ entry(%instance : @guaranteed $AnyObject):
1154
+ %copy = copy_value %instance : $AnyObject
1155
+ %storage = alloc_stack $AnyObject
1156
+ store %copy to [init] %storage : $*AnyObject
1157
+ %cast_addr = unchecked_addr_cast %storage : $*AnyObject to $*Klass
1158
+ %value = load [copy] %cast_addr : $*Klass
1159
+ destroy_addr %storage : $*AnyObject
1160
+ dealloc_stack %storage : $*AnyObject
1161
+ destroy_value %value : $Klass
1162
+ %retval = tuple ()
1163
+ return %retval : $()
1164
+ }
1165
+
1166
+ // Bail if the address produced by an unchecked_addr_cast is destroyed.
1167
+ //
1168
+ // CHECK-LABEL: sil [ossa] @destroy_addr_unchecked_addr_cast : {{.*}} {
1169
+ // CHECK: unchecked_addr_cast
1170
+ // CHECK: load [copy]
1171
+ // CHECK-LABEL: } // end sil function 'destroy_addr_unchecked_addr_cast'
1172
+ sil [ossa] @destroy_addr_unchecked_addr_cast : $@convention(thin) (@guaranteed AnyObject) -> () {
1173
+ entry(%instance : @guaranteed $AnyObject):
1174
+ %copy = copy_value %instance : $AnyObject
1175
+ %storage = alloc_stack $AnyObject
1176
+ store %copy to [init] %storage : $*AnyObject
1177
+ %cast_addr = unchecked_addr_cast %storage : $*AnyObject to $*Klass
1178
+ %value = load [copy] %cast_addr : $*Klass
1179
+ destroy_addr %cast_addr : $*Klass
1180
+ dealloc_stack %storage : $*AnyObject
1181
+ destroy_value %value : $Klass
1182
+ %retval = tuple ()
1183
+ return %retval : $()
1184
+ }
1185
+
1186
+ // Bail if there's a load [take] of one of multiple non-trivial fields.
1187
+ //
1188
+ // CHECK-LABEL: sil [ossa] @load_take_one_of_two_nontrivial_struct_fields : {{.*}} {
1189
+ // CHECK: load [take]
1190
+ // CHECK: destroy_addr
1191
+ // CHECK-LABEL: } // end sil function 'load_take_one_of_two_nontrivial_struct_fields'
1192
+ sil [ossa] @load_take_one_of_two_nontrivial_struct_fields : $@convention(thin) (@guaranteed S) -> () {
1193
+ entry(%instance : @guaranteed $S):
1194
+ %copy = copy_value %instance : $S
1195
+ %storage = alloc_stack $S
1196
+ store %copy to [init] %storage : $*S
1197
+ %v1_addr = struct_element_addr %storage : $*S, #S.v1
1198
+ %cast_addr = unchecked_addr_cast %v1_addr : $*AnyObject to $*Klass
1199
+ %value = load [take] %cast_addr : $*Klass
1200
+ %v2_addr = struct_element_addr %storage : $*S, #S.v2
1201
+ destroy_addr %v2_addr : $*AnyObject
1202
+ //destroy_addr %storage : $*S
1203
+ dealloc_stack %storage : $*S
1204
+ destroy_value %value : $Klass
1205
+ %retval = tuple ()
1206
+ return %retval : $()
1207
+ }
1208
+
1209
+ // Don't bail if we happen to see an unchecked_addr_cast but then load [take]
1210
+ // the original address.
1211
+ //
1212
+ // CHECK-LABEL: sil [ossa] @load_take_original_despite_cast : {{.*}} {
1213
+ // CHECK: unchecked_bitwise_cast
1214
+ // CHECK: destroy_value
1215
+ // CHECK-LABEL: } // end sil function 'load_take_original_despite_cast'
1216
+ sil [ossa] @load_take_original_despite_cast : $@convention(thin) (@owned AnyObject) -> () {
1217
+ entry(%instance : @owned $AnyObject):
1218
+ %74 = alloc_stack $AnyObject
1219
+ store %instance to [init] %74 : $*AnyObject
1220
+ %76 = unchecked_addr_cast %74 : $*AnyObject to $*UInt8
1221
+ %77 = load [trivial] %76 : $*UInt8
1222
+ %79 = load [take] %74 : $*AnyObject
1223
+ destroy_value %79 : $AnyObject
1224
+ dealloc_stack %74 : $*AnyObject
1225
+ %82 = tuple ()
1226
+ return %82 : $()
1227
+ }
0 commit comments