[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / ARM / speculation-hardening-sls.ll
blob127e245ae327fd0605ebcad1d7968ce845d87d7c
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
50 entry:
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.
57   %mul = mul i32 %b, %a
58   ret i32 %mul
60 if.else:                                          ; preds = %entry
61   %div3 = sdiv i32 %a, %b
62   %div2 = sdiv i32 %a, %div3
63   %div1 = sdiv i32 %a, %div2
64   ret i32 %div1
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
101 entry:
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]
107 l2:                                               ; preds = %entry
108   br label %return
110 return:                                           ; preds = %entry, %l2
111   %retval.0 = phi i32 [ 1, %l2 ], [ 0, %entry ]
112   ret i32 %retval.0
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
141 entry:
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.
146 ; ISDDSB-NOT: dsb sy
148 asm.fallthrough:               ; preds = %entry
149   ret i32 0
151 d:                             ; preds = %asm.fallthrough, %entry
152   ret i32 1
155 ; Check that indirect branches produced through switch jump tables are also
156 ; hardened:
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
209 entry:
210   switch i32 %b, label %sw.epilog [
211     i32 0, label %sw.bb
212     i32 1, label %sw.bb1
213     i32 3, label %sw.bb3
214     i32 4, label %sw.bb5
215   ]
218 sw.bb:                                            ; preds = %entry
219   %add = shl nsw i32 %a, 1
220   br label %sw.bb1
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
225   br label %sw.bb3
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
230   br label %sw.bb5
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
235   br label %sw.epilog
237 sw.epilog:                                        ; preds = %sw.bb5, %entry
238   %a.addr.3 = phi i32 [ %a, %entry ], [ %add6, %sw.bb5 ]
239   ret i32 %a.addr.3
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) {
265 entry:
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
273   ret i32 %add
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}
305 entry:
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
310   ret void
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}
340 entry:
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()
345   ret i32 %call
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}
370 entry:
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()
375   ret i32 %call
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
384 ; ISBDSB-NEXT:    @APP
385 ; ISBDSB-NEXT:    blx r12
386 ; ISBDSB-NEXT:    @NO_APP
387 ; ISBDSB-NEXT:    bx lr
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
394 ; SB-NEXT:    @APP
395 ; SB-NEXT:    blx r12
396 ; SB-NEXT:    @NO_APP
397 ; SB-NEXT:    bx lr
398 ; SB-NEXT:    sb
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
415 entry:
416   %0 = bitcast void ()* %g to i8*
417   tail call void asm sideeffect "blx $0", "{r12}"(i8* %0) nounwind
418   ret void
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}}:
430 ; HARDEN:    bx r5
431 ; ISBDSB-NEXT: dsb sy
432 ; ISBDSB-NEXT: isb
433 ; SB-NEXT:     dsb sy
434 ; SB-NEXT:     isb
435 ; HARDEN-NEXT: .Lfunc_end