Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / AArch64 / cfguard-checks.ll
blob12491632808208494f617b8d095ecc5d0052c5f6
1 ; RUN: llc < %s -mtriple=aarch64-pc-windows-msvc | FileCheck %s
2 ; RUN: llc < %s -mtriple=aarch64-w64-windows-gnu | FileCheck %s
3 ; Control Flow Guard is currently only available on Windows
5 ; Test that Control Flow Guard checks are correctly added when required.
8 declare i32 @target_func()
11 ; Test that Control Flow Guard checks are not added on calls with the "guard_nocf" attribute.
12 define i32 @func_guard_nocf() {
13 entry:
14   %func_ptr = alloca ptr, align 8
15   store ptr @target_func, ptr %func_ptr, align 8
16   %0 = load ptr, ptr %func_ptr, align 8
17   %1 = call i32 %0() #0
18   ret i32 %1
20   ; CHECK-LABEL: func_guard_nocf
21   ; CHECK:       adrp x8, target_func
22         ; CHECK:       add x8, x8, :lo12:target_func
23   ; CHECK-NOT:   __guard_check_icall_fptr
24         ; CHECK:       blr x8
26 attributes #0 = { "guard_nocf" }
29 ; Test that Control Flow Guard checks are added even at -O0.
30 define i32 @func_optnone_cf() #1 {
31 entry:
32   %func_ptr = alloca ptr, align 8
33   store ptr @target_func, ptr %func_ptr, align 8
34   %0 = load ptr, ptr %func_ptr, align 8
35   %1 = call i32 %0()
36   ret i32 %1
38   ; The call to __guard_check_icall_fptr should come immediately before the call to the target function.
39   ; CHECK-LABEL: func_optnone_cf
40         ; CHECK:        adrp x8, target_func
41         ; CHECK:        add x8, x8, :lo12:target_func
42         ; CHECK:        adrp x9, __guard_check_icall_fptr
43         ; CHECK:        add x9, x9, :lo12:__guard_check_icall_fptr
44         ; CHECK:        ldr x9, [x9]
45         ; CHECK:        mov x15, x8
46         ; CHECK:        blr x9
47         ; CHECK-NEXT:   blr x8
49 attributes #1 = { noinline optnone }
52 ; Test that Control Flow Guard checks are correctly added in optimized code (common case).
53 define i32 @func_cf() {
54 entry:
55   %func_ptr = alloca ptr, align 8
56   store ptr @target_func, ptr %func_ptr, align 8
57   %0 = load ptr, ptr %func_ptr, align 8
58   %1 = call i32 %0()
59   ret i32 %1
61   ; The call to __guard_check_icall_fptr should come immediately before the call to the target function.
62   ; CHECK-LABEL: func_cf
63   ; CHECK:        adrp x8, __guard_check_icall_fptr
64         ; CHECK:        ldr x9, [x8, :lo12:__guard_check_icall_fptr]
65         ; CHECK:        adrp x8, target_func
66         ; CHECK:        add x8, x8, :lo12:target_func
67         ; CHECK:        mov x15, x8
68         ; CHECK:                blr x9
69         ; CHECK-NEXT:   blr x8
73 ; Test that Control Flow Guard checks are correctly added on invoke instructions.
74 define i32 @func_cf_invoke() personality ptr @h {
75 entry:
76   %0 = alloca i32, align 4
77   %func_ptr = alloca ptr, align 8
78   store ptr @target_func, ptr %func_ptr, align 8
79   %1 = load ptr, ptr %func_ptr, align 8
80   %2 = invoke i32 %1()
81           to label %invoke.cont unwind label %lpad
82 invoke.cont:                                      ; preds = %entry
83   ret i32 %2
85 lpad:                                             ; preds = %entry
86   %tmp = landingpad { ptr, i32 }
87           catch ptr null
88   ret i32 -1
90   ; The call to __guard_check_icall_fptr should come immediately before the call to the target function.
91   ; CHECK-LABEL: func_cf_invoke
92   ; CHECK:        adrp x8, __guard_check_icall_fptr
93         ; CHECK:        ldr x9, [x8, :lo12:__guard_check_icall_fptr]
94         ; CHECK:        adrp x8, target_func
95         ; CHECK:        add x8, x8, :lo12:target_func
96         ; CHECK:        mov x15, x8
97         ; CHECK:        blr x9
98   ; CHECK-NEXT:   .Ltmp0:
99         ; CHECK-NEXT:   blr x8
100   ; CHECK:       // %common.ret
101   ; CHECK:       // %lpad
104 declare void @h()
107 ; Test that longjmp targets have public labels and are included in the .gljmp section.
108 %struct._SETJMP_FLOAT128 = type { [2 x i64] }
109 @buf1 = internal global [16 x %struct._SETJMP_FLOAT128] zeroinitializer, align 16
111 define i32 @func_cf_setjmp() {
112   %1 = alloca i32, align 4
113   %2 = alloca i32, align 4
114   store i32 0, ptr %1, align 4
115   store i32 -1, ptr %2, align 4
116   %3 = call ptr @llvm.frameaddress(i32 0)
117   %4 = call i32 @_setjmp(ptr @buf1, ptr %3) #2
119   ; CHECK-LABEL: func_cf_setjmp
120   ; CHECK:       bl _setjmp
121   ; CHECK-NEXT:  $cfgsj_func_cf_setjmp0:
123   %5 = call ptr @llvm.frameaddress(i32 0)
124   %6 = call i32 @_setjmp(ptr @buf1, ptr %5) #3
126   ; CHECK:       bl _setjmp
127   ; CHECK-NEXT:  $cfgsj_func_cf_setjmp1:
129   store i32 1, ptr %2, align 4
130   %7 = load i32, ptr %2, align 4
131   ret i32 %7
133   ; CHECK:       .section .gljmp$y,"dr"
134   ; CHECK-NEXT:  .symidx $cfgsj_func_cf_setjmp0
135   ; CHECK-NEXT:  .symidx $cfgsj_func_cf_setjmp1
138 declare ptr @llvm.frameaddress(i32)
140 ; Function Attrs: returns_twice
141 declare dso_local i32 @_setjmp(ptr, ptr) #2
143 attributes #2 = { returns_twice }
144 attributes #3 = { returns_twice }
147 !llvm.module.flags = !{!0}
148 !0 = !{i32 2, !"cfguard", i32 2}