1 ; RUN: llc < %s -mtriple=i686-pc-windows-msvc | FileCheck %s -check-prefix=X32
2 ; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s -check-prefixes=X64,X64_MSVC
3 ; RUN: llc < %s -mtriple=i686-w64-windows-gnu | FileCheck %s -check-prefixes=X32,X32_MINGW
4 ; RUN: llc < %s -mtriple=x86_64-w64-windows-gnu | FileCheck %s -check-prefixes=X64,X64_MINGW
5 ; Control Flow Guard is currently only available on Windows
7 ; Test that Control Flow Guard checks are correctly added when required.
10 declare i32 @target_func()
13 ; Test that Control Flow Guard checks are not added on calls with the "guard_nocf" attribute.
14 define i32 @func_guard_nocf() {
16 %func_ptr = alloca ptr, align 8
17 store ptr @target_func, ptr %func_ptr, align 8
18 %0 = load ptr, ptr %func_ptr, align 8
22 ; X32-LABEL: func_guard_nocf
23 ; X32: movl $_target_func, %eax
24 ; X32-NOT: __guard_check_icall_fptr
27 ; X64-LABEL: func_guard_nocf
28 ; X64: leaq target_func(%rip), %rax
29 ; X64-NOT: __guard_dispatch_icall_fptr
32 attributes #0 = { "guard_nocf" }
35 ; Test that Control Flow Guard checks are added even at -O0.
36 ; FIXME Ideally these checks should be added as a single call instruction, as in the optimized case.
37 define i32 @func_optnone_cf() #1 {
39 %func_ptr = alloca ptr, align 8
40 store ptr @target_func, ptr %func_ptr, align 8
41 %0 = load ptr, ptr %func_ptr, align 8
45 ; On i686, the call to __guard_check_icall_fptr should come immediately before the call to the target function.
46 ; X32-LABEL: func_optnone_cf
47 ; X32: leal _target_func, %eax
48 ; X32: movl %eax, (%esp)
49 ; X32: movl (%esp), %ecx
50 ; X32: calll *___guard_check_icall_fptr
51 ; X32-NEXT: calll *%ecx
53 ; On x86_64, __guard_dispatch_icall_fptr tail calls the function, so there should be only one call instruction.
54 ; X64-LABEL: func_optnone_cf
55 ; X64: leaq target_func(%rip), %rax
56 ; X64: movq __guard_dispatch_icall_fptr(%rip), %rcx
60 attributes #1 = { noinline optnone }
63 ; Test that Control Flow Guard checks are correctly added in optimized code (common case).
64 define i32 @func_cf() {
66 %func_ptr = alloca ptr, align 8
67 store ptr @target_func, ptr %func_ptr, align 8
68 %0 = load ptr, ptr %func_ptr, align 8
72 ; On i686, the call to __guard_check_icall_fptr should come immediately before the call to the target function.
74 ; X32: movl $_target_func, %esi
75 ; X32: movl $_target_func, %ecx
76 ; X32: calll *___guard_check_icall_fptr
77 ; X32-NEXT: calll *%esi
79 ; On x86_64, __guard_dispatch_icall_fptr tail calls the function, so there should be only one call instruction.
81 ; X64: leaq target_func(%rip), %rax
82 ; X64: callq *__guard_dispatch_icall_fptr(%rip)
87 ; Test that Control Flow Guard checks are correctly added on invoke instructions.
88 define i32 @func_cf_invoke() personality ptr @h {
90 %0 = alloca i32, align 4
91 %func_ptr = alloca ptr, align 8
92 store ptr @target_func, ptr %func_ptr, align 8
93 %1 = load ptr, ptr %func_ptr, align 8
95 to label %invoke.cont unwind label %lpad
96 invoke.cont: ; preds = %entry
99 lpad: ; preds = %entry
100 %tmp = landingpad { ptr, i32 }
104 ; On i686, the call to __guard_check_icall_fptr should come immediately before the call to the target function.
105 ; X32-LABEL: func_cf_invoke
106 ; X32: movl $_target_func, %esi
107 ; X32: movl $_target_func, %ecx
108 ; X32: calll *___guard_check_icall_fptr
109 ; X32_MINGW-NEXT: Ltmp0:
110 ; X32-NEXT: calll *%esi
111 ; X32: # %invoke.cont
114 ; On x86_64, __guard_dispatch_icall_fptr tail calls the function, so there should be only one call instruction.
115 ; X64-LABEL: func_cf_invoke
116 ; X64: leaq target_func(%rip), %rax
117 ; X64: callq *__guard_dispatch_icall_fptr(%rip)
119 ; X64: # %invoke.cont
126 ; Test that Control Flow Guard preserves floating point arguments.
127 declare double @target_func_doubles(double, double, double, double)
129 define double @func_cf_doubles() {
131 %func_ptr = alloca ptr, align 8
132 store ptr @target_func_doubles, ptr %func_ptr, align 8
133 %0 = load ptr, ptr %func_ptr, align 8
134 %1 = call double %0(double 1.000000e+00, double 2.000000e+00, double 3.000000e+00, double 4.000000e+00)
137 ; On i686, the call to __guard_check_icall_fptr should come immediately before the call to the target function.
138 ; X32-LABEL: func_cf_doubles
139 ; X32: movl $_target_func_doubles, %esi
140 ; X32: movl $_target_func_doubles, %ecx
141 ; X32: calll *___guard_check_icall_fptr
145 ; On x86_64, __guard_dispatch_icall_fptr tail calls the function, so there should be only one call instruction.
146 ; X64-LABEL: func_cf_doubles
147 ; X64: leaq target_func_doubles(%rip), %rax
148 ; X64_MSVC: movsd __real@3ff0000000000000(%rip), %xmm0
149 ; X64_MSVC: movsd __real@4000000000000000(%rip), %xmm1
150 ; X64_MSVC: movsd __real@4008000000000000(%rip), %xmm2
151 ; X64_MSVC: movsd __real@4010000000000000(%rip), %xmm3
152 ; X64_MINGW: movsd .LCPI4_0(%rip), %xmm0
153 ; X64_MINGW: movsd .LCPI4_1(%rip), %xmm1
154 ; X64_MINGW: movsd .LCPI4_2(%rip), %xmm2
155 ; X64_MINGW: movsd .LCPI4_3(%rip), %xmm3
156 ; X64: callq *__guard_dispatch_icall_fptr(%rip)
162 ; Test that Control Flow Guard checks are correctly added for tail calls.
163 define i32 @func_cf_tail() {
165 %func_ptr = alloca ptr, align 8
166 store ptr @target_func, ptr %func_ptr, align 8
167 %0 = load ptr, ptr %func_ptr, align 8
168 %1 = musttail call i32 %0()
171 ; On i686, the call to __guard_check_icall_fptr should come immediately before the call to the target function.
172 ; X32-LABEL: func_cf_tail
173 ; X32: movl $_target_func, %ecx
174 ; X32: calll *___guard_check_icall_fptr
175 ; X32: movl $_target_func, %eax
176 ; X32: jmpl *%eax # TAILCALL
179 ; X64-LABEL: func_cf_tail
180 ; X64: leaq target_func(%rip), %rax
181 ; X64: rex64 jmpq *__guard_dispatch_icall_fptr(%rip) # TAILCALL
186 %struct.Foo = type { ptr }
188 ; Test that Control Flow Guard checks are correctly added for variadic musttail
189 ; calls. These are used for MS C++ ABI virtual member pointer thunks.
191 define i32 @vmptr_thunk(ptr inreg %p) {
193 %vptr = load ptr, ptr %p
194 %slot = getelementptr inbounds ptr, ptr %vptr, i32 1
195 %vmethod = load ptr, ptr %slot
196 %rv = musttail call i32 %vmethod(ptr inreg %p)
199 ; On i686, the call to __guard_check_icall_fptr should come immediately before the call to the target function.
200 ; X32-LABEL: _vmptr_thunk:
201 ; X32: movl %eax, %esi
202 ; X32: movl (%eax), %eax
203 ; X32: movl 4(%eax), %ecx
204 ; X32: calll *___guard_check_icall_fptr
205 ; X32: movl %esi, %eax
206 ; X32: jmpl *%ecx # TAILCALL
209 ; Use NEXT here because we previously had an extra instruction in this sequence.
210 ; X64-LABEL: vmptr_thunk:
211 ; X64: movq (%rcx), %rax
212 ; X64-NEXT: movq 8(%rax), %rax
213 ; X64-NEXT: movq __guard_dispatch_icall_fptr(%rip), %rdx
214 ; X64-NEXT: rex64 jmpq *%rdx # TAILCALL
218 ; Test that longjmp targets have public labels and are included in the .gljmp section.
219 %struct._SETJMP_FLOAT128 = type { [2 x i64] }
220 @buf1 = internal global [16 x %struct._SETJMP_FLOAT128] zeroinitializer, align 16
222 define i32 @func_cf_setjmp() {
223 %1 = alloca i32, align 4
224 %2 = alloca i32, align 4
225 store i32 0, ptr %1, align 4
226 store i32 -1, ptr %2, align 4
227 %3 = call ptr @llvm.frameaddress(i32 0)
228 %4 = call i32 @_setjmp(ptr @buf1, ptr %3) #2
230 ; X32-LABEL: func_cf_setjmp
231 ; X32: calll __setjmp
232 ; X32-NEXT: $cfgsj_func_cf_setjmp0:
234 ; X64-LABEL: func_cf_setjmp
236 ; X64-NEXT: $cfgsj_func_cf_setjmp0:
238 %5 = call ptr @llvm.frameaddress(i32 0)
239 %6 = call i32 @_setjmp(ptr @buf1, ptr %5) #2
241 ; X32: calll __setjmp
242 ; X32-NEXT: $cfgsj_func_cf_setjmp1:
245 ; X64-NEXT: $cfgsj_func_cf_setjmp1:
247 store i32 1, ptr %2, align 4
248 %7 = load i32, ptr %2, align 4
251 ; X32: .section .gljmp$y,"dr"
252 ; X32-NEXT: .symidx $cfgsj_func_cf_setjmp0
253 ; X32-NEXT: .symidx $cfgsj_func_cf_setjmp1
255 ; X64: .section .gljmp$y,"dr"
256 ; X64-NEXT: .symidx $cfgsj_func_cf_setjmp0
257 ; X64-NEXT: .symidx $cfgsj_func_cf_setjmp1
260 declare ptr @llvm.frameaddress(i32)
262 ; Function Attrs: returns_twice
263 declare dso_local i32 @_setjmp(ptr, ptr) #2
265 attributes #2 = { returns_twice }
268 !llvm.module.flags = !{!0}
269 !0 = !{i32 2, !"cfguard", i32 2}