| // RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime |
| |
| import Swift |
| |
| // CHECK-LABEL: define{{( protected)?}} void @retain_release_boxed_existential(%swift.error*) |
| sil @retain_release_boxed_existential : $@convention(thin) (Error) -> () { |
| entry(%e : $Error): |
| // CHECK-objc: @swift_errorRetain |
| // CHECK-native: @rt_swift_retain |
| strong_retain %e : $Error |
| // CHECK-objc: @swift_errorRelease |
| // CHECK-native: @rt_swift_release |
| strong_release %e : $Error |
| return undef : $() |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} %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 { %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* [[ADDR]], %swift.opaque* %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{{( protected)?}} %swift.error* @alloc_boxed_existential_concrete |
| sil @alloc_boxed_existential_concrete : $@convention(thin) (@owned SomeError) -> @owned Error { |
| entry(%x : $SomeError): |
| // CHECK: [[BOX_PAIR:%.*]] = call { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* {{.*}} @_TMfV17boxed_existential9SomeError, {{.*}}, i8** {{%.*|@_TWPV17boxed_existential9SomeErrors5ErrorS_}}, %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 %V17boxed_existential9SomeError* |
| %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{{( protected)?}} 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 : $() |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} {{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 |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} {{i[0-9]+}} @open_boxed_existential(%swift.error*) |
| sil @open_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: [[OUT_TYPE:%.*]] = getelementptr inbounds {{.*}} [[OUT]], i32 0, i32 1 |
| // CHECK: [[TYPE:%.*]] = load {{.*}} [[OUT_TYPE]] |
| // CHECK: [[OUT_WITNESS:%.*]] = getelementptr inbounds {{.*}} [[OUT]], i32 0, i32 2 |
| // CHECK: [[WITNESS:%.*]] = load {{.*}} [[OUT_WITNESS]] |
| %o = open_existential_box %b : $Error to $*@opened("01234567-89AB-CDEF-0123-000000000000") Error |
| // CHECK: [[CODE_ADDR:%.*]] = getelementptr {{.*}} [[WITNESS]], i32 1 |
| // CHECK: [[CODE:%.*]] = load {{.*}} [[CODE_ADDR]] |
| %m = witness_method $@opened("01234567-89AB-CDEF-0123-000000000000") Error, #Error._code!getter.1, %o : $*@opened("01234567-89AB-CDEF-0123-000000000000") Error : $@convention(witness_method) <Self: Error> (@in_guaranteed Self) -> Int |
| // CHECK: [[CODE_FN:%.*]] = bitcast i8* [[CODE]] to [[INT:i[0-9]+]] (%swift.opaque*, %swift.type*, i8**)* |
| // CHECK: [[RESULT:%.*]] = call [[INT]] [[CODE_FN]](%swift.opaque* noalias nocapture [[ADDR]], %swift.type* [[TYPE]], i8** [[WITNESS]]) |
| %c = apply %m<@opened("01234567-89AB-CDEF-0123-000000000000") Error>(%o) : $@convention(witness_method) <Self: Error> (@in_guaranteed Self) -> Int |
| // CHECK: ret [[INT]] [[RESULT]] |
| return %c : $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]]) |
| // 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*)* @rt_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 |
| } |