Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / X86 / lvi-hardening-indirectbr.ll
blobb6e6e61c73b168c34429fa2a0a2c327d28310599
1 ; RUN: llc -verify-machineinstrs -mtriple=x86_64-unknown -mattr=+lvi-cfi < %s | FileCheck %s --check-prefix=X64
2 ; RUN: llc -verify-machineinstrs -mtriple=x86_64-unknown -mattr=+lvi-cfi -O0 < %s | FileCheck %s --check-prefix=X64FAST
4 ; Note that a lot of this code was lifted from retpoline.ll.
6 declare dso_local void @bar(i32)
8 ; Test a simple indirect call and tail call.
9 define void @icall_reg(ptr %fp, i32 %x) {
10 entry:
11   tail call void @bar(i32 %x)
12   tail call void %fp(i32 %x)
13   tail call void @bar(i32 %x)
14   tail call void %fp(i32 %x)
15   ret void
18 ; X64-LABEL: icall_reg:
19 ; X64-DAG:   movq %rdi, %[[fp:[^ ]*]]
20 ; X64-DAG:   movl %esi, %[[x:[^ ]*]]
21 ; X64:       movl %esi, %edi
22 ; X64:       callq bar
23 ; X64-DAG:   movl %[[x]], %edi
24 ; X64-DAG:   movq %[[fp]], %r11
25 ; X64:       cs
26 ; X64-NEXT:  callq __llvm_lvi_thunk_r11
27 ; X64:       movl %[[x]], %edi
28 ; X64:       callq bar
29 ; X64-DAG:   movl %[[x]], %edi
30 ; X64-DAG:   movq %[[fp]], %r11
31 ; X64:       cs
32 ; X64-NEXT:  jmp __llvm_lvi_thunk_r11 # TAILCALL
34 ; X64FAST-LABEL: icall_reg:
35 ; X64FAST:       callq bar
36 ; X64FAST:       cs
37 ; X64FAST-NEXT:  callq __llvm_lvi_thunk_r11
38 ; X64FAST:       callq bar
39 ; X64FAST:       cs
40 ; X64FAST-NEXT:  jmp __llvm_lvi_thunk_r11 # TAILCALL
43 @global_fp = external dso_local global ptr
45 ; Test an indirect call through a global variable.
46 define void @icall_global_fp(i32 %x, ptr %fpp) #0 {
47   %fp1 = load ptr, ptr @global_fp
48   call void %fp1(i32 %x)
49   %fp2 = load ptr, ptr @global_fp
50   tail call void %fp2(i32 %x)
51   ret void
54 ; X64-LABEL: icall_global_fp:
55 ; X64-DAG:   movl %edi, %[[x:[^ ]*]]
56 ; X64-DAG:   movq global_fp(%rip), %r11
57 ; X64:       cs
58 ; X64-NEXT:  callq __llvm_lvi_thunk_r11
59 ; X64-DAG:   movl %[[x]], %edi
60 ; X64-DAG:   movq global_fp(%rip), %r11
61 ; X64:       cs
62 ; X64-NEXT:  jmp __llvm_lvi_thunk_r11 # TAILCALL
64 ; X64FAST-LABEL: icall_global_fp:
65 ; X64FAST:       movq global_fp(%rip), %r11
66 ; X64FAST:       cs
67 ; X64FAST-NEXT:  callq __llvm_lvi_thunk_r11
68 ; X64FAST:       movq global_fp(%rip), %r11
69 ; X64FAST:       cs
70 ; X64FAST-NEXT:  jmp __llvm_lvi_thunk_r11 # TAILCALL
73 %struct.Foo = type { ptr }
75 ; Test an indirect call through a vtable.
76 define void @vcall(ptr %obj) #0 {
77   %vptr = load ptr, ptr %obj
78   %vslot = getelementptr ptr, ptr %vptr, i32 1
79   %fp = load ptr, ptr %vslot
80   tail call void %fp(ptr %obj)
81   tail call void %fp(ptr %obj)
82   ret void
85 ; X64-LABEL: vcall:
86 ; X64:       movq %rdi, %[[obj:[^ ]*]]
87 ; X64:       movq (%rdi), %[[vptr:[^ ]*]]
88 ; X64:       movq 8(%[[vptr]]), %[[fp:[^ ]*]]
89 ; X64:       movq %[[fp]], %r11
90 ; X64:       cs
91 ; X64-NEXT:  callq __llvm_lvi_thunk_r11
92 ; X64-DAG:   movq %[[obj]], %rdi
93 ; X64-DAG:   movq %[[fp]], %r11
94 ; X64:       cs
95 ; X64-NEXT:  jmp __llvm_lvi_thunk_r11 # TAILCALL
97 ; X64FAST-LABEL: vcall:
98 ; X64FAST:       cs
99 ; X64FAST-NEXT:  callq __llvm_lvi_thunk_r11
100 ; X64FAST:       cs
101 ; X64FAST-NEXT:  jmp __llvm_lvi_thunk_r11 # TAILCALL
104 declare dso_local void @direct_callee()
106 define void @direct_tail() #0 {
107   tail call void @direct_callee()
108   ret void
111 ; X64-LABEL: direct_tail:
112 ; X64:       jmp direct_callee # TAILCALL
113 ; X64FAST-LABEL: direct_tail:
114 ; X64FAST:   jmp direct_callee # TAILCALL
117 declare void @nonlazybind_callee() #1
119 define void @nonlazybind_caller() #0 {
120   call void @nonlazybind_callee()
121   tail call void @nonlazybind_callee()
122   ret void
125 ; X64-LABEL: nonlazybind_caller:
126 ; X64:       movq nonlazybind_callee@GOTPCREL(%rip), %[[REG:.*]]
127 ; X64:       movq %[[REG]], %r11
128 ; X64:       cs
129 ; X64-NEXT:  callq __llvm_lvi_thunk_r11
130 ; X64:       movq %[[REG]], %r11
131 ; X64:       cs
132 ; X64-NEXT:  jmp __llvm_lvi_thunk_r11 # TAILCALL
133 ; X64FAST-LABEL: nonlazybind_caller:
134 ; X64FAST:   movq nonlazybind_callee@GOTPCREL(%rip), %r11
135 ; X64FAST:   cs
136 ; X64FAST-NEXT:  callq __llvm_lvi_thunk_r11
137 ; X64FAST:   movq nonlazybind_callee@GOTPCREL(%rip), %r11
138 ; X64FAST:   cs
139 ; X64FAST-NEXT:  jmp __llvm_lvi_thunk_r11 # TAILCALL
142 ; Check that a switch gets lowered using a jump table
143 define void @switch_jumptable(ptr %ptr, ptr %sink) #0 {
144 ; X64-LABEL: switch_jumptable:
145 ; X64-NOT:      jmpq *
146 entry:
147   br label %header
149 header:
150   %i = load volatile i32, ptr %ptr
151   switch i32 %i, label %bb0 [
152     i32 1, label %bb1
153     i32 2, label %bb2
154     i32 3, label %bb3
155     i32 4, label %bb4
156     i32 5, label %bb5
157     i32 6, label %bb6
158     i32 7, label %bb7
159     i32 8, label %bb8
160     i32 9, label %bb9
161   ]
163 bb0:
164   store volatile i64 0, ptr %sink
165   br label %header
167 bb1:
168   store volatile i64 1, ptr %sink
169   br label %header
171 bb2:
172   store volatile i64 2, ptr %sink
173   br label %header
175 bb3:
176   store volatile i64 3, ptr %sink
177   br label %header
179 bb4:
180   store volatile i64 4, ptr %sink
181   br label %header
183 bb5:
184   store volatile i64 5, ptr %sink
185   br label %header
187 bb6:
188   store volatile i64 6, ptr %sink
189   br label %header
191 bb7:
192   store volatile i64 7, ptr %sink
193   br label %header
195 bb8:
196   store volatile i64 8, ptr %sink
197   br label %header
199 bb9:
200   store volatile i64 9, ptr %sink
201   br label %header
205 @indirectbr_rewrite.targets = constant [10 x ptr] [ptr blockaddress(@indirectbr_rewrite, %bb0),
206                                                    ptr blockaddress(@indirectbr_rewrite, %bb1),
207                                                    ptr blockaddress(@indirectbr_rewrite, %bb2),
208                                                    ptr blockaddress(@indirectbr_rewrite, %bb3),
209                                                    ptr blockaddress(@indirectbr_rewrite, %bb4),
210                                                    ptr blockaddress(@indirectbr_rewrite, %bb5),
211                                                    ptr blockaddress(@indirectbr_rewrite, %bb6),
212                                                    ptr blockaddress(@indirectbr_rewrite, %bb7),
213                                                    ptr blockaddress(@indirectbr_rewrite, %bb8),
214                                                    ptr blockaddress(@indirectbr_rewrite, %bb9)]
216 ; Check that when thunks are enabled the indirectbr instruction gets
217 ; rewritten to use switch, and that in turn doesn't get lowered as a jump
218 ; table.
219 define void @indirectbr_rewrite(ptr readonly %p, ptr %sink) #0 {
220 ; X64-LABEL: indirectbr_rewrite:
221 ; X64-NOT:     jmpq *
222 entry:
223   %i0 = load i64, ptr %p
224   %target.i0 = getelementptr [10 x ptr], ptr @indirectbr_rewrite.targets, i64 0, i64 %i0
225   %target0 = load ptr, ptr %target.i0
226   indirectbr ptr %target0, [label %bb1, label %bb3]
228 bb0:
229   store volatile i64 0, ptr %sink
230   br label %latch
232 bb1:
233   store volatile i64 1, ptr %sink
234   br label %latch
236 bb2:
237   store volatile i64 2, ptr %sink
238   br label %latch
240 bb3:
241   store volatile i64 3, ptr %sink
242   br label %latch
244 bb4:
245   store volatile i64 4, ptr %sink
246   br label %latch
248 bb5:
249   store volatile i64 5, ptr %sink
250   br label %latch
252 bb6:
253   store volatile i64 6, ptr %sink
254   br label %latch
256 bb7:
257   store volatile i64 7, ptr %sink
258   br label %latch
260 bb8:
261   store volatile i64 8, ptr %sink
262   br label %latch
264 bb9:
265   store volatile i64 9, ptr %sink
266   br label %latch
268 latch:
269   %i.next = load i64, ptr %p
270   %target.i.next = getelementptr [10 x ptr], ptr @indirectbr_rewrite.targets, i64 0, i64 %i.next
271   %target.next = load ptr, ptr %target.i.next
272   ; Potentially hit a full 10 successors here so that even if we rewrite as
273   ; a switch it will try to be lowered with a jump table.
274   indirectbr ptr %target.next, [label %bb0,
275                                 label %bb1,
276                                 label %bb2,
277                                 label %bb3,
278                                 label %bb4,
279                                 label %bb5,
280                                 label %bb6,
281                                 label %bb7,
282                                 label %bb8,
283                                 label %bb9]
286 ; Lastly check that the necessary thunks were emitted.
288 ; X64-LABEL:         .section        .text.__llvm_lvi_thunk_r11,{{.*}},__llvm_lvi_thunk_r11,comdat
289 ; X64-NEXT:          .hidden __llvm_lvi_thunk_r11
290 ; X64-NEXT:          .weak   __llvm_lvi_thunk_r11
291 ; X64:       __llvm_lvi_thunk_r11:
292 ; X64-NEXT:  # {{.*}}                                # %entry
293 ; X64-NEXT:          lfence
294 ; X64-NEXT:          jmpq     *%r11
296 attributes #1 = { nonlazybind }
298 !llvm.module.flags = !{!0}
300 !0 = !{i32 4, !"indirect_branch_cs_prefix", i32 1}