1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=HARDEN,HARDEN-COMDAT,ISBDSB -dump-input-context=100
3 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=HARDEN,HARDEN-COMDAT,ISBDSB -dump-input-context=100
4 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=HARDEN,HARDEN-COMDAT,SB -dump-input-context=100
5 ; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=HARDEN,HARDEN-COMDAT,SB -dump-input-context=100
6 ; 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=HARDEN,HARDEN-COMDAT-OFF,ISBDSB -dump-input-context=100
7 ; 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=HARDEN,HARDEN-COMDAT-OFF,ISBDSB -dump-input-context=100
8 ; 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=HARDEN,HARDEN-COMDAT-OFF,SB -dump-input-context=100
9 ; 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=HARDEN,HARDEN-COMDAT-OFF,SB -dump-input-context=100
10 ; RUN: llc -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=NOHARDENARM -dump-input-context=100
11 ; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=NOHARDENTHUMB
12 ; 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=HARDEN,HARDEN-COMDAT,ISBDSB
13 ; 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=HARDEN,HARDEN-COMDAT,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=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=HARDEN,HARDEN-COMDAT-OFF,ISBDSB
15 ; 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=HARDEN,HARDEN-COMDAT-OFF,ISBDSB
16 ; 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=HARDEN,SB
17 ; 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=HARDEN,SB
18 ; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=HARDEN,HARDEN-COMDAT,ISBDSB
19 ; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=HARDEN,HARDEN-COMDAT,ISBDSB
20 ; 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=HARDEN,HARDEN-COMDAT-OFF,ISBDSB
21 ; 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=HARDEN,HARDEN-COMDAT-OFF,ISBDSB
22 ; 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=HARDEN,SB
23 ; 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=HARDEN,SB
25 ; Function Attrs: norecurse nounwind readnone
26 define dso_local i32 @double_return(i32 %a, i32 %b) local_unnamed_addr {
27 ; NOHARDENARM-LABEL: double_return:
28 ; NOHARDENARM: @ %bb.0: @ %entry
29 ; NOHARDENARM-NEXT: cmp r0, #0
30 ; NOHARDENARM-NEXT: mulgt r0, r1, r0
31 ; NOHARDENARM-NEXT: bxgt lr
32 ; NOHARDENARM-NEXT: .LBB0_1: @ %if.else
33 ; NOHARDENARM-NEXT: sdiv r1, r0, r1
34 ; NOHARDENARM-NEXT: sdiv r1, r0, r1
35 ; NOHARDENARM-NEXT: sdiv r0, r0, r1
36 ; NOHARDENARM-NEXT: bx lr
38 ; NOHARDENTHUMB-LABEL: double_return:
39 ; NOHARDENTHUMB: @ %bb.0: @ %entry
40 ; NOHARDENTHUMB-NEXT: cmp r0, #0
41 ; NOHARDENTHUMB-NEXT: ble .LBB0_2
42 ; NOHARDENTHUMB-NEXT: @ %bb.1: @ %if.then
43 ; NOHARDENTHUMB-NEXT: muls r0, r1, r0
44 ; NOHARDENTHUMB-NEXT: bx lr
45 ; NOHARDENTHUMB-NEXT: .LBB0_2: @ %if.else
46 ; NOHARDENTHUMB-NEXT: sdiv r1, r0, r1
47 ; NOHARDENTHUMB-NEXT: sdiv r1, r0, r1
48 ; NOHARDENTHUMB-NEXT: sdiv r0, r0, r1
49 ; NOHARDENTHUMB-NEXT: bx lr
51 %cmp = icmp sgt i32 %a, 0
52 br i1 %cmp, label %if.then, label %if.else
54 if.then: ; preds = %entry
55 ; Make a very easy, very likely to predicate return (BX LR), to test that
56 ; it will not get predicated when sls-hardening is enabled.
60 if.else: ; preds = %entry
61 %div3 = sdiv i32 %a, %b
62 %div2 = sdiv i32 %a, %div3
63 %div1 = sdiv i32 %a, %div2
68 @__const.indirect_branch.ptr = private unnamed_addr constant [2 x i8*] [i8* blockaddress(@indirect_branch, %return), i8* blockaddress(@indirect_branch, %l2)], align 8
70 ; Function Attrs: norecurse nounwind readnone
71 define dso_local i32 @indirect_branch(i32 %a, i32 %b, i32 %i) {
72 ; NOHARDENARM-LABEL: indirect_branch:
73 ; NOHARDENARM: @ %bb.0: @ %entry
74 ; NOHARDENARM-NEXT: movw r0, :lower16:.L__const.indirect_branch.ptr
75 ; NOHARDENARM-NEXT: movt r0, :upper16:.L__const.indirect_branch.ptr
76 ; NOHARDENARM-NEXT: ldr r0, [r0, r2, lsl #2]
77 ; NOHARDENARM-NEXT: bx r0
78 ; NOHARDENARM-NEXT: .Ltmp0: @ Block address taken
79 ; NOHARDENARM-NEXT: .LBB1_1: @ %return
80 ; NOHARDENARM-NEXT: mov r0, #0
81 ; NOHARDENARM-NEXT: bx lr
82 ; NOHARDENARM-NEXT: .Ltmp1: @ Block address taken
83 ; NOHARDENARM-NEXT: .LBB1_2: @ %l2
84 ; NOHARDENARM-NEXT: mov r0, #1
85 ; NOHARDENARM-NEXT: bx lr
87 ; NOHARDENTHUMB-LABEL: indirect_branch:
88 ; NOHARDENTHUMB: @ %bb.0: @ %entry
89 ; NOHARDENTHUMB-NEXT: movw r0, :lower16:.L__const.indirect_branch.ptr
90 ; NOHARDENTHUMB-NEXT: movt r0, :upper16:.L__const.indirect_branch.ptr
91 ; NOHARDENTHUMB-NEXT: ldr.w r0, [r0, r2, lsl #2]
92 ; NOHARDENTHUMB-NEXT: mov pc, r0
93 ; NOHARDENTHUMB-NEXT: .Ltmp0: @ Block address taken
94 ; NOHARDENTHUMB-NEXT: .LBB1_1: @ %return
95 ; NOHARDENTHUMB-NEXT: movs r0, #0
96 ; NOHARDENTHUMB-NEXT: bx lr
97 ; NOHARDENTHUMB-NEXT: .Ltmp1: @ Block address taken
98 ; NOHARDENTHUMB-NEXT: .LBB1_2: @ %l2
99 ; NOHARDENTHUMB-NEXT: movs r0, #1
100 ; NOHARDENTHUMB-NEXT: bx lr
102 %idxprom = sext i32 %i to i64
103 %arrayidx = getelementptr inbounds [2 x i8*], [2 x i8*]* @__const.indirect_branch.ptr, i64 0, i64 %idxprom
104 %0 = load i8*, i8** %arrayidx, align 8
105 indirectbr i8* %0, [label %return, label %l2]
110 return: ; preds = %entry, %l2
111 %retval.0 = phi i32 [ 1, %l2 ], [ 0, %entry ]
115 define i32 @asmgoto() {
116 ; NOHARDENARM-LABEL: asmgoto:
117 ; NOHARDENARM: @ %bb.0: @ %entry
118 ; NOHARDENARM-NEXT: mov r0, #0
119 ; NOHARDENARM-NEXT: @APP
120 ; NOHARDENARM-NEXT: b .Ltmp2
121 ; NOHARDENARM-NEXT: @NO_APP
122 ; NOHARDENARM-NEXT: @ %bb.1: @ %common.ret
123 ; NOHARDENARM-NEXT: bx lr
124 ; NOHARDENARM-NEXT: .Ltmp2: @ Block address taken
125 ; NOHARDENARM-NEXT: .LBB2_2: @ %d
126 ; NOHARDENARM-NEXT: mov r0, #1
127 ; NOHARDENARM-NEXT: bx lr
129 ; NOHARDENTHUMB-LABEL: asmgoto:
130 ; NOHARDENTHUMB: @ %bb.0: @ %entry
131 ; NOHARDENTHUMB-NEXT: @APP
132 ; NOHARDENTHUMB-NEXT: b .Ltmp2
133 ; NOHARDENTHUMB-NEXT: @NO_APP
134 ; NOHARDENTHUMB-NEXT: @ %bb.1:
135 ; NOHARDENTHUMB-NEXT: movs r0, #0
136 ; NOHARDENTHUMB-NEXT: bx lr
137 ; NOHARDENTHUMB-NEXT: .Ltmp2: @ Block address taken
138 ; NOHARDENTHUMB-NEXT: .LBB2_2: @ %d
139 ; NOHARDENTHUMB-NEXT: movs r0, #1
140 ; NOHARDENTHUMB-NEXT: bx lr
142 callbr void asm sideeffect "B $0", "X"(i8* blockaddress(@asmgoto, %d))
143 to label %asm.fallthrough [label %d]
144 ; The asm goto above produces a direct branch:
145 ; For direct branches, no mitigation is needed.
148 asm.fallthrough: ; preds = %entry
151 d: ; preds = %asm.fallthrough, %entry
155 ; Check that indirect branches produced through switch jump tables are also
157 define dso_local i32 @jumptable(i32 %a, i32 %b) {
158 ; NOHARDENARM-LABEL: jumptable:
159 ; NOHARDENARM: @ %bb.0: @ %entry
160 ; NOHARDENARM-NEXT: cmp r1, #4
161 ; NOHARDENARM-NEXT: bxhi lr
162 ; NOHARDENARM-NEXT: .LBB3_1: @ %entry
163 ; NOHARDENARM-NEXT: adr r2, .LJTI3_0
164 ; NOHARDENARM-NEXT: ldr pc, [r2, r1, lsl #2]
165 ; NOHARDENARM-NEXT: @ %bb.2:
166 ; NOHARDENARM-NEXT: .p2align 2
167 ; NOHARDENARM-NEXT: .LJTI3_0:
168 ; NOHARDENARM-NEXT: .long .LBB3_3
169 ; NOHARDENARM-NEXT: .long .LBB3_4
170 ; NOHARDENARM-NEXT: .long .LBB3_7
171 ; NOHARDENARM-NEXT: .long .LBB3_5
172 ; NOHARDENARM-NEXT: .long .LBB3_6
173 ; NOHARDENARM-NEXT: .LBB3_3: @ %sw.bb
174 ; NOHARDENARM-NEXT: lsl r0, r0, #1
175 ; NOHARDENARM-NEXT: .LBB3_4: @ %sw.bb1
176 ; NOHARDENARM-NEXT: lsl r0, r0, #1
177 ; NOHARDENARM-NEXT: .LBB3_5: @ %sw.bb3
178 ; NOHARDENARM-NEXT: lsl r0, r0, #1
179 ; NOHARDENARM-NEXT: .LBB3_6: @ %sw.bb5
180 ; NOHARDENARM-NEXT: lsl r0, r0, #1
181 ; NOHARDENARM-NEXT: .LBB3_7: @ %sw.epilog
182 ; NOHARDENARM-NEXT: bx lr
184 ; NOHARDENTHUMB-LABEL: jumptable:
185 ; NOHARDENTHUMB: @ %bb.0: @ %entry
186 ; NOHARDENTHUMB-NEXT: cmp r1, #4
187 ; NOHARDENTHUMB-NEXT: bhi .LBB3_7
188 ; NOHARDENTHUMB-NEXT: @ %bb.1: @ %entry
189 ; NOHARDENTHUMB-NEXT: .LCPI3_0:
190 ; NOHARDENTHUMB-NEXT: tbb [pc, r1]
191 ; NOHARDENTHUMB-NEXT: @ %bb.2:
192 ; NOHARDENTHUMB-NEXT: .LJTI3_0:
193 ; NOHARDENTHUMB-NEXT: .byte (.LBB3_3-(.LCPI3_0+4))/2
194 ; NOHARDENTHUMB-NEXT: .byte (.LBB3_4-(.LCPI3_0+4))/2
195 ; NOHARDENTHUMB-NEXT: .byte (.LBB3_7-(.LCPI3_0+4))/2
196 ; NOHARDENTHUMB-NEXT: .byte (.LBB3_5-(.LCPI3_0+4))/2
197 ; NOHARDENTHUMB-NEXT: .byte (.LBB3_6-(.LCPI3_0+4))/2
198 ; NOHARDENTHUMB-NEXT: .p2align 1
199 ; NOHARDENTHUMB-NEXT: .LBB3_3: @ %sw.bb
200 ; NOHARDENTHUMB-NEXT: lsls r0, r0, #1
201 ; NOHARDENTHUMB-NEXT: .LBB3_4: @ %sw.bb1
202 ; NOHARDENTHUMB-NEXT: lsls r0, r0, #1
203 ; NOHARDENTHUMB-NEXT: .LBB3_5: @ %sw.bb3
204 ; NOHARDENTHUMB-NEXT: lsls r0, r0, #1
205 ; NOHARDENTHUMB-NEXT: .LBB3_6: @ %sw.bb5
206 ; NOHARDENTHUMB-NEXT: lsls r0, r0, #1
207 ; NOHARDENTHUMB-NEXT: .LBB3_7: @ %sw.epilog
208 ; NOHARDENTHUMB-NEXT: bx lr
210 switch i32 %b, label %sw.epilog [
218 sw.bb: ; preds = %entry
219 %add = shl nsw i32 %a, 1
222 sw.bb1: ; preds = %entry, %sw.bb
223 %a.addr.0 = phi i32 [ %a, %entry ], [ %add, %sw.bb ]
224 %add2 = shl nsw i32 %a.addr.0, 1
227 sw.bb3: ; preds = %entry, %sw.bb1
228 %a.addr.1 = phi i32 [ %a, %entry ], [ %add2, %sw.bb1 ]
229 %add4 = shl nsw i32 %a.addr.1, 1
232 sw.bb5: ; preds = %entry, %sw.bb3
233 %a.addr.2 = phi i32 [ %a, %entry ], [ %add4, %sw.bb3 ]
234 %add6 = shl nsw i32 %a.addr.2, 1
237 sw.epilog: ; preds = %sw.bb5, %entry
238 %a.addr.3 = phi i32 [ %a, %entry ], [ %add6, %sw.bb5 ]
242 define dso_local i32 @indirect_call(
243 ; NOHARDENARM-LABEL: indirect_call:
244 ; NOHARDENARM: @ %bb.0: @ %entry
245 ; NOHARDENARM-NEXT: .save {r4, r5, r11, lr}
246 ; NOHARDENARM-NEXT: push {r4, r5, r11, lr}
247 ; NOHARDENARM-NEXT: mov r4, r1
248 ; NOHARDENARM-NEXT: blx r0
249 ; NOHARDENARM-NEXT: mov r5, r0
250 ; NOHARDENARM-NEXT: blx r4
251 ; NOHARDENARM-NEXT: add r0, r0, r5
252 ; NOHARDENARM-NEXT: pop {r4, r5, r11, pc}
254 ; NOHARDENTHUMB-LABEL: indirect_call:
255 ; NOHARDENTHUMB: @ %bb.0: @ %entry
256 ; NOHARDENTHUMB-NEXT: .save {r4, r5, r7, lr}
257 ; NOHARDENTHUMB-NEXT: push {r4, r5, r7, lr}
258 ; NOHARDENTHUMB-NEXT: mov r4, r1
259 ; NOHARDENTHUMB-NEXT: blx r0
260 ; NOHARDENTHUMB-NEXT: mov r5, r0
261 ; NOHARDENTHUMB-NEXT: blx r4
262 ; NOHARDENTHUMB-NEXT: add r0, r5
263 ; NOHARDENTHUMB-NEXT: pop {r4, r5, r7, pc}
264 i32 (...)* nocapture %f1, i32 (...)* nocapture %f2) {
266 %callee.knr.cast = bitcast i32 (...)* %f1 to i32 ()*
267 %call = tail call i32 %callee.knr.cast()
268 ; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}}
269 %callee.knr.cast1 = bitcast i32 (...)* %f2 to i32 ()*
270 %call2 = tail call i32 %callee.knr.cast1()
271 ; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}}
272 %add = add nsw i32 %call2, %call
276 ; verify calling through a function pointer.
277 @a = dso_local local_unnamed_addr global i32 (...)* null, align 8
278 @b = dso_local local_unnamed_addr global i32 0, align 4
279 define dso_local void @indirect_call_global() local_unnamed_addr {
280 ; NOHARDENARM-LABEL: indirect_call_global:
281 ; NOHARDENARM: @ %bb.0: @ %entry
282 ; NOHARDENARM-NEXT: .save {r11, lr}
283 ; NOHARDENARM-NEXT: push {r11, lr}
284 ; NOHARDENARM-NEXT: movw r0, :lower16:a
285 ; NOHARDENARM-NEXT: movt r0, :upper16:a
286 ; NOHARDENARM-NEXT: ldr r0, [r0]
287 ; NOHARDENARM-NEXT: blx r0
288 ; NOHARDENARM-NEXT: movw r1, :lower16:b
289 ; NOHARDENARM-NEXT: movt r1, :upper16:b
290 ; NOHARDENARM-NEXT: str r0, [r1]
291 ; NOHARDENARM-NEXT: pop {r11, pc}
293 ; NOHARDENTHUMB-LABEL: indirect_call_global:
294 ; NOHARDENTHUMB: @ %bb.0: @ %entry
295 ; NOHARDENTHUMB-NEXT: .save {r7, lr}
296 ; NOHARDENTHUMB-NEXT: push {r7, lr}
297 ; NOHARDENTHUMB-NEXT: movw r0, :lower16:a
298 ; NOHARDENTHUMB-NEXT: movt r0, :upper16:a
299 ; NOHARDENTHUMB-NEXT: ldr r0, [r0]
300 ; NOHARDENTHUMB-NEXT: blx r0
301 ; NOHARDENTHUMB-NEXT: movw r1, :lower16:b
302 ; NOHARDENTHUMB-NEXT: movt r1, :upper16:b
303 ; NOHARDENTHUMB-NEXT: str r0, [r1]
304 ; NOHARDENTHUMB-NEXT: pop {r7, pc}
306 %0 = load i32 ()*, i32 ()** bitcast (i32 (...)** @a to i32 ()**), align 8
307 %call = tail call i32 %0() nounwind
308 ; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}}
309 store i32 %call, i32* @b, align 4
313 ; Verify that neither r12 nor lr are used as registers in indirect call
314 ; instructions when the sls-hardening-blr mitigation is enabled, as
315 ; (a) a linker is allowed to clobber r12 on calls, and
316 ; (b) the hardening transformation isn't correct if lr is the register holding
317 ; the address of the function called.
318 define i32 @check_r12(i32 ()** %fp) {
319 ; NOHARDENARM-LABEL: check_r12:
320 ; NOHARDENARM: @ %bb.0: @ %entry
321 ; NOHARDENARM-NEXT: .save {r11, lr}
322 ; NOHARDENARM-NEXT: push {r11, lr}
323 ; NOHARDENARM-NEXT: ldr r12, [r0]
324 ; NOHARDENARM-NEXT: @APP
325 ; NOHARDENARM-NEXT: add r12, r12, #0
326 ; NOHARDENARM-NEXT: @NO_APP
327 ; NOHARDENARM-NEXT: blx r12
328 ; NOHARDENARM-NEXT: pop {r11, pc}
330 ; NOHARDENTHUMB-LABEL: check_r12:
331 ; NOHARDENTHUMB: @ %bb.0: @ %entry
332 ; NOHARDENTHUMB-NEXT: .save {r7, lr}
333 ; NOHARDENTHUMB-NEXT: push {r7, lr}
334 ; NOHARDENTHUMB-NEXT: ldr.w r12, [r0]
335 ; NOHARDENTHUMB-NEXT: @APP
336 ; NOHARDENTHUMB-NEXT: add.w r12, r12, #0
337 ; NOHARDENTHUMB-NEXT: @NO_APP
338 ; NOHARDENTHUMB-NEXT: blx r12
339 ; NOHARDENTHUMB-NEXT: pop {r7, pc}
341 %f = load i32 ()*, i32 ()** %fp, align 4
342 ; Force f to be moved into r12
343 %r12_f = tail call i32 ()* asm "add $0, $1, #0", "={r12},{r12}"(i32 ()* %f) nounwind
344 %call = call i32 %r12_f()
348 define i32 @check_lr(i32 ()** %fp) {
349 ; NOHARDENARM-LABEL: check_lr:
350 ; NOHARDENARM: @ %bb.0: @ %entry
351 ; NOHARDENARM-NEXT: .save {r11, lr}
352 ; NOHARDENARM-NEXT: push {r11, lr}
353 ; NOHARDENARM-NEXT: ldr lr, [r0]
354 ; NOHARDENARM-NEXT: @APP
355 ; NOHARDENARM-NEXT: add lr, lr, #0
356 ; NOHARDENARM-NEXT: @NO_APP
357 ; NOHARDENARM-NEXT: blx lr
358 ; NOHARDENARM-NEXT: pop {r11, pc}
360 ; NOHARDENTHUMB-LABEL: check_lr:
361 ; NOHARDENTHUMB: @ %bb.0: @ %entry
362 ; NOHARDENTHUMB-NEXT: .save {r7, lr}
363 ; NOHARDENTHUMB-NEXT: push {r7, lr}
364 ; NOHARDENTHUMB-NEXT: ldr.w lr, [r0]
365 ; NOHARDENTHUMB-NEXT: @APP
366 ; NOHARDENTHUMB-NEXT: add.w lr, lr, #0
367 ; NOHARDENTHUMB-NEXT: @NO_APP
368 ; NOHARDENTHUMB-NEXT: blx lr
369 ; NOHARDENTHUMB-NEXT: pop {r7, pc}
371 %f = load i32 ()*, i32 ()** %fp, align 4
372 ; Force f to be moved into lr
373 %lr_f = tail call i32 ()* asm "add $0, $1, #0", "={lr},{lr}"(i32 ()* %f) nounwind
374 %call = call i32 %lr_f()
378 ; Verify that even when sls-harden-blr is enabled, "blx r12" is still an
379 ; instruction that is accepted by the inline assembler
380 define void @verify_inline_asm_blx_r12(void ()* %g) {
381 ; ISBDSB-LABEL: verify_inline_asm_blx_r12:
382 ; ISBDSB: @ %bb.0: @ %entry
383 ; ISBDSB-NEXT: mov r12, r0
385 ; ISBDSB-NEXT: blx r12
386 ; ISBDSB-NEXT: @NO_APP
388 ; ISBDSB-NEXT: dsb sy
389 ; ISBDSB-NEXT: isb sy
391 ; SB-LABEL: verify_inline_asm_blx_r12:
392 ; SB: @ %bb.0: @ %entry
393 ; SB-NEXT: mov r12, r0
400 ; NOHARDENARM-LABEL: verify_inline_asm_blx_r12:
401 ; NOHARDENARM: @ %bb.0: @ %entry
402 ; NOHARDENARM-NEXT: mov r12, r0
403 ; NOHARDENARM-NEXT: @APP
404 ; NOHARDENARM-NEXT: blx r12
405 ; NOHARDENARM-NEXT: @NO_APP
406 ; NOHARDENARM-NEXT: bx lr
408 ; NOHARDENTHUMB-LABEL: verify_inline_asm_blx_r12:
409 ; NOHARDENTHUMB: @ %bb.0: @ %entry
410 ; NOHARDENTHUMB-NEXT: mov r12, r0
411 ; NOHARDENTHUMB-NEXT: @APP
412 ; NOHARDENTHUMB-NEXT: blx r12
413 ; NOHARDENTHUMB-NEXT: @NO_APP
414 ; NOHARDENTHUMB-NEXT: bx lr
416 %0 = bitcast void ()* %g to i8*
417 tail call void asm sideeffect "blx $0", "{r12}"(i8* %0) nounwind
421 ; HARDEN-COMDAT: .section {{.text.__llvm_slsblr_thunk_(arm|thumb)_r5}}
422 ; HARDEN-COMDAT: .hidden {{__llvm_slsblr_thunk_(arm|thumb)_r5}}
423 ; HARDEN-COMDAT: .weak {{__llvm_slsblr_thunk_(arm|thumb)_r5}}
424 ; HARDEN-COMDAT: .type {{__llvm_slsblr_thunk_(arm|thumb)_r5}},%function
425 ; HARDEN-COMDAT-OFF-NOT: .section {{.text.__llvm_slsblr_thunk_(arm|thumb)_r5}}
426 ; HARDEN-COMDAT-OFF-NOT: .hidden {{__llvm_slsblr_thunk_(arm|thumb)_r5}}
427 ; HARDEN-COMDAT-OFF-NOT: .weak {{__llvm_slsblr_thunk_(arm|thumb)_r5}}
428 ; HARDEN-COMDAT-OFF: .type {{__llvm_slsblr_thunk_(arm|thumb)_r5}},%function
429 ; HARDEN-label: {{__llvm_slsblr_thunk_(arm|thumb)_r5}}:
431 ; ISBDSB-NEXT: dsb sy
435 ; HARDEN-NEXT: .Lfunc_end