| // RUN: %target-swift-frontend -module-name specialize_checked_cast_branch -emit-sil -O -sil-inline-threshold 0 -Xllvm -sil-disable-pass=function-signature-opts %s -o - | %FileCheck %s |
| |
| class C {} |
| class D : C {} |
| class E {} |
| |
| struct NotUInt8 { var value: UInt8 } |
| struct NotUInt64 { var value: UInt64 } |
| |
| var b = NotUInt8(value: 0) |
| var c = C() |
| var d = D() |
| var e = E() |
| var f = NotUInt64(value: 0) |
| var o : AnyObject = c |
| |
| //////////////////////// |
| // Arch to Arch Casts // |
| //////////////////////// |
| |
| public func ArchetypeToArchetypeCast<T1, T2>(t1 : T1, t2 : T2) -> T2 { |
| if let x = t1 as? T2 { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AA1DCTg5 : $@convention(thin) (@guaranteed C, @guaranteed D) -> @owned D |
| // CHECK: bb0([[ARG:%.*]] : $C, [[ARG2:%.*]] : $D): |
| // CHECK: checked_cast_br [[ARG]] : $C to $D, bb1, bb2 |
| // |
| // CHECK: bb1([[T0:%.*]] : $D): |
| // CHECK: strong_retain [[ARG]] |
| // CHECK: return [[T0]] |
| // |
| // CHECK: bb2 |
| // CHECK: builtin "int_trap" |
| // CHECK: unreachable |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AA1DCTg5' |
| _ = ArchetypeToArchetypeCast(t1: c, t2: d) |
| |
| // x -> x where x is a class. |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AFTg5 : $@convention(thin) (@guaranteed C, @guaranteed C) -> @owned C { |
| // CHECK: bb0 |
| // CHECK-NOT: bb1 |
| // CHECK: strong_retain %0 : $C |
| // CHECK: return %0 : $C |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AFTg5' |
| _ = ArchetypeToArchetypeCast(t1: c, t2: c) |
| |
| // TODO: x -> x where x is not a class. |
| _ = ArchetypeToArchetypeCast(t1: b, t2: b) |
| |
| // TODO: x -> y where x is not a class and y is not a class. |
| _ = ArchetypeToArchetypeCast(t1: b, t2: f) |
| |
| // x -> y where x is not a class but y is. |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA8NotUInt8V_AA1CCTg5 : $@convention(thin) (NotUInt8, @guaranteed C) -> @owned C { |
| // CHECK: bb0 |
| // CHECK-NOT: bb1 |
| // CHECK: builtin "int_trap" |
| // CHECK: unreachable |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA8NotUInt8V_AA1CCTg5' |
| _ = ArchetypeToArchetypeCast(t1: b, t2: c) |
| |
| // y -> x where x is a class but y is not. |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AA8NotUInt8VTg5 : $@convention(thin) (@guaranteed C, NotUInt8) -> NotUInt8 { |
| // CHECK: bb0 |
| // CHECK-NOT: bb1 |
| // CHECK: builtin "int_trap" |
| // CHECK: unreachable |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AA8NotUInt8VTg5' |
| _ = ArchetypeToArchetypeCast(t1: c, t2: b) |
| |
| // y -> x where x is a super class of y. |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1DC_AA1CCTg5 : $@convention(thin) (@guaranteed D, @guaranteed C) -> @owned C { |
| // CHECK: [[T1:%.*]] = upcast %0 : $D to $C |
| // CHECK: strong_retain %0 : $D |
| // CHECK: return [[T1]] : $C |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1DC_AA1CCTg5' |
| _ = ArchetypeToArchetypeCast(t1: d, t2: c) |
| |
| // x -> y where x and y are unrelated. |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AA1ECTg5 : $@convention(thin) (@guaranteed C, @guaranteed E) -> @owned E { |
| // CHECK: bb0 |
| // CHECK-NOT: bb1 |
| // CHECK: builtin "int_trap" |
| // CHECK: unreachable |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AA1ECTg5' |
| _ = ArchetypeToArchetypeCast(t1: c, t2: e) |
| |
| /////////////////////////// |
| // Archetype To Concrete // |
| /////////////////////////// |
| |
| func ArchetypeToConcreteCastUInt8<T>(t : T) -> NotUInt8 { |
| if let x = t as? NotUInt8 { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| |
| func ArchetypeToConcreteCastC<T>(t : T) -> C { |
| if let x = t as? C { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| |
| func ArchetypeToConcreteCastD<T>(t : T) -> D { |
| if let x = t as? D { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| |
| func ArchetypeToConcreteCastE<T>(t : T) -> E { |
| if let x = t as? E { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| |
| // uint8 -> uint8 |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch28ArchetypeToConcreteCastUInt81tAA03NotI0Vx_tlFAE_Tg5 : $@convention(thin) (NotUInt8) -> NotUInt8 { |
| // CHECK: bb0([[ARG:%.*]] : |
| // CHECK: return [[ARG]] : $NotUInt8 |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch28ArchetypeToConcreteCastUInt81tAA03NotI0Vx_tlFAE_Tg5' |
| _ = ArchetypeToConcreteCastUInt8(t: b) |
| |
| // TODO: This needs FileCheck love. |
| _ = ArchetypeToConcreteCastUInt8(t: c) |
| |
| // UInt64 -> Uint8 |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch28ArchetypeToConcreteCastUInt81tAA03NotI0Vx_tlFAA0J6UInt64V_Tg5 : $@convention(thin) (NotUInt64) -> NotUInt8 { |
| // CHECK: bb0 |
| // CHECK-NOT: checked_cast_br |
| // CHECK: builtin "int_trap" |
| // CHECK: unreachable |
| _ = ArchetypeToConcreteCastUInt8(t: f) |
| |
| // NotUInt8 -> C |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAA8NotUInt8V_Tg5 : $@convention(thin) (NotUInt8) -> @owned C { |
| // CHECK: bb0 |
| // CHECK-NOT: checked_cast_br |
| // CHECK: unreachable |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAA8NotUInt8V_Tg5' |
| _ = ArchetypeToConcreteCastC(t: b) |
| |
| // C -> C |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAE_Tg5 : $@convention(thin) (@guaranteed C) -> @owned C { |
| // CHECK: bb0([[ARG:%.*]] : $C) |
| // CHECK: strong_retain [[ARG]] |
| // CHECK: return [[ARG]] : $C |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAE_Tg5' |
| _ = ArchetypeToConcreteCastC(t: c) |
| |
| // D -> C |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAA1DC_Tg5 : $@convention(thin) (@guaranteed D) -> @owned C { |
| // CHECK: bb0([[ARG:%.*]] : $D): |
| // CHECK: [[CAST:%.*]] = upcast [[ARG]] : $D to $C |
| // CHECK: strong_retain [[ARG]] |
| // CHECK: return [[CAST]] |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAA1DC_Tg5' |
| _ = ArchetypeToConcreteCastC(t: d) |
| |
| // E -> C |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAA1EC_Tg5 : $@convention(thin) (@guaranteed E) -> @owned C { |
| // CHECK: bb0 |
| // CHECK: builtin "int_trap" |
| // CHECK: unreachable |
| _ = ArchetypeToConcreteCastC(t: e) |
| |
| // C -> D |
| // x -> y where x is a super class of y. |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ArchetypeToConcreteCastD1tAA1DCx_tlFAA1CC_Tg5 : $@convention(thin) (@guaranteed C) -> @owned D { |
| // CHECK: bb0([[ARG:%.*]] : $C): |
| // CHECK: checked_cast_br [[ARG]] : $C to $D, [[SUCC_BB:bb[0-9]+]], [[FAIL_BB:bb[0-9]+]] |
| // |
| // CHECK: [[SUCC_BB]]([[T0:%.*]] : $D): |
| // CHECK: strong_retain [[ARG]] |
| // CHECK: return [[T0]] : $D |
| // |
| // CHECK: [[FAIL_BB]]: |
| // CHECK: builtin "int_trap" |
| // CHECK: unreachable |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch24ArchetypeToConcreteCastD1tAA1DCx_tlFAA1CC_Tg5' |
| _ = ArchetypeToConcreteCastD(t: c) |
| |
| // C -> E |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ArchetypeToConcreteCastE1tAA1ECx_tlFAA1CC_Tg5 : $@convention(thin) (@guaranteed C) -> @owned E { |
| // CHECK: bb0 |
| // CHECK: builtin "int_trap" |
| // CHECK: unreachable |
| _ = ArchetypeToConcreteCastE(t: c) |
| |
| /////////////////////////// |
| // Concrete To Archetype // |
| /////////////////////////// |
| |
| func ConcreteToArchetypeCastUInt8<T>(t: NotUInt8, t2: T) -> T { |
| if let x = t as? T { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| func ConcreteToArchetypeCastC<T>(t: C, t2: T) -> T { |
| if let x = t as? T { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| func ConcreteToArchetypeCastD<T>(t: D, t2: T) -> T { |
| if let x = t as? T { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| |
| // x -> x where x is not a class. |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch28ConcreteToArchetypeCastUInt81t2t2xAA03NotI0V_xtlFAF_Tg5 : $@convention(thin) (NotUInt8, NotUInt8) -> NotUInt8 { |
| // CHECK: bb0 |
| // CHECK-NOT: bb1 |
| // CHECK: return %0 : $NotUInt8 |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch28ConcreteToArchetypeCastUInt81t2t2xAA03NotI0V_xtlFAF_Tg5' |
| _ = ConcreteToArchetypeCastUInt8(t: b, t2: b) |
| |
| // x -> y where x,y are not classes and x is a different type from y. |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch28ConcreteToArchetypeCastUInt81t2t2xAA03NotI0V_xtlFAA0K6UInt64V_Tg5 : $@convention(thin) (NotUInt8, NotUInt64) -> NotUInt64 { |
| // CHECK: bb0 |
| // CHECK-NOT: bb1 |
| // CHECK: unreachable |
| // CHECK: } // end sil function '$s30specialize_checked_cast_branch28ConcreteToArchetypeCastUInt81t2t2xAA03NotI0V_xtlFAA0K6UInt64V_Tg5 |
| _ = ConcreteToArchetypeCastUInt8(t: b, t2: f) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch28ConcreteToArchetypeCastUInt81t2t2xAA03NotI0V_xtlFAA1CC_Tg5 : $@convention(thin) (NotUInt8, @guaranteed C) -> @owned C |
| // CHECK: bb0 |
| // CHECK: unreachable |
| _ = ConcreteToArchetypeCastUInt8(t: b, t2: c) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ConcreteToArchetypeCastC1t2t2xAA1CC_xtlFAF_Tg5 : $@convention(thin) (@guaranteed C, @guaranteed C) -> @owned C |
| // CHECK: bb0 |
| // CHECK: return %0 |
| _ = ConcreteToArchetypeCastC(t: c, t2: c) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ConcreteToArchetypeCastC1t2t2xAA1CC_xtlFAA8NotUInt8V_Tg5 : $@convention(thin) (@guaranteed C, NotUInt8) -> NotUInt8 |
| // CHECK: bb0 |
| // CHECK: unreachable |
| _ = ConcreteToArchetypeCastC(t: c, t2: b) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ConcreteToArchetypeCastC1t2t2xAA1CC_xtlFAA1DC_Tg5 : $@convention(thin) (@guaranteed C, @guaranteed D) -> @owned D |
| // CHECK: bb0 |
| // CHECK: checked_cast_br %0 : $C to $D |
| // CHECK: bb1 |
| _ = ConcreteToArchetypeCastC(t: c, t2: d) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ConcreteToArchetypeCastC1t2t2xAA1CC_xtlFAA1EC_Tg5 : $@convention(thin) (@guaranteed C, @guaranteed E) -> @owned E |
| // CHECK: bb0 |
| // CHECK: unreachable |
| _ = ConcreteToArchetypeCastC(t: c, t2: e) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch24ConcreteToArchetypeCastD1t2t2xAA1DC_xtlFAA1CC_Tg5 : $@convention(thin) (@guaranteed D, @guaranteed C) -> @owned C |
| // CHECK: bb0 |
| // CHECK: [[T0:%.*]] = upcast %0 : $D to $C |
| // CHECK: return [[T0]] |
| _ = ConcreteToArchetypeCastD(t: d, t2: c) |
| |
| //////////////////////// |
| // Super To Archetype // |
| //////////////////////// |
| |
| func SuperToArchetypeCastC<T>(c : C, t : T) -> T { |
| if let x = c as? T { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| |
| func SuperToArchetypeCastD<T>(d : D, t : T) -> T { |
| if let x = d as? T { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch21SuperToArchetypeCastC1c1txAA1CC_xtlFAF_Tg5 : $@convention(thin) (@guaranteed C, @guaranteed C) -> @owned C |
| // CHECK: bb0 |
| // CHECK: return %0 : $C |
| _ = SuperToArchetypeCastC(c: c, t: c) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch21SuperToArchetypeCastC1c1txAA1CC_xtlFAA1DC_Tg5 : $@convention(thin) (@guaranteed C, @guaranteed D) -> @owned D |
| // CHECK: bb0 |
| // CHECK: checked_cast_br %0 : $C to $D |
| // CHECK: bb1 |
| _ = SuperToArchetypeCastC(c: c, t: d) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch21SuperToArchetypeCastC1c1txAA1CC_xtlFAA8NotUInt8V_Tg5 : $@convention(thin) (@guaranteed C, NotUInt8) -> NotUInt8 |
| // CHECK: bb0 |
| // CHECK: unreachable |
| _ = SuperToArchetypeCastC(c: c, t: b) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch21SuperToArchetypeCastD1d1txAA1DC_xtlFAA1CC_Tg5 : $@convention(thin) (@guaranteed D, @guaranteed C) -> @owned C |
| // CHECK: bb0 |
| // CHECK: [[T0:%.*]] = upcast %0 : $D to $C |
| // CHECK: return [[T0]] |
| _ = SuperToArchetypeCastD(d: d, t: c) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch21SuperToArchetypeCastD1d1txAA1DC_xtlFAF_Tg5 : $@convention(thin) (@guaranteed D, @guaranteed D) -> @owned D |
| // CHECK: bb0 |
| // CHECK: return %0 : $D |
| _ = SuperToArchetypeCastD(d: d, t: d) |
| |
| ////////////////////////////// |
| // Existential To Archetype // |
| ////////////////////////////// |
| |
| func ExistentialToArchetypeCast<T>(o : AnyObject, t : T) -> T { |
| if let x = o as? T { |
| return x |
| } |
| preconditionFailure("??? Profit?") |
| } |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch26ExistentialToArchetypeCast1o1txyXl_xtlFAA1CC_Tg5 : $@convention(thin) (@guaranteed AnyObject, @guaranteed C) -> @owned C |
| // CHECK: bb0 |
| // CHECK: checked_cast_br %0 : $AnyObject to $C |
| // CHECK: bb1 |
| _ = ExistentialToArchetypeCast(o: o, t: c) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch26ExistentialToArchetypeCast1o1txyXl_xtlFAA8NotUInt8V_Tg5 : $@convention(thin) (@guaranteed AnyObject, NotUInt8) -> NotUInt8 |
| // CHECK: bb0 |
| // CHECK: checked_cast_addr_br take_always AnyObject in {{%.*}} : $*AnyObject to NotUInt8 in {{%.*}} : $*NotUInt8, |
| // CHECK: bb1 |
| _ = ExistentialToArchetypeCast(o: o, t: b) |
| |
| // CHECK-LABEL: sil shared @$s30specialize_checked_cast_branch26ExistentialToArchetypeCast1o1txyXl_xtlFyXl_Tg5 : $@convention(thin) (@guaranteed AnyObject, @guaranteed AnyObject) -> @owned AnyObject |
| // CHECK: bb0 |
| // CHECK-NOT: checked_cast_br % |
| // CHECK: return %0 : $AnyObject |
| // CHECK-NOT: checked_cast_br % |
| _ = ExistentialToArchetypeCast(o: o, t: o) |