[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / X86 / lvi-hardening-indirectbr.ll
blob57bfca2ac07239d0e279a7365750b4a3054b5747
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(void (i32)* %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:       callq __llvm_lvi_thunk_r11
26 ; X64:       movl %[[x]], %edi
27 ; X64:       callq bar
28 ; X64-DAG:   movl %[[x]], %edi
29 ; X64-DAG:   movq %[[fp]], %r11
30 ; X64:       jmp __llvm_lvi_thunk_r11 # TAILCALL
32 ; X64FAST-LABEL: icall_reg:
33 ; X64FAST:       callq bar
34 ; X64FAST:       callq __llvm_lvi_thunk_r11
35 ; X64FAST:       callq bar
36 ; X64FAST:       jmp __llvm_lvi_thunk_r11 # TAILCALL
39 @global_fp = external dso_local global void (i32)*
41 ; Test an indirect call through a global variable.
42 define void @icall_global_fp(i32 %x, void (i32)** %fpp) #0 {
43   %fp1 = load void (i32)*, void (i32)** @global_fp
44   call void %fp1(i32 %x)
45   %fp2 = load void (i32)*, void (i32)** @global_fp
46   tail call void %fp2(i32 %x)
47   ret void
50 ; X64-LABEL: icall_global_fp:
51 ; X64-DAG:   movl %edi, %[[x:[^ ]*]]
52 ; X64-DAG:   movq global_fp(%rip), %r11
53 ; X64:       callq __llvm_lvi_thunk_r11
54 ; X64-DAG:   movl %[[x]], %edi
55 ; X64-DAG:   movq global_fp(%rip), %r11
56 ; X64:       jmp __llvm_lvi_thunk_r11 # TAILCALL
58 ; X64FAST-LABEL: icall_global_fp:
59 ; X64FAST:       movq global_fp(%rip), %r11
60 ; X64FAST:       callq __llvm_lvi_thunk_r11
61 ; X64FAST:       movq global_fp(%rip), %r11
62 ; X64FAST:       jmp __llvm_lvi_thunk_r11 # TAILCALL
65 %struct.Foo = type { void (%struct.Foo*)** }
67 ; Test an indirect call through a vtable.
68 define void @vcall(%struct.Foo* %obj) #0 {
69   %vptr_field = getelementptr %struct.Foo, %struct.Foo* %obj, i32 0, i32 0
70   %vptr = load void (%struct.Foo*)**, void (%struct.Foo*)*** %vptr_field
71   %vslot = getelementptr void(%struct.Foo*)*, void(%struct.Foo*)** %vptr, i32 1
72   %fp = load void(%struct.Foo*)*, void(%struct.Foo*)** %vslot
73   tail call void %fp(%struct.Foo* %obj)
74   tail call void %fp(%struct.Foo* %obj)
75   ret void
78 ; X64-LABEL: vcall:
79 ; X64:       movq %rdi, %[[obj:[^ ]*]]
80 ; X64:       movq (%rdi), %[[vptr:[^ ]*]]
81 ; X64:       movq 8(%[[vptr]]), %[[fp:[^ ]*]]
82 ; X64:       movq %[[fp]], %r11
83 ; X64:       callq __llvm_lvi_thunk_r11
84 ; X64-DAG:   movq %[[obj]], %rdi
85 ; X64-DAG:   movq %[[fp]], %r11
86 ; X64:       jmp __llvm_lvi_thunk_r11 # TAILCALL
88 ; X64FAST-LABEL: vcall:
89 ; X64FAST:       callq __llvm_lvi_thunk_r11
90 ; X64FAST:       jmp __llvm_lvi_thunk_r11 # TAILCALL
93 declare dso_local void @direct_callee()
95 define void @direct_tail() #0 {
96   tail call void @direct_callee()
97   ret void
100 ; X64-LABEL: direct_tail:
101 ; X64:       jmp direct_callee # TAILCALL
102 ; X64FAST-LABEL: direct_tail:
103 ; X64FAST:   jmp direct_callee # TAILCALL
106 declare void @nonlazybind_callee() #1
108 define void @nonlazybind_caller() #0 {
109   call void @nonlazybind_callee()
110   tail call void @nonlazybind_callee()
111   ret void
114 ; X64-LABEL: nonlazybind_caller:
115 ; X64:       movq nonlazybind_callee@GOTPCREL(%rip), %[[REG:.*]]
116 ; X64:       movq %[[REG]], %r11
117 ; X64:       callq __llvm_lvi_thunk_r11
118 ; X64:       movq %[[REG]], %r11
119 ; X64:       jmp __llvm_lvi_thunk_r11 # TAILCALL
120 ; X64FAST-LABEL: nonlazybind_caller:
121 ; X64FAST:   movq nonlazybind_callee@GOTPCREL(%rip), %r11
122 ; X64FAST:   callq __llvm_lvi_thunk_r11
123 ; X64FAST:   movq nonlazybind_callee@GOTPCREL(%rip), %r11
124 ; X64FAST:   jmp __llvm_lvi_thunk_r11 # TAILCALL
127 ; Check that a switch gets lowered using a jump table
128 define void @switch_jumptable(i32* %ptr, i64* %sink) #0 {
129 ; X64-LABEL: switch_jumptable:
130 ; X64_NOT:      jmpq *
131 entry:
132   br label %header
134 header:
135   %i = load volatile i32, i32* %ptr
136   switch i32 %i, label %bb0 [
137     i32 1, label %bb1
138     i32 2, label %bb2
139     i32 3, label %bb3
140     i32 4, label %bb4
141     i32 5, label %bb5
142     i32 6, label %bb6
143     i32 7, label %bb7
144     i32 8, label %bb8
145     i32 9, label %bb9
146   ]
148 bb0:
149   store volatile i64 0, i64* %sink
150   br label %header
152 bb1:
153   store volatile i64 1, i64* %sink
154   br label %header
156 bb2:
157   store volatile i64 2, i64* %sink
158   br label %header
160 bb3:
161   store volatile i64 3, i64* %sink
162   br label %header
164 bb4:
165   store volatile i64 4, i64* %sink
166   br label %header
168 bb5:
169   store volatile i64 5, i64* %sink
170   br label %header
172 bb6:
173   store volatile i64 6, i64* %sink
174   br label %header
176 bb7:
177   store volatile i64 7, i64* %sink
178   br label %header
180 bb8:
181   store volatile i64 8, i64* %sink
182   br label %header
184 bb9:
185   store volatile i64 9, i64* %sink
186   br label %header
190 @indirectbr_rewrite.targets = constant [10 x i8*] [i8* blockaddress(@indirectbr_rewrite, %bb0),
191                                                    i8* blockaddress(@indirectbr_rewrite, %bb1),
192                                                    i8* blockaddress(@indirectbr_rewrite, %bb2),
193                                                    i8* blockaddress(@indirectbr_rewrite, %bb3),
194                                                    i8* blockaddress(@indirectbr_rewrite, %bb4),
195                                                    i8* blockaddress(@indirectbr_rewrite, %bb5),
196                                                    i8* blockaddress(@indirectbr_rewrite, %bb6),
197                                                    i8* blockaddress(@indirectbr_rewrite, %bb7),
198                                                    i8* blockaddress(@indirectbr_rewrite, %bb8),
199                                                    i8* blockaddress(@indirectbr_rewrite, %bb9)]
201 ; Check that when thunks are enabled the indirectbr instruction gets
202 ; rewritten to use switch, and that in turn doesn't get lowered as a jump
203 ; table.
204 define void @indirectbr_rewrite(i64* readonly %p, i64* %sink) #0 {
205 ; X64-LABEL: indirectbr_rewrite:
206 ; X64-NOT:     jmpq *
207 entry:
208   %i0 = load i64, i64* %p
209   %target.i0 = getelementptr [10 x i8*], [10 x i8*]* @indirectbr_rewrite.targets, i64 0, i64 %i0
210   %target0 = load i8*, i8** %target.i0
211   indirectbr i8* %target0, [label %bb1, label %bb3]
213 bb0:
214   store volatile i64 0, i64* %sink
215   br label %latch
217 bb1:
218   store volatile i64 1, i64* %sink
219   br label %latch
221 bb2:
222   store volatile i64 2, i64* %sink
223   br label %latch
225 bb3:
226   store volatile i64 3, i64* %sink
227   br label %latch
229 bb4:
230   store volatile i64 4, i64* %sink
231   br label %latch
233 bb5:
234   store volatile i64 5, i64* %sink
235   br label %latch
237 bb6:
238   store volatile i64 6, i64* %sink
239   br label %latch
241 bb7:
242   store volatile i64 7, i64* %sink
243   br label %latch
245 bb8:
246   store volatile i64 8, i64* %sink
247   br label %latch
249 bb9:
250   store volatile i64 9, i64* %sink
251   br label %latch
253 latch:
254   %i.next = load i64, i64* %p
255   %target.i.next = getelementptr [10 x i8*], [10 x i8*]* @indirectbr_rewrite.targets, i64 0, i64 %i.next
256   %target.next = load i8*, i8** %target.i.next
257   ; Potentially hit a full 10 successors here so that even if we rewrite as
258   ; a switch it will try to be lowered with a jump table.
259   indirectbr i8* %target.next, [label %bb0,
260                                 label %bb1,
261                                 label %bb2,
262                                 label %bb3,
263                                 label %bb4,
264                                 label %bb5,
265                                 label %bb6,
266                                 label %bb7,
267                                 label %bb8,
268                                 label %bb9]
271 ; Lastly check that the necessary thunks were emitted.
273 ; X64-LABEL:         .section        .text.__llvm_lvi_thunk_r11,{{.*}},__llvm_lvi_thunk_r11,comdat
274 ; X64-NEXT:          .hidden __llvm_lvi_thunk_r11
275 ; X64-NEXT:          .weak   __llvm_lvi_thunk_r11
276 ; X64:       __llvm_lvi_thunk_r11:
277 ; X64-NEXT:  # {{.*}}                                # %entry
278 ; X64-NEXT:          lfence
279 ; X64-NEXT:          jmpq     *%r11
281 attributes #1 = { nonlazybind }