|
| 1 | +// RUN: %target-swift-frontend -primary-file %s -emit-ir -Onone -enable-copy-propagation | %FileCheck %s -DINT=i%target-ptrsize |
| 2 | + |
| 3 | +// Test debug_value [poison] emission |
| 4 | + |
| 5 | +class K { |
| 6 | + init() {} |
| 7 | +} |
| 8 | + |
| 9 | +protocol P : AnyObject {} |
| 10 | + |
| 11 | +class D : P {} |
| 12 | + |
| 13 | +protocol Q {} |
| 14 | + |
| 15 | +class E : Q {} |
| 16 | + |
| 17 | +func useInt(_ i: Int) {} |
| 18 | +func useAny(_: Any) {} |
| 19 | +func useOptionalAny(_: Any?) {} |
| 20 | +func useNone() {} |
| 21 | +func getK() -> K { return K() } |
| 22 | +func getOptionalK() -> K? { return K() } |
| 23 | + |
| 24 | +private func useK(_: K) -> Int { |
| 25 | + return 2 |
| 26 | +} |
| 27 | +private func useOptionalK(_: K?) -> Int { |
| 28 | + return 2 |
| 29 | +} |
| 30 | + |
| 31 | +// Hoist and poison 'b' above useInt(y). |
| 32 | +// |
| 33 | +// CHECK-LABEL: define {{.*}}swiftcc void @"$s12debug_poison13testPoisonRefyyF" |
| 34 | +// CHECK: %b.debug = alloca %T12debug_poison1KC* |
| 35 | +// CHECK: %y.debug = alloca [[INT]] |
| 36 | +// CHECK: [[REF:%.*]] = call {{.*}} %T12debug_poison1KC* @"$s12debug_poison4getKAA1KCyF"() |
| 37 | +// CHECK: store %T12debug_poison1KC* [[REF]], %T12debug_poison1KC** %b.debug |
| 38 | +// CHECK: [[Y:%.*]] = call {{.*}} [[INT]] @"$s12debug_poison4use{{.*}}"(%T12debug_poison1KC* [[REF]]) |
| 39 | +// CHECK: call void {{.*}} @swift_release {{.*}} [[REF]] |
| 40 | +// CHECK: store %T12debug_poison1KC* inttoptr ([[INT]] 2176 to %T12debug_poison1KC*), %T12debug_poison1KC** %b.debug |
| 41 | +// CHECK: store [[INT]] [[Y]], [[INT]]* %y.debug |
| 42 | +// CHECK: call {{.*}} void @"$s12debug_poison6useIntyySiF"([[INT]] [[Y]]) |
| 43 | +public func testPoisonRef() { |
| 44 | + let b = getK() |
| 45 | + let y = useK(b) |
| 46 | + useInt(y) |
| 47 | +} |
| 48 | + |
| 49 | +// Hoist and poison 'b' above useInt(y). |
| 50 | +// |
| 51 | +// CHECK-LABEL: define {{.*}}swiftcc void @"$s12debug_poison21testPoisonOptionalRefyyF" |
| 52 | +// CHECK: %b.debug = alloca [[INT]] |
| 53 | +// CHECK: %y.debug = alloca [[INT]] |
| 54 | +// CHECK: [[REF:%.*]] = call {{.*}} [[INT]] @"$s12debug_poison12getOptionalKAA1KCSgyF"() |
| 55 | +// CHECK: store [[INT]] [[REF]], [[INT]]* %b.debug |
| 56 | +// CHECK: [[Y:%.*]] = call {{.*}} [[INT]] @"$s12debug_poison12useOptionalK{{.*}}"([[INT]] [[REF]]) |
| 57 | +// CHECK: call void @swift_release |
| 58 | +// CHECK: [[NIL:%.*]] = icmp eq [[INT]] [[REF]], 0 |
| 59 | +// CHECK: [[POISON:%.*]] = select i1 [[NIL]], [[INT]] [[REF]], [[INT]] 2176 |
| 60 | +// CHECK: store [[INT]] [[POISON]], [[INT]]* %b.debug |
| 61 | +// CHECK: store [[INT]] [[Y]], [[INT]]* %y.debug |
| 62 | +// CHECK: call {{.*}} void @"$s12debug_poison6useIntyySiF"([[INT]] [[Y]]) |
| 63 | +public func testPoisonOptionalRef() { |
| 64 | + let b: K? = getOptionalK() |
| 65 | + let y = useOptionalK(b) |
| 66 | + useInt(y) |
| 67 | +} |
| 68 | + |
| 69 | +// Hoist and poison 'b' above useNone. |
| 70 | +// |
| 71 | +// CHECK-LABEL: define {{.*}}swiftcc void @"$s12debug_poison21testPoisonExistentialyyF" |
| 72 | +// CHECK: %b.debug = alloca %T12debug_poison1PP |
| 73 | +// CHECK: [[INIT:%.*]] = call {{.*}} %T12debug_poison1DC* @"$s12debug_poison1DCACycfC"( |
| 74 | +// CHECK: [[REF:%.*]] = bitcast %T12debug_poison1DC* [[INIT]] to %[[REFTY:.*]]* |
| 75 | +// CHECK: [[GEP0:%.*]] = getelementptr inbounds %T12debug_poison1PP, %T12debug_poison1PP* %b.debug, i32 0, i32 0 |
| 76 | +// CHECK: store %[[REFTY]]* [[REF]], %[[REFTY]]** [[GEP0]] |
| 77 | +// CHECK: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s12debug_poison1DCAA1PAAWP", i32 0, i32 0), i8*** |
| 78 | +// CHECK: call %[[REFTY]]* @swift_{{unknownObjectRetain|retain}}(%[[REFTY]]* returned [[REF]]) |
| 79 | +// CHECK: store %[[REFTY]]* [[REF]], %[[REFTY]]** |
| 80 | +// CHECK: call {{.*}} void @"$s12debug_poison6useAnyyyypF"( |
| 81 | +// CHECK: call void @swift_{{unknownObjectRelease|release}}(%[[REFTY]]* [[REF]]) #1 |
| 82 | +// CHECK: [[GEP1:%.*]] = getelementptr inbounds %T12debug_poison1PP, %T12debug_poison1PP* %b.debug, i32 0, i32 0 |
| 83 | +// CHECK: store %[[REFTY]]* inttoptr ([[INT]] 2176 to %[[REFTY]]*), %[[REFTY]]** [[GEP1]] |
| 84 | +// CHECK: call {{.*}} void @"$s12debug_poison7useNoneyyF"() |
| 85 | +public func testPoisonExistential() { |
| 86 | + let b: P = D() |
| 87 | + useAny(b) |
| 88 | + useNone() |
| 89 | +} |
| 90 | + |
| 91 | +// Hoist and poison 'b' above useNone. |
| 92 | +// |
| 93 | +// CHECK-LABEL: define {{.*}}swiftcc void @"$s12debug_poison19testPoisonCompositeyyF"() |
| 94 | +// CHECK: %b.debug = alloca %T12debug_poison1Q_Xl |
| 95 | +// CHECK: [[INIT:%.*]] = call {{.*}} %T12debug_poison1EC* @"$s12debug_poison1ECACycfC"( |
| 96 | +// CHECK: [[REF:%.*]] = bitcast %T12debug_poison1EC* [[INIT]] to %[[REFTY]]* |
| 97 | +// CHECK: [[GEP0:%.*]] = getelementptr inbounds %T12debug_poison1Q_Xl, %T12debug_poison1Q_Xl* %b.debug, i32 0, i32 0 |
| 98 | +// CHECK: store %[[REFTY]]* [[REF]], %[[REFTY]]** [[GEP0]] |
| 99 | +// CHECK: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s12debug_poison1ECAA1QAAWP", i32 0, i32 0), i8*** |
| 100 | +// CHECK: call %[[REFTY]]* @swift_{{unknownObjectRetain|retain}}(%[[REFTY]]* returned [[REF]]) |
| 101 | +// CHECK: store %[[REFTY]]* [[REF]], %[[REFTY]]** |
| 102 | +// CHECK: call {{.*}} void @"$s12debug_poison6useAnyyyypF"( |
| 103 | +// CHECK: call void @swift_{{unknownObjectRelease|release}}(%[[REFTY]]* [[REF]]) #1 |
| 104 | +// CHECK: [[GEP1:%.*]] = getelementptr inbounds %T12debug_poison1Q_Xl, %T12debug_poison1Q_Xl* %b.debug, i32 0, i32 0 |
| 105 | +// CHECK: store %[[REFTY]]* inttoptr ([[INT]] 2176 to %[[REFTY]]*), %[[REFTY]]** [[GEP1]] |
| 106 | +// CHECK: call {{.*}} void @"$s12debug_poison7useNoneyyF"() |
| 107 | +public func testPoisonComposite() { |
| 108 | + let b: Q & AnyObject = E() |
| 109 | + useAny(b) |
| 110 | + useNone() |
| 111 | +} |
| 112 | + |
| 113 | +// CopyPropagation hoists 'b' above useNone, but IRGen currently bails on emitting poison. |
| 114 | +// |
| 115 | +// CHECK-LABEL: define {{.*}}swiftcc void @"$s12debug_poison27testPoisonOptionalCompositeyyF"() |
| 116 | +// CHECK: %b.debug = alloca %T12debug_poison1Q_XlSg |
| 117 | +// CHECK: [[INIT:%.*]] = call {{.*}} %T12debug_poison1EC* @"$s12debug_poison1ECACycfC"( |
| 118 | +// CHECK: [[REF0:%.*]] = bitcast %T12debug_poison1EC* [[INIT]] to %[[REFTY]]* |
| 119 | +// CHECK: [[REFINT0:%.*]] = ptrtoint %[[REFTY]]* [[REF0]] to [[INT]] |
| 120 | +// CHECK: [[SHADOW0:%.*]] = bitcast %T12debug_poison1Q_XlSg* %b.debug to { [[INT]], [[INT]] }* |
| 121 | +// CHECK: [[GEP0:%.*]] = getelementptr inbounds {{.*}} [[SHADOW0]], i32 0, i32 0 |
| 122 | +// CHECK: store [[INT]] [[REFINT0]], [[INT]]* [[GEP0]] |
| 123 | +// CHECK: store [[INT]] ptrtoint ([1 x i8*]* @"$s12debug_poison1ECAA1QAAWP" to [[INT]]), |
| 124 | +// CHECK: [[REF1:%.*]] = inttoptr [[INT]] [[REFINT0]] to %[[REFTY]]* |
| 125 | +// CHECK: call %[[REFTY]]* @swift_{{unknownObjectRetain|retain}}(%[[REFTY]]* returned [[REF1]]) |
| 126 | +// CHECK: icmp eq [[INT]] [[REFINT0]], 0 |
| 127 | +// CHECK: [[PHI:%.*]] = phi %[[REFTY]]* |
| 128 | +// CHECK: call void @swift_{{unknownObjectRelease|release}}(%[[REFTY]]* |
| 129 | +// CHECK: store %[[REFTY]]* [[PHI]], %[[REFTY]]** |
| 130 | +// CHECK: call {{.*}} void @"$s12debug_poison14useOptionalAnyyyypSgF"( |
| 131 | +// |
| 132 | +// Currently no poison store here. |
| 133 | +// CHECK-NOT: store |
| 134 | +// CHECK: call {{.*}} void @"$s12debug_poison7useNoneyyF"() |
| 135 | +public func testPoisonOptionalComposite() { |
| 136 | + let b: Optional<Q & AnyObject> = E() |
| 137 | + useOptionalAny(b) |
| 138 | + useNone() |
| 139 | +} |
0 commit comments