| // RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -primary-file %s -emit-ir| %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s |
| |
| // REQUIRES: CPU=i386 || CPU=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)?}} swiftcc i32 @bitcast_trivial(%T7bitcast1CC*) {{.*}} { |
| // CHECK-i386: [[BUF:%.*]] = alloca %T7bitcast1CC*, align 4 |
| // CHECK-i386: store %T7bitcast1CC* %0, %T7bitcast1CC** [[BUF]] |
| // CHECK-i386: [[OUT_BUF:%.*]] = bitcast %T7bitcast1CC** [[BUF]] to %TSi* |
| // CHECK-i386: [[VALUE_BUF:%.*]] = getelementptr inbounds %TSi, %TSi* [[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)?}} swiftcc i64 @bitcast_trivial(%T7bitcast1CC*) {{.*}} { |
| // CHECK-x86_64: [[BUF:%.*]] = alloca %T7bitcast1CC*, align 8 |
| // CHECK-x86_64: store %T7bitcast1CC* %0, %T7bitcast1CC** [[BUF]] |
| // CHECK-x86_64: [[OUT_BUF:%.*]] = bitcast %T7bitcast1CC** [[BUF]] to %TSi* |
| // CHECK-x86_64: [[VALUE_BUF:%.*]] = getelementptr inbounds %TSi, %TSi* [[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)?}} swiftcc { i64, i8 } @bitcast_trivial_optional(i64, i8) {{.*}} { |
| // CHECK-x86_64-NEXT: entry: |
| // CHECK-x86_64-NEXT: %2 = trunc i8 %1 to i1 |
| // CHECK-x86_64-NEXT: %3 = zext i1 %2 to i8 |
| // CHECK-x86_64-NEXT: %4 = insertvalue { i64, i8 } undef, i64 %0, 0 |
| // CHECK-x86_64-NEXT: %5 = insertvalue { i64, i8 } %4, i8 %3, 1 |
| // CHECK-x86_64-NEXT: ret { i64, i8 } %5 |
| |
| sil @bitcast_trivial_optional: $@convention(thin) (Optional<Int>) -> Optional<Int> { |
| entry(%c : $Optional<Int>): |
| %i = unchecked_trivial_bit_cast %c : $Optional<Int> to $Optional<Int> |
| return %i : $Optional<Int> |
| } |
| |
| // CHECK-i386-LABEL: define{{( protected)?}} swiftcc i32 @bitcast_ref(%T7bitcast1CC*) {{.*}} { |
| // CHECK-i386-NEXT: entry: |
| // CHECK-i386-NEXT: [[VALUE:%.*]] = ptrtoint %T7bitcast1CC* %0 to i32 |
| // CHECK-i386-NEXT: ret i32 [[VALUE]] |
| // CHECK-i386-NEXT: } |
| |
| // CHECK-x86_64-LABEL: define{{( protected)?}} swiftcc i64 @bitcast_ref(%T7bitcast1CC*) {{.*}} { |
| // CHECK-x86_64-NEXT: entry: |
| // CHECK-x86_64-NEXT: [[VALUE:%.*]] = ptrtoint %T7bitcast1CC* %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 swiftcc i32 @bitcast_ref_optional(i32) {{.*}} { |
| // CHECK-i386-NEXT: entry: |
| // CHECK-i386-NEXT: ret i32 %0 |
| // CHECK-i386-NEXT: } |
| |
| // CHECK-x86_64-LABEL: define hidden swiftcc 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 Optional<C>) -> @owned Optional<C> { |
| bb0(%0 : $Optional<C>): |
| %o = unchecked_ref_cast %0 : $Optional<C> to $Optional<C> |
| return %o : $Optional<C> |
| } |
| |
| // CHECK-x86_64-LABEL: define hidden swiftcc i64 @unchecked_bitwise_cast(i64, i64) {{.*}} { |
| // CHECK-x86_64-NEXT: entry: |
| // CHECK-x86_64-NEXT: alloca <{ %TSi, %TSi }>, 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 <{ %TSi, %TSi }>* %bitcast to %TSi* |
| // CHECK-x86_64-NEXT: [[VAL:%.*]] = getelementptr inbounds %TSi, %TSi* %{{.*}}, 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 swiftcc i64 @trivial_bitwise_cast(i64, i64) {{.*}} { |
| // CHECK-x86_64-NOT: trap |
| // CHECK-x86_64-NOT: unreachable |
| // CHECK-x86_64: bitcast <{ %TSi, %TSi }>* %bitcast to %TSi* |
| // 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)?}} swiftcc void @unchecked_ref_cast_addr |
| // CHECK-i386: call i1 @swift_rt_swift_dynamicCast(%swift.opaque* %0, %swift.opaque* %{{.*}}, %swift.type* %T, %swift.type* %U, i32 7) |
| // CHECK-x86_64: call i1 @swift_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)?}} swiftcc i32 @unchecked_ref_cast_class_optional |
| // CHECK-i386: ptrtoint %T7bitcast1AC* %0 to i32 |
| // CHECK-i386-NEXT: ret i32 |
| |
| // CHECK-x86_64-LABEL: define{{( protected)?}} swiftcc i64 @unchecked_ref_cast_class_optional |
| // CHECK-x86_64: ptrtoint %T7bitcast1AC* %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)?}} swiftcc i32 @unchecked_ref_cast_optional_optional |
| // CHECK-i386: ret i32 %0 |
| |
| // CHECK-x86_64-LABEL: define{{( protected)?}} swiftcc 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)?}} swiftcc 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)?}} swiftcc 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)?}} swiftcc i32 @unchecked_ref_cast_optionalproto_optional |
| // CHECK-i386: ret i32 %0 |
| |
| // CHECK-x86_64-LABEL: define{{( protected)?}} swiftcc 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> |
| } |