Use Align for TFL::TransientStackAlignment
[llvm-core.git] / test / CodeGen / X86 / shadow-stack.ll
blob6fa4137818202fae9fc5d99ae9183c86fe9df009
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple x86_64-apple-macosx10.13.0 < %s | FileCheck %s --check-prefix=X86_64
3 ; RUN: llc -mtriple i386-apple-macosx10.13.0 < %s | FileCheck %s --check-prefix=X86
5 ; The MacOS tripples are used to get trapping behavior on the "unreachable" IR
6 ; instruction, so that the placement of the ud2 instruction could be verified.
8 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 ;; The IR was created using the following C code:
10 ;; typedef void *jmp_buf;
11 ;; jmp_buf buf;
13 ;; __attribute__((noinline)) int bar(int i) {
14 ;;   int j = i - 111;
15 ;;   __builtin_longjmp(&buf, 1);
16 ;;   return j;
17 ;; }
19 ;; int foo(int i) {
20 ;;   int j = i * 11;
21 ;;   if (!__builtin_setjmp(&buf)) {
22 ;;     j += 33 + bar(j);
23 ;;   }
24 ;;   return j + i;
25 ;; }
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28 @buf = common local_unnamed_addr global i8* null, align 8
30 ; Functions that use LongJmp should fix the Shadow Stack using previosuly saved
31 ; ShadowStackPointer in the input buffer.
32 ; The fix requires unwinding the shadow stack to the last SSP.
33 define i32 @bar(i32 %i) local_unnamed_addr {
34 ; X86_64-LABEL: bar:
35 ; X86_64:       ## %bb.0: ## %entry
36 ; X86_64-NEXT:    pushq %rbp
37 ; X86_64-NEXT:    .cfi_def_cfa_offset 16
38 ; X86_64-NEXT:    .cfi_offset %rbp, -16
39 ; X86_64-NEXT:    movq _buf@{{.*}}(%rip), %rax
40 ; X86_64-NEXT:    movq (%rax), %rax
41 ; X86_64-NEXT:    xorq %rdx, %rdx
42 ; X86_64-NEXT:    rdsspq %rdx
43 ; X86_64-NEXT:    testq %rdx, %rdx
44 ; X86_64-NEXT:    je LBB0_5
45 ; X86_64-NEXT:  ## %bb.1: ## %entry
46 ; X86_64-NEXT:    movq 24(%rax), %rcx
47 ; X86_64-NEXT:    subq %rdx, %rcx
48 ; X86_64-NEXT:    jbe LBB0_5
49 ; X86_64-NEXT:  ## %bb.2: ## %entry
50 ; X86_64-NEXT:    shrq $3, %rcx
51 ; X86_64-NEXT:    incsspq %rcx
52 ; X86_64-NEXT:    shrq $8, %rcx
53 ; X86_64-NEXT:    je LBB0_5
54 ; X86_64-NEXT:  ## %bb.3: ## %entry
55 ; X86_64-NEXT:    shlq %rcx
56 ; X86_64-NEXT:    movq $128, %rdx
57 ; X86_64-NEXT:  LBB0_4: ## %entry
58 ; X86_64-NEXT:    ## =>This Inner Loop Header: Depth=1
59 ; X86_64-NEXT:    incsspq %rdx
60 ; X86_64-NEXT:    decq %rcx
61 ; X86_64-NEXT:    jne LBB0_4
62 ; X86_64-NEXT:  LBB0_5: ## %entry
63 ; X86_64-NEXT:    movq (%rax), %rbp
64 ; X86_64-NEXT:    movq 8(%rax), %rcx
65 ; X86_64-NEXT:    movq 16(%rax), %rsp
66 ; X86_64-NEXT:    jmpq *%rcx
68 ; X86-LABEL: bar:
69 ; X86:       ## %bb.0: ## %entry
70 ; X86-NEXT:    pushl %ebp
71 ; X86-NEXT:    .cfi_def_cfa_offset 8
72 ; X86-NEXT:    .cfi_offset %ebp, -8
73 ; X86-NEXT:    movl L_buf$non_lazy_ptr, %eax
74 ; X86-NEXT:    movl (%eax), %eax
75 ; X86-NEXT:    xorl %edx, %edx
76 ; X86-NEXT:    rdsspd %edx
77 ; X86-NEXT:    testl %edx, %edx
78 ; X86-NEXT:    je LBB0_5
79 ; X86-NEXT:  ## %bb.1: ## %entry
80 ; X86-NEXT:    movl 12(%eax), %ecx
81 ; X86-NEXT:    subl %edx, %ecx
82 ; X86-NEXT:    jbe LBB0_5
83 ; X86-NEXT:  ## %bb.2: ## %entry
84 ; X86-NEXT:    shrl $2, %ecx
85 ; X86-NEXT:    incsspd %ecx
86 ; X86-NEXT:    shrl $8, %ecx
87 ; X86-NEXT:    je LBB0_5
88 ; X86-NEXT:  ## %bb.3: ## %entry
89 ; X86-NEXT:    shll %ecx
90 ; X86-NEXT:    movl $128, %edx
91 ; X86-NEXT:  LBB0_4: ## %entry
92 ; X86-NEXT:    ## =>This Inner Loop Header: Depth=1
93 ; X86-NEXT:    incsspd %edx
94 ; X86-NEXT:    decl %ecx
95 ; X86-NEXT:    jne LBB0_4
96 ; X86-NEXT:  LBB0_5: ## %entry
97 ; X86-NEXT:    movl (%eax), %ebp
98 ; X86-NEXT:    movl 4(%eax), %ecx
99 ; X86-NEXT:    movl 8(%eax), %esp
100 ; X86-NEXT:    jmpl *%ecx
101 entry:
102   %0 = load i8*, i8** @buf, align 8
103   tail call void @llvm.eh.sjlj.longjmp(i8* %0)
104   unreachable
107 declare void @llvm.eh.sjlj.longjmp(i8*)
109 ; Functions that call SetJmp should save the current ShadowStackPointer for
110 ; future fixing of the Shadow Stack.
111 define i32 @foo(i32 %i) local_unnamed_addr {
112 ; X86_64-LABEL: foo:
113 ; X86_64:       ## %bb.0: ## %entry
114 ; X86_64-NEXT:    pushq %rbp
115 ; X86_64-NEXT:    .cfi_def_cfa_offset 16
116 ; X86_64-NEXT:    .cfi_offset %rbp, -16
117 ; X86_64-NEXT:    movq %rsp, %rbp
118 ; X86_64-NEXT:    .cfi_def_cfa_register %rbp
119 ; X86_64-NEXT:    pushq %r15
120 ; X86_64-NEXT:    pushq %r14
121 ; X86_64-NEXT:    pushq %r13
122 ; X86_64-NEXT:    pushq %r12
123 ; X86_64-NEXT:    pushq %rbx
124 ; X86_64-NEXT:    pushq %rax
125 ; X86_64-NEXT:    .cfi_offset %rbx, -56
126 ; X86_64-NEXT:    .cfi_offset %r12, -48
127 ; X86_64-NEXT:    .cfi_offset %r13, -40
128 ; X86_64-NEXT:    .cfi_offset %r14, -32
129 ; X86_64-NEXT:    .cfi_offset %r15, -24
130 ; X86_64-NEXT:    ## kill: def $edi killed $edi def $rdi
131 ; X86_64-NEXT:    movq %rdi, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill
132 ; X86_64-NEXT:    movq _buf@{{.*}}(%rip), %rax
133 ; X86_64-NEXT:    movq (%rax), %rax
134 ; X86_64-NEXT:    movq %rbp, (%rax)
135 ; X86_64-NEXT:    movq %rsp, 16(%rax)
136 ; X86_64-NEXT:    leaq {{.*}}(%rip), %rcx
137 ; X86_64-NEXT:    movq %rcx, 8(%rax)
138 ; X86_64-NEXT:    xorq %rcx, %rcx
139 ; X86_64-NEXT:    rdsspq %rcx
140 ; X86_64-NEXT:    movq %rcx, 24(%rax)
141 ; X86_64-NEXT:    #EH_SjLj_Setup LBB1_4
142 ; X86_64-NEXT:  ## %bb.1: ## %entry
143 ; X86_64-NEXT:    xorl %eax, %eax
144 ; X86_64-NEXT:    testl %eax, %eax
145 ; X86_64-NEXT:    jne LBB1_3
146 ; X86_64-NEXT:    jmp LBB1_5
147 ; X86_64-NEXT:  LBB1_4: ## Block address taken
148 ; X86_64-NEXT:    ## %entry
149 ; X86_64-NEXT:    movl $1, %eax
150 ; X86_64-NEXT:    testl %eax, %eax
151 ; X86_64-NEXT:    je LBB1_5
152 ; X86_64-NEXT:  LBB1_3: ## %if.end
153 ; X86_64-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Reload
154 ; X86_64-NEXT:    shll $2, %eax
155 ; X86_64-NEXT:    leal (%rax,%rax,2), %eax
156 ; X86_64-NEXT:    addq $8, %rsp
157 ; X86_64-NEXT:    popq %rbx
158 ; X86_64-NEXT:    popq %r12
159 ; X86_64-NEXT:    popq %r13
160 ; X86_64-NEXT:    popq %r14
161 ; X86_64-NEXT:    popq %r15
162 ; X86_64-NEXT:    popq %rbp
163 ; X86_64-NEXT:    retq
164 ; X86_64-NEXT:  LBB1_5: ## %if.then
165 ; X86_64-NEXT:    callq _bar
166 ; X86_64-NEXT:    ud2
168 ; X86-LABEL: foo:
169 ; X86:       ## %bb.0: ## %entry
170 ; X86-NEXT:    pushl %ebp
171 ; X86-NEXT:    .cfi_def_cfa_offset 8
172 ; X86-NEXT:    .cfi_offset %ebp, -8
173 ; X86-NEXT:    movl %esp, %ebp
174 ; X86-NEXT:    .cfi_def_cfa_register %ebp
175 ; X86-NEXT:    pushl %ebx
176 ; X86-NEXT:    pushl %edi
177 ; X86-NEXT:    pushl %esi
178 ; X86-NEXT:    subl $12, %esp
179 ; X86-NEXT:    .cfi_offset %esi, -20
180 ; X86-NEXT:    .cfi_offset %edi, -16
181 ; X86-NEXT:    .cfi_offset %ebx, -12
182 ; X86-NEXT:    movl L_buf$non_lazy_ptr, %eax
183 ; X86-NEXT:    movl (%eax), %eax
184 ; X86-NEXT:    movl %ebp, (%eax)
185 ; X86-NEXT:    movl %esp, 16(%eax)
186 ; X86-NEXT:    movl $LBB1_4, 4(%eax)
187 ; X86-NEXT:    xorl %ecx, %ecx
188 ; X86-NEXT:    rdsspd %ecx
189 ; X86-NEXT:    movl %ecx, 12(%eax)
190 ; X86-NEXT:    #EH_SjLj_Setup LBB1_4
191 ; X86-NEXT:  ## %bb.1: ## %entry
192 ; X86-NEXT:    xorl %eax, %eax
193 ; X86-NEXT:    testl %eax, %eax
194 ; X86-NEXT:    jne LBB1_3
195 ; X86-NEXT:    jmp LBB1_5
196 ; X86-NEXT:  LBB1_4: ## Block address taken
197 ; X86-NEXT:    ## %entry
198 ; X86-NEXT:    movl $1, %eax
199 ; X86-NEXT:    testl %eax, %eax
200 ; X86-NEXT:    je LBB1_5
201 ; X86-NEXT:  LBB1_3: ## %if.end
202 ; X86-NEXT:    movl 8(%ebp), %eax
203 ; X86-NEXT:    shll $2, %eax
204 ; X86-NEXT:    leal (%eax,%eax,2), %eax
205 ; X86-NEXT:    addl $12, %esp
206 ; X86-NEXT:    popl %esi
207 ; X86-NEXT:    popl %edi
208 ; X86-NEXT:    popl %ebx
209 ; X86-NEXT:    popl %ebp
210 ; X86-NEXT:    retl
211 ; X86-NEXT:  LBB1_5: ## %if.then
212 ; X86-NEXT:    calll _bar
213 ; X86-NEXT:    ud2
214 entry:
215   %0 = load i8*, i8** @buf, align 8
216   %1 = bitcast i8* %0 to i8**
217   %2 = tail call i8* @llvm.frameaddress(i32 0)
218   store i8* %2, i8** %1, align 8
219   %3 = tail call i8* @llvm.stacksave()
220   %4 = getelementptr inbounds i8, i8* %0, i64 16
221   %5 = bitcast i8* %4 to i8**
222   store i8* %3, i8** %5, align 8
223   %6 = tail call i32 @llvm.eh.sjlj.setjmp(i8* %0)
224   %tobool = icmp eq i32 %6, 0
225   br i1 %tobool, label %if.then, label %if.end
227 if.then:                                          ; preds = %entry
228   %call = tail call i32 @bar(i32 undef)
229   unreachable
231 if.end:                                           ; preds = %entry
232   %add2 = mul nsw i32 %i, 12
233   ret i32 %add2
236 declare i8* @llvm.frameaddress(i32)
237 declare i8* @llvm.stacksave()
238 declare i32 @llvm.eh.sjlj.setjmp(i8*)
240 !llvm.module.flags = !{!0}
242 !0 = !{i32 4, !"cf-protection-return", i32 1}