blob: a6219815c2cc2c9527d269cb34459907eb6e525f [file] [log] [blame]
// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime
import Swift
sil @error_user : $@convention(thin) (@owned Error) -> ()
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @retain_release_boxed_existential(%swift.error*)
sil @retain_release_boxed_existential : $@convention(thin) (@owned Error) -> () {
entry(%e : $Error):
// CHECK-objc: @swift_errorRetain
// CHECK-native: @swift_retain
strong_retain %e : $Error
%1 = function_ref @error_user : $@convention(thin) (@owned Error) -> ()
apply %1(%e) : $@convention(thin) (@owned Error) -> ()
// CHECK-objc: @swift_errorRelease
// CHECK-native: @swift_release
strong_release %e : $Error
return undef : $()
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.error* @alloc_boxed_existential(%swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.Error)
sil @alloc_boxed_existential : $@convention(thin) <T: Error> (@in T) -> @owned Error {
entry(%x : $*T):
// CHECK: [[BOX_PAIR:%.*]] = call swiftcc { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* %T, i8** %T.Error, %swift.opaque* null, i1 false)
// CHECK: [[BOX:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 0
// CHECK: [[ADDR:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 1
%b = alloc_existential_box $Error, $T
%p = project_existential_box $T in %b : $Error
// CHECK: call %swift.opaque* %initializeWithTake(%swift.opaque* noalias [[ADDR]], %swift.opaque* noalias %0, %swift.type* %T)
copy_addr [take] %x to [initialization] %p : $*T
// CHECK: ret %swift.error* [[BOX]]
return %b : $Error
}
struct SomeError: Error {
let _domain: String
let _code: Int
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.error* @alloc_boxed_existential_concrete
sil @alloc_boxed_existential_concrete : $@convention(thin) (@owned SomeError) -> @owned Error {
entry(%x : $SomeError):
// CHECK: [[BOX_PAIR:%.*]] = call swiftcc { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* {{.*}} @"$s17boxed_existential9SomeErrorVMf", {{.*}}, i8** {{%.*|@"\$s17boxed_existential9SomeErrorVs0D0AAWP"}}, %swift.opaque* null, i1 false)
// CHECK: [[BOX:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 0
// CHECK: [[OPAQUE_ADDR:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 1
// CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* [[OPAQUE_ADDR]] to %T17boxed_existential9SomeErrorV*
%b = alloc_existential_box $Error, $SomeError
%p = project_existential_box $SomeError in %b : $Error
store %x to %p : $*SomeError
// CHECK: ret %swift.error* [[BOX]]
return %b : $Error
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dealloc_boxed_existential(%swift.error*, %swift.type* %T, i8** %T.Error)
sil @dealloc_boxed_existential : $@convention(thin) <T: Error> (@owned Error) -> () {
entry(%b : $Error):
// CHECK: call void @swift_deallocError(%swift.error* %0, %swift.type* %T)
dealloc_existential_box %b : $Error, $T
return undef : $()
}
struct Str : Error { }
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @alloc_dealloc_box_with_concrete_type
sil @alloc_dealloc_box_with_concrete_type : $@convention(thin) () -> () {
bb0:
// CHECK: call {{.*}} @swift_allocError
%b = alloc_existential_box $Error, $Str
// CHECK: call void @swift_deallocError
dealloc_existential_box %b : $Error, $Str
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc {{i[0-9]+}} @project_boxed_existential(%swift.error*)
sil @project_boxed_existential : $@convention(thin) (@owned Error) -> Int {
entry(%b : $Error):
// CHECK: call void @swift_getErrorValue(%swift.error* %0, i8** {{%.*}}, [[TRIPLE:{ %swift.opaque\*, %swift.type\*, i8\*\* }]]* [[OUT:%.*]])
// CHECK: [[OUT_ADDR:%.*]] = getelementptr inbounds {{.*}} [[OUT]], i32 0, i32 0
// CHECK: [[ADDR:%.*]] = load {{.*}} [[OUT_ADDR]]
// CHECK: [[CADDR:%.*]] = bitcast %swift.opaque* %2 to [[TYPE:%[^*]*]]*
%a = project_existential_box $SomeError in %b : $Error
// CHECK: [[GEP1:%.*]] = getelementptr inbounds [[TYPE]], [[TYPE]]* [[CADDR]], i32 0, i32 1
// CHECK: [[GEP2:%.*]] = getelementptr inbounds {{.*}} [[GEP1]], i32 0, i32 0
%c = struct_element_addr %a : $*SomeError, #SomeError._code
// CHECK: [[R:%.*]] = load {{i[0-9]+}}, {{i[0-9]+}}* [[GEP2]]
%l = load %c : $*Int
// CHECK: ret {{i[0-9]+}} [[R]]
return %l : $Int
}
sil @dynamic_type_boxed_existential : $@convention(thin) (@owned Error) -> @thick Error.Type {
entry(%b : $Error):
// CHECK: call void @swift_getErrorValue(%swift.error* %0, i8** {{%.*}}, [[TRIPLE:{ %swift.opaque\*, %swift.type\*, i8\*\* }]]* [[OUT:%.*]])
// CHECK: [[OUT_ADDR:%.*]] = getelementptr inbounds {{.*}} [[OUT]], i32 0, i32 0
// CHECK: [[ADDR:%.*]] = load {{.*}} [[OUT_ADDR]]
// CHECK: [[OUT_TYPE:%.*]] = getelementptr inbounds {{.*}} [[OUT]], i32 0, i32 1
// CHECK: [[TYPE:%.*]] = load {{.*}} [[OUT_TYPE]]
// CHECK: [[DYNAMIC_TYPE:%.*]] = call %swift.type* @swift_getDynamicType(%swift.opaque* [[ADDR]], %swift.type* [[TYPE]], i1 true)
// CHECK: [[OUT_WITNESS:%.*]] = getelementptr inbounds {{.*}} [[OUT]], i32 0, i32 2
// CHECK: [[WITNESS:%.*]] = load {{.*}} [[OUT_WITNESS]]
%m = existential_metatype $@thick Error.Type, %b : $Error
// CHECK-objc: call void @swift_errorRelease(%swift.error* %0)
// CHECK-native: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%swift.error*)*)(%swift.error* %0)
strong_release %b : $Error
// CHECK: [[RET:%.*]] = insertvalue { %swift.type*, i8** } undef, %swift.type* [[DYNAMIC_TYPE]], 0
// CHECK: [[RET2:%.*]] = insertvalue { %swift.type*, i8** } [[RET]], i8** [[WITNESS]], 1
// CHECK: ret { %swift.type*, i8** } [[RET2]]
return %m : $@thick Error.Type
}