• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -x86-speculative-load-hardening -data-sections | FileCheck %s --check-prefix=X64
3; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -x86-speculative-load-hardening -data-sections -mattr=+retpoline | FileCheck %s --check-prefix=X64-RETPOLINE
4;
5; FIXME: Add support for 32-bit.
6
7@global_fnptr = external global i32 ()*
8
9@global_blockaddrs = constant [4 x i8*] [
10  i8* blockaddress(@test_indirectbr_global, %bb0),
11  i8* blockaddress(@test_indirectbr_global, %bb1),
12  i8* blockaddress(@test_indirectbr_global, %bb2),
13  i8* blockaddress(@test_indirectbr_global, %bb3)
14]
15
16define i32 @test_indirect_call(i32 ()** %ptr) nounwind {
17; X64-LABEL: test_indirect_call:
18; X64:       # %bb.0: # %entry
19; X64-NEXT:    pushq %rax
20; X64-NEXT:    movq %rsp, %rax
21; X64-NEXT:    movq $-1, %rcx
22; X64-NEXT:    sarq $63, %rax
23; X64-NEXT:    movq (%rdi), %rcx
24; X64-NEXT:    orq %rax, %rcx
25; X64-NEXT:    shlq $47, %rax
26; X64-NEXT:    orq %rax, %rsp
27; X64-NEXT:    callq *%rcx
28; X64-NEXT:    movq %rsp, %rcx
29; X64-NEXT:    sarq $63, %rcx
30; X64-NEXT:    shlq $47, %rcx
31; X64-NEXT:    orq %rcx, %rsp
32; X64-NEXT:    popq %rcx
33; X64-NEXT:    retq
34;
35; X64-RETPOLINE-LABEL: test_indirect_call:
36; X64-RETPOLINE:       # %bb.0: # %entry
37; X64-RETPOLINE-NEXT:    pushq %rax
38; X64-RETPOLINE-NEXT:    movq %rsp, %rax
39; X64-RETPOLINE-NEXT:    movq $-1, %rcx
40; X64-RETPOLINE-NEXT:    sarq $63, %rax
41; X64-RETPOLINE-NEXT:    movq (%rdi), %r11
42; X64-RETPOLINE-NEXT:    orq %rax, %r11
43; X64-RETPOLINE-NEXT:    shlq $47, %rax
44; X64-RETPOLINE-NEXT:    orq %rax, %rsp
45; X64-RETPOLINE-NEXT:    callq __llvm_retpoline_r11
46; X64-RETPOLINE-NEXT:    movq %rsp, %rcx
47; X64-RETPOLINE-NEXT:    sarq $63, %rcx
48; X64-RETPOLINE-NEXT:    shlq $47, %rcx
49; X64-RETPOLINE-NEXT:    orq %rcx, %rsp
50; X64-RETPOLINE-NEXT:    popq %rcx
51; X64-RETPOLINE-NEXT:    retq
52entry:
53  %fp = load i32 ()*, i32 ()** %ptr
54  %v = call i32 %fp()
55  ret i32 %v
56}
57
58define i32 @test_indirect_tail_call(i32 ()** %ptr) nounwind {
59; X64-LABEL: test_indirect_tail_call:
60; X64:       # %bb.0: # %entry
61; X64-NEXT:    movq %rsp, %rax
62; X64-NEXT:    movq $-1, %rcx
63; X64-NEXT:    sarq $63, %rax
64; X64-NEXT:    movq (%rdi), %rcx
65; X64-NEXT:    orq %rax, %rcx
66; X64-NEXT:    shlq $47, %rax
67; X64-NEXT:    orq %rax, %rsp
68; X64-NEXT:    jmpq *%rcx # TAILCALL
69;
70; X64-RETPOLINE-LABEL: test_indirect_tail_call:
71; X64-RETPOLINE:       # %bb.0: # %entry
72; X64-RETPOLINE-NEXT:    movq %rsp, %rax
73; X64-RETPOLINE-NEXT:    movq $-1, %rcx
74; X64-RETPOLINE-NEXT:    sarq $63, %rax
75; X64-RETPOLINE-NEXT:    movq (%rdi), %r11
76; X64-RETPOLINE-NEXT:    orq %rax, %r11
77; X64-RETPOLINE-NEXT:    shlq $47, %rax
78; X64-RETPOLINE-NEXT:    orq %rax, %rsp
79; X64-RETPOLINE-NEXT:    jmp __llvm_retpoline_r11 # TAILCALL
80entry:
81  %fp = load i32 ()*, i32 ()** %ptr
82  %v = tail call i32 %fp()
83  ret i32 %v
84}
85
86define i32 @test_indirect_call_global() nounwind {
87; X64-LABEL: test_indirect_call_global:
88; X64:       # %bb.0: # %entry
89; X64-NEXT:    pushq %rax
90; X64-NEXT:    movq %rsp, %rax
91; X64-NEXT:    movq $-1, %rcx
92; X64-NEXT:    sarq $63, %rax
93; X64-NEXT:    movq {{.*}}(%rip), %rcx
94; X64-NEXT:    orq %rax, %rcx
95; X64-NEXT:    shlq $47, %rax
96; X64-NEXT:    orq %rax, %rsp
97; X64-NEXT:    callq *%rcx
98; X64-NEXT:    movq %rsp, %rcx
99; X64-NEXT:    sarq $63, %rcx
100; X64-NEXT:    shlq $47, %rcx
101; X64-NEXT:    orq %rcx, %rsp
102; X64-NEXT:    popq %rcx
103; X64-NEXT:    retq
104;
105; X64-RETPOLINE-LABEL: test_indirect_call_global:
106; X64-RETPOLINE:       # %bb.0: # %entry
107; X64-RETPOLINE-NEXT:    pushq %rax
108; X64-RETPOLINE-NEXT:    movq %rsp, %rax
109; X64-RETPOLINE-NEXT:    movq $-1, %rcx
110; X64-RETPOLINE-NEXT:    sarq $63, %rax
111; X64-RETPOLINE-NEXT:    movq {{.*}}(%rip), %r11
112; X64-RETPOLINE-NEXT:    shlq $47, %rax
113; X64-RETPOLINE-NEXT:    orq %rax, %rsp
114; X64-RETPOLINE-NEXT:    callq __llvm_retpoline_r11
115; X64-RETPOLINE-NEXT:    movq %rsp, %rcx
116; X64-RETPOLINE-NEXT:    sarq $63, %rcx
117; X64-RETPOLINE-NEXT:    shlq $47, %rcx
118; X64-RETPOLINE-NEXT:    orq %rcx, %rsp
119; X64-RETPOLINE-NEXT:    popq %rcx
120; X64-RETPOLINE-NEXT:    retq
121entry:
122  %fp = load i32 ()*, i32 ()** @global_fnptr
123  %v = call i32 %fp()
124  ret i32 %v
125}
126
127define i32 @test_indirect_tail_call_global() nounwind {
128; X64-LABEL: test_indirect_tail_call_global:
129; X64:       # %bb.0: # %entry
130; X64-NEXT:    movq %rsp, %rax
131; X64-NEXT:    movq $-1, %rcx
132; X64-NEXT:    sarq $63, %rax
133; X64-NEXT:    movq {{.*}}(%rip), %rcx
134; X64-NEXT:    orq %rax, %rcx
135; X64-NEXT:    shlq $47, %rax
136; X64-NEXT:    orq %rax, %rsp
137; X64-NEXT:    jmpq *%rcx # TAILCALL
138;
139; X64-RETPOLINE-LABEL: test_indirect_tail_call_global:
140; X64-RETPOLINE:       # %bb.0: # %entry
141; X64-RETPOLINE-NEXT:    movq %rsp, %rax
142; X64-RETPOLINE-NEXT:    movq $-1, %rcx
143; X64-RETPOLINE-NEXT:    sarq $63, %rax
144; X64-RETPOLINE-NEXT:    movq {{.*}}(%rip), %r11
145; X64-RETPOLINE-NEXT:    shlq $47, %rax
146; X64-RETPOLINE-NEXT:    orq %rax, %rsp
147; X64-RETPOLINE-NEXT:    jmp __llvm_retpoline_r11 # TAILCALL
148entry:
149  %fp = load i32 ()*, i32 ()** @global_fnptr
150  %v = tail call i32 %fp()
151  ret i32 %v
152}
153
154define i32 @test_indirectbr(i8** %ptr) nounwind {
155; X64-LABEL: test_indirectbr:
156; X64:       # %bb.0: # %entry
157; X64-NEXT:    movq %rsp, %rcx
158; X64-NEXT:    movq $-1, %rax
159; X64-NEXT:    sarq $63, %rcx
160; X64-NEXT:    movq (%rdi), %rax
161; X64-NEXT:    orq %rcx, %rax
162; X64-NEXT:    jmpq *%rax
163; X64-NEXT:  .LBB4_1: # %bb0
164; X64-NEXT:    movl $2, %eax
165; X64-NEXT:    jmp .LBB4_2
166; X64-NEXT:  .LBB4_4: # %bb2
167; X64-NEXT:    movl $13, %eax
168; X64-NEXT:    jmp .LBB4_2
169; X64-NEXT:  .LBB4_5: # %bb3
170; X64-NEXT:    movl $42, %eax
171; X64-NEXT:    jmp .LBB4_2
172; X64-NEXT:  .LBB4_3: # %bb1
173; X64-NEXT:    movl $7, %eax
174; X64-NEXT:  .LBB4_2: # %bb0
175; X64-NEXT:    shlq $47, %rcx
176; X64-NEXT:    orq %rcx, %rsp
177; X64-NEXT:    retq
178;
179; X64-RETPOLINE-LABEL: test_indirectbr:
180; X64-RETPOLINE:       # %bb.0: # %entry
181entry:
182  %a = load i8*, i8** %ptr
183  indirectbr i8* %a, [ label %bb0, label %bb1, label %bb2, label %bb3 ]
184
185bb0:
186  ret i32 2
187
188bb1:
189  ret i32 7
190
191bb2:
192  ret i32 13
193
194bb3:
195  ret i32 42
196}
197
198define i32 @test_indirectbr_global(i32 %idx) nounwind {
199; X64-LABEL: test_indirectbr_global:
200; X64:       # %bb.0: # %entry
201; X64-NEXT:    movq %rsp, %rcx
202; X64-NEXT:    movq $-1, %rax
203; X64-NEXT:    sarq $63, %rcx
204; X64-NEXT:    movslq %edi, %rax
205; X64-NEXT:    movq global_blockaddrs(,%rax,8), %rax
206; X64-NEXT:    orq %rcx, %rax
207; X64-NEXT:    jmpq *%rax
208; X64-NEXT:  .Ltmp0: # Block address taken
209; X64-NEXT:  .LBB5_1: # %bb0
210; X64-NEXT:    movl $2, %eax
211; X64-NEXT:    jmp .LBB5_2
212; X64-NEXT:  .Ltmp1: # Block address taken
213; X64-NEXT:  .LBB5_4: # %bb2
214; X64-NEXT:    movl $13, %eax
215; X64-NEXT:    jmp .LBB5_2
216; X64-NEXT:  .Ltmp2: # Block address taken
217; X64-NEXT:  .LBB5_5: # %bb3
218; X64-NEXT:    movl $42, %eax
219; X64-NEXT:    jmp .LBB5_2
220; X64-NEXT:  .Ltmp3: # Block address taken
221; X64-NEXT:  .LBB5_3: # %bb1
222; X64-NEXT:    movl $7, %eax
223; X64-NEXT:  .LBB5_2: # %bb0
224; X64-NEXT:    shlq $47, %rcx
225; X64-NEXT:    orq %rcx, %rsp
226; X64-NEXT:    retq
227;
228; X64-RETPOLINE-LABEL: test_indirectbr_global:
229; X64-RETPOLINE:       # %bb.0: # %entry
230; X64-RETPOLINE-NEXT:    movq %rsp, %rcx
231; X64-RETPOLINE-NEXT:    movq $-1, %rax
232; X64-RETPOLINE-NEXT:    sarq $63, %rcx
233; X64-RETPOLINE-NEXT:    movslq %edi, %rdx
234; X64-RETPOLINE-NEXT:    movq global_blockaddrs(,%rdx,8), %rdx
235; X64-RETPOLINE-NEXT:    orq %rcx, %rdx
236; X64-RETPOLINE-NEXT:    cmpq $2, %rdx
237; X64-RETPOLINE-NEXT:    je .LBB6_5
238; X64-RETPOLINE-NEXT:  # %bb.1: # %entry
239; X64-RETPOLINE-NEXT:    cmoveq %rax, %rcx
240; X64-RETPOLINE-NEXT:    cmpq $3, %rdx
241; X64-RETPOLINE-NEXT:    je .LBB6_6
242; X64-RETPOLINE-NEXT:  # %bb.2: # %entry
243; X64-RETPOLINE-NEXT:    cmoveq %rax, %rcx
244; X64-RETPOLINE-NEXT:    cmpq $4, %rdx
245; X64-RETPOLINE-NEXT:    jne .LBB6_3
246; X64-RETPOLINE-NEXT:  .Ltmp0: # Block address taken
247; X64-RETPOLINE-NEXT:  # %bb.7: # %bb3
248; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
249; X64-RETPOLINE-NEXT:    movl $42, %eax
250; X64-RETPOLINE-NEXT:    jmp .LBB6_4
251; X64-RETPOLINE-NEXT:  .Ltmp1: # Block address taken
252; X64-RETPOLINE-NEXT:  .LBB6_5: # %bb1
253; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
254; X64-RETPOLINE-NEXT:    movl $7, %eax
255; X64-RETPOLINE-NEXT:    jmp .LBB6_4
256; X64-RETPOLINE-NEXT:  .Ltmp2: # Block address taken
257; X64-RETPOLINE-NEXT:  .LBB6_6: # %bb2
258; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
259; X64-RETPOLINE-NEXT:    movl $13, %eax
260; X64-RETPOLINE-NEXT:    jmp .LBB6_4
261; X64-RETPOLINE-NEXT:  .Ltmp3: # Block address taken
262; X64-RETPOLINE-NEXT:  .LBB6_3: # %bb0
263; X64-RETPOLINE-NEXT:    cmoveq %rax, %rcx
264; X64-RETPOLINE-NEXT:    movl $2, %eax
265; X64-RETPOLINE-NEXT:  .LBB6_4: # %bb0
266; X64-RETPOLINE-NEXT:    shlq $47, %rcx
267; X64-RETPOLINE-NEXT:    orq %rcx, %rsp
268; X64-RETPOLINE-NEXT:    retq
269entry:
270  %ptr = getelementptr [4 x i8*], [4 x i8*]* @global_blockaddrs, i32 0, i32 %idx
271  %a = load i8*, i8** %ptr
272  indirectbr i8* %a, [ label %bb0, label %bb1, label %bb2, label %bb3 ]
273
274bb0:
275  ret i32 2
276
277bb1:
278  ret i32 7
279
280bb2:
281  ret i32 13
282
283bb3:
284  ret i32 42
285}
286
287; This function's switch is crafted to trigger jump-table lowering in the x86
288; backend so that we can test how the exact jump table lowering behaves.
289define i32 @test_switch_jumptable(i32 %idx) nounwind {
290; X64-LABEL: test_switch_jumptable:
291; X64:       # %bb.0: # %entry
292; X64-NEXT:    movq %rsp, %rcx
293; X64-NEXT:    movq $-1, %rax
294; X64-NEXT:    sarq $63, %rcx
295; X64-NEXT:    cmpl $3, %edi
296; X64-NEXT:    ja .LBB6_2
297; X64-NEXT:  # %bb.1: # %entry
298; X64-NEXT:    cmovaq %rax, %rcx
299; X64-NEXT:    movl %edi, %eax
300; X64-NEXT:    movq .LJTI6_0(,%rax,8), %rax
301; X64-NEXT:    orq %rcx, %rax
302; X64-NEXT:    jmpq *%rax
303; X64-NEXT:  .LBB6_3: # %bb1
304; X64-NEXT:    movl $7, %eax
305; X64-NEXT:    jmp .LBB6_4
306; X64-NEXT:  .LBB6_2: # %bb0
307; X64-NEXT:    cmovbeq %rax, %rcx
308; X64-NEXT:    movl $2, %eax
309; X64-NEXT:    jmp .LBB6_4
310; X64-NEXT:  .LBB6_5: # %bb2
311; X64-NEXT:    movl $13, %eax
312; X64-NEXT:    jmp .LBB6_4
313; X64-NEXT:  .LBB6_6: # %bb3
314; X64-NEXT:    movl $42, %eax
315; X64-NEXT:    jmp .LBB6_4
316; X64-NEXT:  .LBB6_7: # %bb5
317; X64-NEXT:    movl $11, %eax
318; X64-NEXT:  .LBB6_4: # %bb1
319; X64-NEXT:    shlq $47, %rcx
320; X64-NEXT:    orq %rcx, %rsp
321; X64-NEXT:    retq
322;
323; X64-RETPOLINE-LABEL: test_switch_jumptable:
324; X64-RETPOLINE:       # %bb.0: # %entry
325; X64-RETPOLINE-NEXT:    movq %rsp, %rcx
326; X64-RETPOLINE-NEXT:    movq $-1, %rax
327; X64-RETPOLINE-NEXT:    sarq $63, %rcx
328; X64-RETPOLINE-NEXT:    cmpl $1, %edi
329; X64-RETPOLINE-NEXT:    jg .LBB7_4
330; X64-RETPOLINE-NEXT:  # %bb.1: # %entry
331; X64-RETPOLINE-NEXT:    cmovgq %rax, %rcx
332; X64-RETPOLINE-NEXT:    testl %edi, %edi
333; X64-RETPOLINE-NEXT:    je .LBB7_8
334; X64-RETPOLINE-NEXT:  # %bb.2: # %entry
335; X64-RETPOLINE-NEXT:    cmoveq %rax, %rcx
336; X64-RETPOLINE-NEXT:    cmpl $1, %edi
337; X64-RETPOLINE-NEXT:    jne .LBB7_6
338; X64-RETPOLINE-NEXT:  # %bb.3: # %bb2
339; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
340; X64-RETPOLINE-NEXT:    movl $13, %eax
341; X64-RETPOLINE-NEXT:    jmp .LBB7_7
342; X64-RETPOLINE-NEXT:  .LBB7_4: # %entry
343; X64-RETPOLINE-NEXT:    cmovleq %rax, %rcx
344; X64-RETPOLINE-NEXT:    cmpl $2, %edi
345; X64-RETPOLINE-NEXT:    je .LBB7_9
346; X64-RETPOLINE-NEXT:  # %bb.5: # %entry
347; X64-RETPOLINE-NEXT:    cmoveq %rax, %rcx
348; X64-RETPOLINE-NEXT:    cmpl $3, %edi
349; X64-RETPOLINE-NEXT:    jne .LBB7_6
350; X64-RETPOLINE-NEXT:  # %bb.10: # %bb5
351; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
352; X64-RETPOLINE-NEXT:    movl $11, %eax
353; X64-RETPOLINE-NEXT:    jmp .LBB7_7
354; X64-RETPOLINE-NEXT:  .LBB7_6:
355; X64-RETPOLINE-NEXT:    cmoveq %rax, %rcx
356; X64-RETPOLINE-NEXT:    movl $2, %eax
357; X64-RETPOLINE-NEXT:    jmp .LBB7_7
358; X64-RETPOLINE-NEXT:  .LBB7_8: # %bb1
359; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
360; X64-RETPOLINE-NEXT:    movl $7, %eax
361; X64-RETPOLINE-NEXT:    jmp .LBB7_7
362; X64-RETPOLINE-NEXT:  .LBB7_9: # %bb3
363; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
364; X64-RETPOLINE-NEXT:    movl $42, %eax
365; X64-RETPOLINE-NEXT:  .LBB7_7: # %bb0
366; X64-RETPOLINE-NEXT:    shlq $47, %rcx
367; X64-RETPOLINE-NEXT:    orq %rcx, %rsp
368; X64-RETPOLINE-NEXT:    retq
369entry:
370  switch i32 %idx, label %bb0 [
371    i32 0, label %bb1
372    i32 1, label %bb2
373    i32 2, label %bb3
374    i32 3, label %bb5
375  ]
376
377bb0:
378  ret i32 2
379
380bb1:
381  ret i32 7
382
383bb2:
384  ret i32 13
385
386bb3:
387  ret i32 42
388
389bb5:
390  ret i32 11
391}
392