1; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=X86_64
2; RUN: llc -mtriple=i386-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=X86
3; FIXME: Fix machine verifier issues and remove -verify-machineinstrs=0. PR39439.
4; RUN: llc -mtriple i386-windows-gnu -exception-model sjlj -verify-machineinstrs=0 < %s | FileCheck %s --check-prefix=SJLJ
5
6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7;; Test1
8;; -----
9;; Checks ENDBR insertion in case of switch case statement.
10;; Also since the function is not internal, make sure that endbr32/64 was
11;; added at the beginning of the function.
12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
14define i8 @test1(){
15; ALL-LABEL:   test1
16; X86_64:      endbr64
17; X86:         endbr32
18; ALL:         jmp{{q|l}} *
19; ALL:         .LBB0_1:
20; X86_64-NEXT: endbr64
21; X86-NEXT:    endbr32
22; ALL:         .LBB0_2:
23; X86_64-NEXT: endbr64
24; X86-NEXT:    endbr32
25entry:
26  %0 = select i1 undef, i8* blockaddress(@test1, %bb), i8* blockaddress(@test1, %bb6) ; <i8*> [#uses=1]
27  indirectbr i8* %0, [label %bb, label %bb6]
28
29bb:                                               ; preds = %entry
30  ret i8 1
31
32bb6:                                              ; preds = %entry
33  ret i8 2
34}
35
36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
37;; Test2
38;; -----
39;; Checks NOTRACK insertion in case of switch case statement.
40;; Check that there is no ENDBR insertion in the following case statements.
41;; Also since the function is not internal, ENDBR instruction should be
42;; added to its first basic block.
43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
44
45define i32 @test2(i32 %a) {
46; ALL-LABEL:   test2
47; X86_64:      endbr64
48; X86:         endbr32
49; ALL:         notrack jmp{{q|l}} *
50; X86_64-NOT:      endbr64
51; X86-NOT:         endbr32
52entry:
53  %retval = alloca i32, align 4
54  %a.addr = alloca i32, align 4
55  store i32 %a, i32* %a.addr, align 4
56  %0 = load i32, i32* %a.addr, align 4
57  switch i32 %0, label %sw.default [
58    i32 0, label %sw.bb
59    i32 1, label %sw.bb1
60    i32 2, label %sw.bb2
61    i32 3, label %sw.bb3
62    i32 4, label %sw.bb4
63  ]
64
65sw.bb:                                            ; preds = %entry
66  store i32 5, i32* %retval, align 4
67  br label %return
68
69sw.bb1:                                           ; preds = %entry
70  store i32 7, i32* %retval, align 4
71  br label %return
72
73sw.bb2:                                           ; preds = %entry
74  store i32 2, i32* %retval, align 4
75  br label %return
76
77sw.bb3:                                           ; preds = %entry
78  store i32 32, i32* %retval, align 4
79  br label %return
80
81sw.bb4:                                           ; preds = %entry
82  store i32 73, i32* %retval, align 4
83  br label %return
84
85sw.default:                                       ; preds = %entry
86  store i32 0, i32* %retval, align 4
87  br label %return
88
89return:                                           ; preds = %sw.default, %sw.bb4, %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb
90  %1 = load i32, i32* %retval, align 4
91  ret i32 %1
92}
93
94;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
95;; Test3
96;; -----
97;; Checks ENDBR insertion in case of indirect call instruction.
98;; The new instruction should be added to the called function (test6)
99;; although it is internal.
100;; Also since the function is not internal, ENDBR instruction should be
101;; added to its first basic block.
102;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
103
104define void @test3() {
105; ALL-LABEL:   test3
106; X86_64:      endbr64
107; X86:         endbr32
108; ALL:         call{{q|l}} *
109entry:
110  %f = alloca i32 (...)*, align 8
111  store i32 (...)* bitcast (i32 (i32)* @test6 to i32 (...)*), i32 (...)** %f, align 8
112  %0 = load i32 (...)*, i32 (...)** %f, align 8
113  %call = call i32 (...) %0()
114  ret void
115}
116
117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
118;; Test4
119;; -----
120;; Checks ENDBR insertion in case of setjmp-like function calls.
121;; Also since the function is not internal, ENDBR instruction should be
122;; added to its first basic block.
123;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
124
125@buf = internal global [5 x i8*] zeroinitializer
126declare i8* @llvm.frameaddress(i32)
127declare i8* @llvm.stacksave()
128declare i32 @llvm.eh.sjlj.setjmp(i8*)
129
130define i32 @test4() {
131; ALL-LABEL:   test4
132; X86_64:      endbr64
133; X86:         endbr32
134; ALL:         .LBB3_3:
135; X86_64-NEXT: endbr64
136; X86-NEXT:    endbr32
137  %fp = tail call i8* @llvm.frameaddress(i32 0)
138  store i8* %fp, i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @buf, i64 0, i64 0), align 16
139  %sp = tail call i8* @llvm.stacksave()
140  store i8* %sp, i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @buf, i64 0, i64 2), align 16
141  %r = tail call i32 @llvm.eh.sjlj.setjmp(i8* bitcast ([5 x i8*]* @buf to i8*))
142  ret i32 %r
143}
144
145;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
146;; Test5
147;; -----
148;; Checks ENDBR insertion in case of internal function.
149;; Since the function is internal and its address was not taken,
150;; make sure that endbr32/64 was not added at the beginning of the
151;; function.
152;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
153
154define internal i8 @test5(){
155; ALL-LABEL:   test5
156; X86_64-NOT:      endbr64
157; X86-NOT:         endbr32
158  ret i8 1
159}
160
161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
162;; Test6
163;; -----
164;; Checks ENDBR insertion in case of function that its was address taken.
165;; Since the function's address was taken by test3() and despite being
166;; internal, check for added endbr32/64 at the beginning of the function.
167;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
168
169define internal i32 @test6(i32 %a) {
170; ALL-LABEL:   test6
171; X86_64:      endbr64
172; X86:         endbr32
173  ret i32 1
174}
175
176;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
177;; Test7
178;; -----
179;; Checks ENDBR insertion in case of non-intrenal function.
180;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
181
182define i32 @test7() {
183; ALL-LABEL:   test7
184; X86_64:      endbr64
185; X86:         endbr32
186  ret i32 1
187}
188
189;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
190;; Test8
191;; -----
192;; Checks that NO TRACK prefix is not added for indirect jumps to a jump-
193;; table that was created for SJLJ dispatch.
194;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
195
196declare void @_Z20function_that_throwsv()
197declare i32 @__gxx_personality_sj0(...)
198declare i8* @__cxa_begin_catch(i8*)
199declare void @__cxa_end_catch()
200
201define void @test8() personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) {
202;SJLJ-LABEL:    test8
203;SJLJ-NOT:      ds
204entry:
205  invoke void @_Z20function_that_throwsv()
206          to label %try.cont unwind label %lpad
207
208lpad:
209  %0 = landingpad { i8*, i32 }
210          catch i8* null
211  %1 = extractvalue { i8*, i32 } %0, 0
212  %2 = tail call i8* @__cxa_begin_catch(i8* %1)
213  tail call void @__cxa_end_catch()
214  br label %try.cont
215
216try.cont:
217  ret void
218}
219
220!llvm.module.flags = !{!0}
221
222!0 = !{i32 4, !"cf-protection-branch", i32 1}
223