1; RUN: llc -mtriple=i386-pc-windows-msvc < %s -o - | FileCheck -check-prefix=MSVC-X86 %s
2; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s -o - | FileCheck -check-prefix=MSVC-X64 %s
3
4; Make sure fastisel falls back and does something secure.
5; RUN: llc -mtriple=i686-pc-windows-msvc -O0 < %s -o - | FileCheck -check-prefix=MSVC-X86-O0 %s
6; RUN: llc -mtriple=x86_64-pc-windows-msvc -O0 < %s -o - | FileCheck -check-prefix=MSVC-X64-O0 %s
7
8@"\01LC" = internal constant [11 x i8] c"buf == %s\0A\00"    ; <ptr> [#uses=1]
9
10define void @test(ptr %a) nounwind ssp {
11entry:
12 %a_addr = alloca ptr    ; <ptr> [#uses=2]
13 %buf = alloca [8 x i8]    ; <ptr> [#uses=2]
14 store ptr %a, ptr %a_addr
15 %0 = load ptr, ptr %a_addr, align 4    ; <ptr> [#uses=1]
16 %1 = call ptr @strcpy(ptr %buf, ptr %0) nounwind   ; <ptr> [#uses=0]
17 %2 = call i32 (ptr, ...) @printf(ptr @"\01LC", ptr %buf) nounwind    ; <i32> [#uses=0]
18 br label %return
19
20return:    ; preds = %entry
21 ret void
22}
23
24; MSVC-X86-LABEL: _test:
25; MSVC-X86: movl ___security_cookie, %[[REG1:[^ ]*]]
26; MSVC-X86: xorl %esp, %[[REG1]]
27; MSVC-X86: movl %[[REG1]], [[SLOT:[0-9]*]](%esp)
28; MSVC-X86: calll _strcpy
29; MSVC-X86: movl [[SLOT]](%esp), %ecx
30; MSVC-X86: xorl %esp, %ecx
31; MSVC-X86: calll @__security_check_cookie@4
32; MSVC-X86: retl
33
34; MSVC-X64-LABEL: test:
35; MSVC-X64: movq __security_cookie(%rip), %[[REG1:[^ ]*]]
36; MSVC-X64: xorq %rsp, %[[REG1]]
37; MSVC-X64: movq %[[REG1]], [[SLOT:[0-9]*]](%rsp)
38; MSVC-X64: callq strcpy
39; MSVC-X64: movq [[SLOT]](%rsp), %rcx
40; MSVC-X64: xorq %rsp, %rcx
41; MSVC-X64: callq __security_check_cookie
42; MSVC-X64: retq
43
44; MSVC-X86-O0-LABEL: _test:
45; MSVC-X86-O0: movl ___security_cookie, %[[REG1:[^ ]*]]
46; MSVC-X86-O0: xorl %esp, %[[REG1]]
47; MSVC-X86-O0: movl %[[REG1]], [[SLOT:[0-9]*]](%esp)
48; MSVC-X86-O0: calll _strcpy
49; MSVC-X86-O0: movl [[SLOT]](%esp), %ecx
50; MSVC-X86-O0: xorl %esp, %ecx
51; MSVC-X86-O0: calll @__security_check_cookie@4
52; MSVC-X86-O0: retl
53
54; MSVC-X64-O0-LABEL: test:
55; MSVC-X64-O0: movq __security_cookie(%rip), %[[REG1:[^ ]*]]
56; MSVC-X64-O0: xorq %rsp, %[[REG1]]
57; MSVC-X64-O0: movq %[[REG1]], [[SLOT:[0-9]*]](%rsp)
58; MSVC-X64-O0: callq strcpy
59; MSVC-X64-O0: movq [[SLOT]](%rsp), %rcx
60; MSVC-X64-O0: xorq %rsp, %rcx
61; MSVC-X64-O0: callq __security_check_cookie
62; MSVC-X64-O0: retq
63
64
65declare void @escape(ptr)
66
67define void @test_vla(i32 %n) nounwind ssp {
68  %vla = alloca i32, i32 %n
69  call void @escape(ptr %vla)
70  ret void
71}
72
73; MSVC-X86-LABEL: _test_vla:
74; MSVC-X86: pushl %ebp
75; MSVC-X86: movl %esp, %ebp
76; MSVC-X86: movl ___security_cookie, %[[REG1:[^ ]*]]
77; MSVC-X86: xorl %ebp, %[[REG1]]
78; MSVC-X86: movl %[[REG1]], [[SLOT:-[0-9]*]](%ebp)
79; MSVC-X86: calll __chkstk
80; MSVC-X86: pushl
81; MSVC-X86: calll _escape
82; MSVC-X86: movl [[SLOT]](%ebp), %ecx
83; MSVC-X86: xorl %ebp, %ecx
84; MSVC-X86: calll @__security_check_cookie@4
85; MSVC-X86: movl %ebp, %esp
86; MSVC-X86: popl %ebp
87; MSVC-X86: retl
88
89; MSVC-X64-LABEL: test_vla:
90; MSVC-X64: pushq %rbp
91; MSVC-X64: subq $16, %rsp
92; MSVC-X64: leaq 16(%rsp), %rbp
93; MSVC-X64: movq __security_cookie(%rip), %[[REG1:[^ ]*]]
94; MSVC-X64: xorq %rbp, %[[REG1]]
95; MSVC-X64: movq %[[REG1]], [[SLOT:-[0-9]*]](%rbp)
96; MSVC-X64: callq __chkstk
97; MSVC-X64: callq escape
98; MSVC-X64: movq [[SLOT]](%rbp), %rcx
99; MSVC-X64: xorq %rbp, %rcx
100; MSVC-X64: callq __security_check_cookie
101; MSVC-X64: retq
102
103
104; This case is interesting because we address local variables with RBX but XOR
105; the guard value with RBP. That's fine, either value will do, as long as they
106; are the same across the life of the frame.
107
108define void @test_vla_realign(i32 %n) nounwind ssp {
109  %realign = alloca i32, align 32
110  %vla = alloca i32, i32 %n
111  call void @escape(ptr %realign)
112  call void @escape(ptr %vla)
113  ret void
114}
115
116; MSVC-X86-LABEL: _test_vla_realign:
117; MSVC-X86: pushl %ebp
118; MSVC-X86: movl %esp, %ebp
119; MSVC-X86: pushl %esi
120; MSVC-X86: andl $-32, %esp
121; MSVC-X86: subl $32, %esp
122; MSVC-X86: movl %esp, %esi
123; MSVC-X86: movl ___security_cookie, %[[REG1:[^ ]*]]
124; MSVC-X86: xorl %ebp, %[[REG1]]
125; MSVC-X86: movl %[[REG1]], [[SLOT:[0-9]*]](%esi)
126; MSVC-X86: calll __chkstk
127; MSVC-X86: pushl
128; MSVC-X86: calll _escape
129; MSVC-X86: movl [[SLOT]](%esi), %ecx
130; MSVC-X86: xorl %ebp, %ecx
131; MSVC-X86: calll @__security_check_cookie@4
132; MSVC-X86: leal -8(%ebp), %esp
133; MSVC-X86: popl %esi
134; MSVC-X86: popl %ebp
135; MSVC-X86: retl
136
137; MSVC-X64-LABEL: test_vla_realign:
138; MSVC-X64: pushq %rbp
139; MSVC-X64: pushq %rbx
140; MSVC-X64: subq $32, %rsp
141; MSVC-X64: leaq 32(%rsp), %rbp
142; MSVC-X64: andq $-32, %rsp
143; MSVC-X64: movq %rsp, %rbx
144; MSVC-X64: movq __security_cookie(%rip), %[[REG1:[^ ]*]]
145; MSVC-X64: xorq %rbp, %[[REG1]]
146; MSVC-X64: movq %[[REG1]], [[SLOT:[0-9]*]](%rbx)
147; MSVC-X64: callq __chkstk
148; MSVC-X64: callq escape
149; MSVC-X64: movq [[SLOT]](%rbx), %rcx
150; MSVC-X64: xorq %rbp, %rcx
151; MSVC-X64: callq __security_check_cookie
152; MSVC-X64: retq
153
154
155declare ptr @strcpy(ptr, ptr) nounwind
156
157declare i32 @printf(ptr, ...) nounwind
158
159