1 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT,ISBDSB -dump-input-context=100
2 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT,ISBDSB -dump-input-context=100
3 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT,SB -dump-input-context=100
4 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT,SB -dump-input-context=100
5 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT-OFF,ISBDSB -dump-input-context=100
6 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT-OFF,ISBDSB -dump-input-context=100
7 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT-OFF,SB -dump-input-context=100
8 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT-OFF,SB -dump-input-context=100
9 ; RUN: llc -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,NOHARDENARM -dump-input-context=100
10 ; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,NOHARDENTHUMB
11 ; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT,ISBDSB
12 ; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT,ISBDSB
13 ; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-nocomdat -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT-OFF,ISBDSB
14 ; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-nocomdat -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT-OFF,ISBDSB
15 ; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,SB
16 ; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,SB
17 ; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT,ISBDSB
18 ; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT,ISBDSB
19 ; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT-OFF,ISBDSB
20 ; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT-OFF,ISBDSB
21 ; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,SB
22 ; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,SB
24 ; Function Attrs: norecurse nounwind readnone
25 define dso_local i32 @double_return(i32 %a, i32 %b) local_unnamed_addr {
27 %cmp = icmp sgt i32 %a, 0
28 br i1 %cmp, label %if.then, label %if.else
30 if.then: ; preds = %entry
31 ; Make a very easy, very likely to predicate return (BX LR), to test that
32 ; it will not get predicated when sls-hardening is enabled.
35 ; CHECK-LABEL: double_return:
37 ; NOHARDENARM: {{bxgt lr$}}
38 ; NOHARDENTHUMB: {{bxgt lr$}}
43 if.else: ; preds = %entry
44 %div3 = sdiv i32 %a, %b
45 %div2 = sdiv i32 %a, %div3
46 %div1 = sdiv i32 %a, %div2
53 ; CHECK-NEXT: .Lfunc_end
56 @__const.indirect_branch.ptr = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@indirect_branch, %return), ptr blockaddress(@indirect_branch, %l2)], align 8
58 ; Function Attrs: norecurse nounwind readnone
59 define dso_local i32 @indirect_branch(i32 %a, i32 %b, i32 %i) {
60 ; CHECK-LABEL: indirect_branch:
62 %idxprom = sext i32 %i to i64
63 %arrayidx = getelementptr inbounds [2 x ptr], ptr @__const.indirect_branch.ptr, i64 0, i64 %idxprom
64 %0 = load ptr, ptr %arrayidx, align 8
65 indirectbr ptr %0, [label %return, label %l2]
79 return: ; preds = %entry, %l2
80 %retval.0 = phi i32 [ 1, %l2 ], [ 0, %entry ]
86 ; CHECK-NEXT: .Lfunc_end
89 define i32 @asmgoto() {
91 ; CHECK-LABEL: asmgoto:
92 callbr void asm sideeffect "B $0", "!i"()
93 to label %asm.fallthrough [label %d]
94 ; The asm goto above produces a direct branch:
96 ; CHECK-NEXT: {{^[ \t]+b }}
98 ; For direct branches, no mitigation is needed.
102 asm.fallthrough: ; preds = %entry
105 ; ISBDSB-NEXT: dsb sy
109 d: ; preds = %asm.fallthrough, %entry
112 ; ISBDSB-NEXT: dsb sy
115 ; CHECK-NEXT: .Lfunc_end
118 ; Check that indirect branches produced through switch jump tables are also
120 define dso_local i32 @jumptable(i32 %a, i32 %b) {
121 ; CHECK-LABEL: jumptable:
123 switch i32 %b, label %sw.epilog [
129 ; ARM: ldr pc, [{{r[0-9]}}, {{r[0-9]}}, lsl #2]
130 ; NOHARDENTHUMB: tbb [pc, {{r[0-9]}}]
131 ; HARDENTHUMB: mov pc, {{r[0-9]}}
132 ; ISBDSB-NEXT: dsb sy
137 sw.bb: ; preds = %entry
138 %add = shl nsw i32 %a, 1
141 sw.bb1: ; preds = %entry, %sw.bb
142 %a.addr.0 = phi i32 [ %a, %entry ], [ %add, %sw.bb ]
143 %add2 = shl nsw i32 %a.addr.0, 1
146 sw.bb3: ; preds = %entry, %sw.bb1
147 %a.addr.1 = phi i32 [ %a, %entry ], [ %add2, %sw.bb1 ]
148 %add4 = shl nsw i32 %a.addr.1, 1
151 sw.bb5: ; preds = %entry, %sw.bb3
152 %a.addr.2 = phi i32 [ %a, %entry ], [ %add4, %sw.bb3 ]
153 %add6 = shl nsw i32 %a.addr.2, 1
156 sw.epilog: ; preds = %sw.bb5, %entry
157 %a.addr.3 = phi i32 [ %a, %entry ], [ %add6, %sw.bb5 ]
160 ; ISBDSB-NEXT: dsb sy
165 define dso_local i32 @indirect_call(
166 ptr nocapture %f1, ptr nocapture %f2) {
168 ; CHECK-LABEL: indirect_call:
169 %call = tail call i32 %f1()
170 ; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}}
171 ; HARDENTHUMB: bl {{__llvm_slsblr_thunk_thumb_r[0-9]+$}}
172 %call2 = tail call i32 %f2()
173 ; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}}
174 ; HARDENTHUMB: bl {{__llvm_slsblr_thunk_thumb_r[0-9]+$}}
175 %add = add nsw i32 %call2, %call
180 ; verify calling through a function pointer.
181 @a = dso_local local_unnamed_addr global ptr null, align 8
182 @b = dso_local local_unnamed_addr global i32 0, align 4
183 define dso_local void @indirect_call_global() local_unnamed_addr {
184 ; CHECK-LABEL: indirect_call_global:
186 %0 = load ptr, ptr @a, align 8
187 %call = tail call i32 %0() nounwind
188 ; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}}
189 ; HARDENTHUMB: bl {{__llvm_slsblr_thunk_thumb_r[0-9]+$}}
190 store i32 %call, ptr @b, align 4
195 ; Verify that neither r12 nor lr are used as registers in indirect call
196 ; instructions when the sls-hardening-blr mitigation is enabled, as
197 ; (a) a linker is allowed to clobber r12 on calls, and
198 ; (b) the hardening transformation isn't correct if lr is the register holding
199 ; the address of the function called.
200 define i32 @check_r12(ptr %fp) {
202 ; CHECK-LABEL: check_r12:
203 %f = load ptr, ptr %fp, align 4
204 ; Force f to be moved into r12
205 %r12_f = tail call ptr asm "add $0, $1, #0", "={r12},{r12}"(ptr %f) nounwind
206 %call = call i32 %r12_f()
207 ; NOHARDENARM: blx r12
208 ; NOHARDENTHUMB: blx r12
209 ; HARDEN-NOT: bl {{__llvm_slsblr_thunk_(arm|thumb)_r12}}
214 define i32 @check_lr(ptr %fp) {
216 ; CHECK-LABEL: check_lr:
217 %f = load ptr, ptr %fp, align 4
218 ; Force f to be moved into lr
219 %lr_f = tail call ptr asm "add $0, $1, #0", "={lr},{lr}"(ptr %f) nounwind
220 %call = call i32 %lr_f()
221 ; NOHARDENARM: blx lr
222 ; NOHARDENTHUMB: blx lr
223 ; HARDEN-NOT: bl {{__llvm_slsblr_thunk_(arm|thumb)_lr}}
228 ; Verify that even when sls-harden-blr is enabled, "blx r12" is still an
229 ; instruction that is accepted by the inline assembler
230 define void @verify_inline_asm_blx_r12(ptr %g) {
232 ; CHECK-LABEL: verify_inline_asm_blx_r12:
233 tail call void asm sideeffect "blx $0", "{r12}"(ptr %g) nounwind
237 ; ISBDSB-NEXT: dsb sy
243 ; HARDEN-COMDAT: .section {{.text.__llvm_slsblr_thunk_(arm|thumb)_r5}}
244 ; HARDEN-COMDAT: .hidden {{__llvm_slsblr_thunk_(arm|thumb)_r5}}
245 ; HARDEN-COMDAT: .weak {{__llvm_slsblr_thunk_(arm|thumb)_r5}}
246 ; HARDEN-COMDAT: .type {{__llvm_slsblr_thunk_(arm|thumb)_r5}},%function
247 ; HARDEN-COMDAT-OFF-NOT: .section {{.text.__llvm_slsblr_thunk_(arm|thumb)_r5}}
248 ; HARDEN-COMDAT-OFF-NOT: .hidden {{__llvm_slsblr_thunk_(arm|thumb)_r5}}
249 ; HARDEN-COMDAT-OFF-NOT: .weak {{__llvm_slsblr_thunk_(arm|thumb)_r5}}
250 ; HARDEN-COMDAT-OFF: .type {{__llvm_slsblr_thunk_(arm|thumb)_r5}},%function
251 ; HARDEN-label: {{__llvm_slsblr_thunk_(arm|thumb)_r5}}:
253 ; ISBDSB-NEXT: dsb sy
257 ; HARDEN-NEXT: .Lfunc_end
259 ; THUMB-NOT: __llvm_slsblr_thunk_arm
260 ; ARM-NOT: __llvm_slsblr_thunk_thumb