blob: 7ed2c297d1754b51787d024430847772e92138f0 [file] [log] [blame]
// RUN: %target-swift-frontend -primary-file %s -emit-ir| FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s
// REQUIRES: CPU=i386_or_x86_64
sil_stage canonical
import Swift
class A {}
class B: A {}
class C {}
sil_vtable A {}
sil_vtable B {}
sil_vtable C {}
protocol CP: class {}
// CHECK-i386-LABEL: define{{( protected)?}} i32 @bitcast_trivial(%C7bitcast1C*) {{.*}} {
// CHECK-i386: [[BUF:%.*]] = alloca %C7bitcast1C*, align 4
// CHECK-i386: store %C7bitcast1C* %0, %C7bitcast1C** [[BUF]]
// CHECK-i386: [[OUT_BUF:%.*]] = bitcast %C7bitcast1C** [[BUF]] to %Si*
// CHECK-i386: [[VALUE_BUF:%.*]] = getelementptr inbounds %Si, %Si* [[OUT_BUF]], i32 0, i32 0
// CHECK-i386: [[VALUE:%.*]] = load i32, i32* [[VALUE_BUF]], align 4
// CHECK-i386: ret i32 [[VALUE]]
// CHECK-i386: }
// CHECK-x86_64-LABEL: define{{( protected)?}} i64 @bitcast_trivial(%C7bitcast1C*) {{.*}} {
// CHECK-x86_64: [[BUF:%.*]] = alloca %C7bitcast1C*, align 8
// CHECK-x86_64: store %C7bitcast1C* %0, %C7bitcast1C** [[BUF]]
// CHECK-x86_64: [[OUT_BUF:%.*]] = bitcast %C7bitcast1C** [[BUF]] to %Si*
// CHECK-x86_64: [[VALUE_BUF:%.*]] = getelementptr inbounds %Si, %Si* [[OUT_BUF]], i32 0, i32 0
// CHECK-x86_64: [[VALUE:%.*]] = load i64, i64* [[VALUE_BUF]], align 8
// CHECK-x86_64: ret i64 [[VALUE]]
// CHECK-x86_64: }
sil @bitcast_trivial: $@convention(thin) (C) -> Int {
entry(%c : $C):
%i = unchecked_trivial_bit_cast %c : $C to $Int
return %i : $Int
}
// CHECK-x86_64-LABEL: define{{( protected)?}} { i64, i1 } @bitcast_trivial_optional(i64, i1) {{.*}} {
// CHECK-x86_64-NEXT: entry:
// CHECK-x86_64-NEXT: %2 = insertvalue { i64, i1 } undef, i64 %0, 0
// CHECK-x86_64-NEXT: %3 = insertvalue { i64, i1 } %2, i1 %1, 1
// CHECK-x86_64-NEXT: ret { i64, i1 } %3
sil @bitcast_trivial_optional: $@convention(thin) (Optional<Int>) -> ImplicitlyUnwrappedOptional<Int> {
entry(%c : $Optional<Int>):
%i = unchecked_trivial_bit_cast %c : $Optional<Int> to $ImplicitlyUnwrappedOptional<Int>
return %i : $ImplicitlyUnwrappedOptional<Int>
}
// CHECK-i386-LABEL: define{{( protected)?}} i32 @bitcast_ref(%C7bitcast1C*) {{.*}} {
// CHECK-i386-NEXT: entry:
// CHECK-i386-NEXT: [[VALUE:%.*]] = ptrtoint %C7bitcast1C* %0 to i32
// CHECK-i386-NEXT: ret i32 [[VALUE]]
// CHECK-i386-NEXT: }
// CHECK-x86_64-LABEL: define{{( protected)?}} i64 @bitcast_ref(%C7bitcast1C*) {{.*}} {
// CHECK-x86_64-NEXT: entry:
// CHECK-x86_64-NEXT: [[VALUE:%.*]] = ptrtoint %C7bitcast1C* %0 to i64
// CHECK-x86_64-NEXT: ret i64 [[VALUE]]
// CHECK-x86_64-NEXT: }
sil @bitcast_ref: $@convention(thin) (C) -> Optional<C> {
entry(%c : $C):
%o = unchecked_ref_cast %c : $C to $Optional<C>
return %o : $Optional<C>
}
// CHECK-i386-LABEL: define hidden i32 @bitcast_ref_optional(i32) {{.*}} {
// CHECK-i386-NEXT: entry:
// CHECK-i386-NEXT: ret i32 %0
// CHECK-i386-NEXT: }
// CHECK-x86_64-LABEL: define hidden i64 @bitcast_ref_optional(i64) {{.*}} {
// CHECK-x86_64-NEXT: entry:
// CHECK-x86_64-NEXT: ret i64 %0
// CHECK-x86_64-NEXT: }
sil hidden @bitcast_ref_optional : $@convention(thin) (@owned ImplicitlyUnwrappedOptional<C>) -> @owned Optional<C> {
bb0(%0 : $ImplicitlyUnwrappedOptional<C>):
%o = unchecked_ref_cast %0 : $ImplicitlyUnwrappedOptional<C> to $Optional<C>
return %o : $Optional<C>
}
// CHECK-x86_64-LABEL: define hidden i64 @unchecked_bitwise_cast(i64, i64) {{.*}} {
// CHECK-x86_64-NEXT: entry:
// CHECK-x86_64-NEXT: alloca <{ %Si, %Si }>, align 8
// A bunch of GEPs happen here to get from Int to int.
// CHECK-x86_64: store i64 %{{.*}}, i64* %bitcast.elt._value, align 8
// CHECK-x86_64: store i64 %{{.*}}, i64* %bitcast.elt1._value, align 8
// CHECK-x86_64-NEXT: %{{.*}} = bitcast <{ %Si, %Si }>* %bitcast to %Si*
// CHECK-x86_64-NEXT: [[VAL:%.*]] = getelementptr inbounds %Si, %Si* %{{.*}}, i32 0, i32 0
// CHECK-x86_64-NEXT: [[RESULT:%.*]] = load i64, i64* [[VAL]], align 8
// CHECK-x86_64: ret i64 [[RESULT]]
// CHECK-x86_64-NEXT: }
sil hidden @unchecked_bitwise_cast : $@convention(thin) (Int, Int) -> Int {
bb0(%0 : $Int, %1 : $Int):
%2 = tuple (%0 : $Int, %1 : $Int)
%3 = unchecked_bitwise_cast %2 : $(Int, Int) to $Int
return %3 : $Int
}
// CHECK-x86_64-LABEL: define hidden i64 @trivial_bitwise_cast(i64, i64) {{.*}} {
// CHECK-x86_64-NOT: trap
// CHECK-x86_64-NOT: unreachable
// CHECK-x86_64: bitcast <{ %Si, %Si }>* %bitcast to %Si*
// CHECK-x86_64: ret
sil hidden [noinline] @trivial_bitwise_cast : $@convention(thin) (Int, Int) -> Int {
bb0(%0 : $Int, %1 : $Int):
%t1 = tuple (%0 : $Int, %1 : $Int)
%i3 = unchecked_trivial_bit_cast %t1 : $(Int, Int) to $Int
return %i3 : $Int
}
// CHECK-LABEL: define{{( protected)?}} void @unchecked_ref_cast_addr
// CHECK-i386: call i1 @rt_swift_dynamicCast(%swift.opaque* %0, %swift.opaque* %{{.*}}, %swift.type* %T, %swift.type* %U, i32 7)
// CHECK-x86_64: call i1 @rt_swift_dynamicCast(%swift.opaque* %0, %swift.opaque* %{{.*}}, %swift.type* %T, %swift.type* %U, i64 7)
sil @unchecked_ref_cast_addr : $@convention(thin) <T, U> (@in T) -> @out U {
bb0(%0 : $*U, %1 : $*T):
%a = alloc_stack $T
copy_addr %1 to [initialization] %a : $*T
unchecked_ref_cast_addr T in %a : $*T to U in %0 : $*U
dealloc_stack %a : $*T
destroy_addr %1 : $*T
%r = tuple ()
return %r : $()
}
// CHECK-i386-LABEL: define{{( protected)?}} i32 @unchecked_ref_cast_class_optional
// CHECK-i386: ptrtoint %C7bitcast1A* %0 to i32
// CHECK-i386-NEXT: ret i32
// CHECK-x86_64-LABEL: define{{( protected)?}} i64 @unchecked_ref_cast_class_optional
// CHECK-x86_64: ptrtoint %C7bitcast1A* %0 to i64
// CHECK-x86_64-NEXT: ret i64
sil @unchecked_ref_cast_class_optional : $@convention(thin) (@owned A) -> @owned Optional<AnyObject> {
bb0(%0 : $A):
%2 = unchecked_ref_cast %0 : $A to $Optional<AnyObject>
return %2 : $Optional<AnyObject>
}
// CHECK-i386-LABEL: define{{( protected)?}} i32 @unchecked_ref_cast_optional_optional
// CHECK-i386: ret i32 %0
// CHECK-x86_64-LABEL: define{{( protected)?}} i64 @unchecked_ref_cast_optional_optional
// CHECK-x86_64: ret i64 %0
sil @unchecked_ref_cast_optional_optional : $@convention(thin) (@owned Optional<A>) -> @owned Optional<AnyObject> {
bb0(%0 : $Optional<A>):
%2 = unchecked_ref_cast %0 : $Optional<A> to $Optional<AnyObject>
return %2 : $Optional<AnyObject>
}
// CHECK-i386-LABEL: define{{( protected)?}} i32 @unchecked_ref_cast_proto_optional
// CHECK-i386: ptrtoint {{%objc_object|%swift.refcounted}}* %0 to i32
// CHECK-i386-NEXT: ret i32
// CHECK-x86_64-LABEL: define{{( protected)?}} i64 @unchecked_ref_cast_proto_optional
// CHECK-x86_64: ptrtoint {{%objc_object|%swift.refcounted}}* %0 to i64
// CHECK-x86_64-NEXT: ret i64
sil @unchecked_ref_cast_proto_optional : $@convention(thin) (@owned CP) -> @owned Optional<AnyObject> {
bb0(%0 : $CP):
%2 = unchecked_ref_cast %0 : $CP to $Optional<AnyObject>
return %2 : $Optional<AnyObject>
}
// CHECK-i386-LABEL: define{{( protected)?}} i32 @unchecked_ref_cast_optionalproto_optional
// CHECK-i386: ret i32 %0
// CHECK-x86_64-LABEL: define{{( protected)?}} i64 @unchecked_ref_cast_optionalproto_optional
// CHECK-x86_64: ret i64 %0
sil @unchecked_ref_cast_optionalproto_optional : $@convention(thin) (@owned Optional<CP>) -> @owned Optional<AnyObject> {
bb0(%0 : $Optional<CP>):
%2 = unchecked_ref_cast %0 : $Optional<CP> to $Optional<AnyObject>
return %2 : $Optional<AnyObject>
}