xref: /llvm-project/llvm/test/Verifier/callbr.ll (revision 094190c2f52900d9d5d26dba9522e70030cc00a1)
1; RUN: not opt -S %s -passes=verify 2>&1 | FileCheck %s
2
3; CHECK: Number of label constraints does not match number of callbr dests
4; CHECK-NEXT: #too_few_label_constraints
5define void @too_few_label_constraints() {
6  callbr void asm sideeffect "#too_few_label_constraints", "!i"()
7  to label %1 [label %2, label %3]
81:
9  ret void
102:
11  ret void
123:
13  ret void
14}
15
16; CHECK-NOT: Number of label constraints does not match number of callbr dests
17define void @correct_label_constraints() {
18  callbr void asm sideeffect "${0:l} ${1:l}", "!i,!i"()
19  to label %1 [label %2, label %3]
201:
21  ret void
222:
23  ret void
243:
25  ret void
26}
27
28; CHECK: Number of label constraints does not match number of callbr dests
29; CHECK-NEXT: #too_many_label_constraints
30define void @too_many_label_constraints() {
31  callbr void asm sideeffect "#too_many_label_constraints", "!i,!i,!i"()
32  to label %1 [label %2, label %3]
331:
34  ret void
352:
36  ret void
373:
38  ret void
39}
40
41; CHECK: Label constraints can only be used with callbr
42; CHECK-NEXT: #label_constraint_without_callbr
43define void @label_constraint_without_callbr() {
44  call void asm sideeffect "#label_constraint_without_callbr", "!i"()
45  ret void
46}
47
48; CHECK: Number of label constraints does not match number of callbr dests
49; CHECK-NEXT: #callbr_without_label_constraint
50define void @callbr_without_label_constraint() {
51  callbr void asm sideeffect "#callbr_without_label_constraint", ""()
52  to label %1 [label %2]
531:
54  ret void
552:
56  ret void
57}
58
59;; Ensure you can use the return value of a callbr in indirect targets.
60;; No issue!
61define i32 @test4(i1 %var) {
62entry:
63  %ret = callbr i32 asm sideeffect "#test4", "=r,!i"() to label %normal [label %abnormal]
64
65normal:
66  ret i32 0
67
68abnormal:
69  ret i32 %ret
70}
71
72;; Tests of the callbr.landingpad intrinsic function.
73declare i32 @llvm.callbr.landingpad.i64(i64)
74define void @callbrpad_bad_type() {
75entry:
76; CHECK: Intrinsic has incorrect argument type!
77; CHECK-NEXT: ptr @llvm.callbr.landingpad.i64
78  %foo = call i32 @llvm.callbr.landingpad.i64(i64 42)
79  ret void
80}
81
82declare i32 @llvm.callbr.landingpad.i32(i32)
83define i32 @callbrpad_multi_preds() {
84entry:
85  %foo = callbr i32 asm "", "=r,!i"() to label %direct [label %indirect]
86direct:
87  br label %indirect
88indirect:
89; CHECK-NEXT: Intrinsic in block must have 1 unique predecessor
90; CHECK-NEXT: %out = call i32 @llvm.callbr.landingpad.i32(i32 %foo)
91  %out = call i32 @llvm.callbr.landingpad.i32(i32 %foo)
92  ret i32 %out
93}
94
95define void @callbrpad_wrong_callbr() {
96entry:
97  %foo = callbr i32 asm "", "=r,!i"() to label %direct [label %indirect]
98direct:
99; CHECK-NEXT: Intrinsic's corresponding callbr must have intrinsic's parent basic block in indirect destination list
100; CHECK-NEXT: %x = call i32 @llvm.callbr.landingpad.i32(i32 %foo)
101  %x = call i32 @llvm.callbr.landingpad.i32(i32 %foo)
102  ret void
103indirect:
104  ret void
105}
106
107declare i32 @foo(i32)
108define i32 @test_callbr_landingpad_not_first_inst() {
109entry:
110  %0 = callbr i32 asm "", "=r,!i"()
111          to label %asm.fallthrough [label %landingpad]
112
113asm.fallthrough:
114  ret i32 42
115
116landingpad:
117  %foo = call i32 @foo(i32 42)
118; CHECK-NEXT: No other instructions may proceed intrinsic
119; CHECK-NEXT: %out = call i32 @llvm.callbr.landingpad.i32(i32 %0)
120  %out = call i32 @llvm.callbr.landingpad.i32(i32 %0)
121  ret i32 %out
122}
123