forked from OSchip/llvm-project
203 lines
6.1 KiB
YAML
203 lines
6.1 KiB
YAML
# RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu \
|
|
# RUN: -start-before aarch64-speculation-hardening -o - %s \
|
|
# RUN: | FileCheck %s --dump-input-on-failure
|
|
|
|
# Check that the speculation hardening pass generates code as expected for
|
|
# basic blocks ending with a variety of branch patterns:
|
|
# - (1) no branches (fallthrough)
|
|
# - (2) one unconditional branch
|
|
# - (3) one conditional branch + fall-through
|
|
# - (4) one conditional branch + one unconditional branch
|
|
# - other direct branches don't seem to be generated by the AArch64 codegen
|
|
--- |
|
|
define void @nobranch_fallthrough(i32 %a, i32 %b) speculative_load_hardening {
|
|
ret void
|
|
}
|
|
define void @uncondbranch(i32 %a, i32 %b) speculative_load_hardening {
|
|
ret void
|
|
}
|
|
define void @condbranch_fallthrough(i32 %a, i32 %b) speculative_load_hardening {
|
|
ret void
|
|
}
|
|
define void @condbranch_uncondbranch(i32 %a, i32 %b) speculative_load_hardening {
|
|
ret void
|
|
}
|
|
define void @indirectbranch(i32 %a, i32 %b) speculative_load_hardening {
|
|
ret void
|
|
}
|
|
; Also check that a non-default temporary register gets picked correctly to
|
|
; transfer the SP to to and it with the taint register when the default
|
|
; temporary isn't available.
|
|
define void @indirect_call_x17(i32 %a, i32 %b) speculative_load_hardening {
|
|
ret void
|
|
}
|
|
@g = common dso_local local_unnamed_addr global i64 (...)* null, align 8
|
|
define void @indirect_tailcall_x17(i32 %a, i32 %b) speculative_load_hardening {
|
|
ret void
|
|
}
|
|
define void @indirect_call_lr(i32 %a, i32 %b) speculative_load_hardening {
|
|
ret void
|
|
}
|
|
define void @RS_cannot_find_available_regs() speculative_load_hardening {
|
|
ret void
|
|
}
|
|
...
|
|
---
|
|
name: nobranch_fallthrough
|
|
tracksRegLiveness: true
|
|
body: |
|
|
; CHECK-LABEL: nobranch_fallthrough
|
|
bb.0:
|
|
successors: %bb.1
|
|
liveins: $w0, $w1
|
|
; CHECK-NOT: csel
|
|
bb.1:
|
|
liveins: $w0
|
|
RET undef $lr, implicit $w0
|
|
...
|
|
---
|
|
name: uncondbranch
|
|
tracksRegLiveness: true
|
|
body: |
|
|
; CHECK-LABEL: uncondbranch
|
|
bb.0:
|
|
successors: %bb.1
|
|
liveins: $w0, $w1
|
|
B %bb.1
|
|
; CHECK-NOT: csel
|
|
bb.1:
|
|
liveins: $w0
|
|
RET undef $lr, implicit $w0
|
|
...
|
|
---
|
|
name: condbranch_fallthrough
|
|
tracksRegLiveness: true
|
|
body: |
|
|
; CHECK-LABEL: condbranch_fallthrough
|
|
bb.0:
|
|
successors: %bb.1, %bb.2
|
|
liveins: $w0, $w1
|
|
$wzr = SUBSWrs renamable $w0, renamable $w1, 0, implicit-def $nzcv, implicit-def $nzcv
|
|
Bcc 11, %bb.2, implicit $nzcv
|
|
; CHECK: b.lt [[BB_LT_T:\.LBB[0-9_]+]]
|
|
|
|
bb.1:
|
|
liveins: $nzcv, $w0
|
|
; CHECK: csel x16, x16, xzr, ge
|
|
RET undef $lr, implicit $w0
|
|
bb.2:
|
|
liveins: $nzcv, $w0
|
|
; CHECK: csel x16, x16, xzr, lt
|
|
RET undef $lr, implicit $w0
|
|
...
|
|
---
|
|
name: condbranch_uncondbranch
|
|
tracksRegLiveness: true
|
|
body: |
|
|
; CHECK-LABEL: condbranch_uncondbranch
|
|
bb.0:
|
|
successors: %bb.1, %bb.2
|
|
liveins: $w0, $w1
|
|
$wzr = SUBSWrs renamable $w0, renamable $w1, 0, implicit-def $nzcv, implicit-def $nzcv
|
|
Bcc 11, %bb.2, implicit $nzcv
|
|
B %bb.1, implicit $nzcv
|
|
; CHECK: b.lt [[BB_LT_T:\.LBB[0-9_]+]]
|
|
|
|
bb.1:
|
|
liveins: $nzcv, $w0
|
|
; CHECK: csel x16, x16, xzr, ge
|
|
RET undef $lr, implicit $w0
|
|
bb.2:
|
|
liveins: $nzcv, $w0
|
|
; CHECK: csel x16, x16, xzr, lt
|
|
RET undef $lr, implicit $w0
|
|
...
|
|
---
|
|
name: indirectbranch
|
|
tracksRegLiveness: true
|
|
body: |
|
|
; Check that no instrumentation is done on indirect branches (for now).
|
|
; CHECK-LABEL: indirectbranch
|
|
bb.0:
|
|
successors: %bb.1, %bb.2
|
|
liveins: $x0
|
|
BR $x0
|
|
bb.1:
|
|
liveins: $x0
|
|
; CHECK-NOT: csel
|
|
RET undef $lr, implicit $x0
|
|
bb.2:
|
|
liveins: $x0
|
|
; CHECK-NOT: csel
|
|
RET undef $lr, implicit $x0
|
|
...
|
|
---
|
|
name: indirect_call_x17
|
|
tracksRegLiveness: true
|
|
body: |
|
|
bb.0:
|
|
liveins: $x17
|
|
; CHECK-LABEL: indirect_call_x17
|
|
; CHECK: mov x0, sp
|
|
; CHECK: and x0, x0, x16
|
|
; CHECK: mov sp, x0
|
|
; CHECK: blr x17
|
|
BLR killed renamable $x17, implicit-def dead $lr, implicit $sp
|
|
RET undef $lr, implicit undef $w0
|
|
...
|
|
---
|
|
name: indirect_tailcall_x17
|
|
tracksRegLiveness: true
|
|
body: |
|
|
bb.0:
|
|
liveins: $x0
|
|
; CHECK-LABEL: indirect_tailcall_x17
|
|
; CHECK: mov x1, sp
|
|
; CHECK: and x1, x1, x16
|
|
; CHECK: mov sp, x1
|
|
; CHECK: br x17
|
|
$x8 = ADRP target-flags(aarch64-page) @g
|
|
$x17 = LDRXui killed $x8, target-flags(aarch64-pageoff, aarch64-nc) @g
|
|
TCRETURNri killed $x17, 0, implicit $sp, implicit $x0
|
|
...
|
|
---
|
|
name: indirect_call_lr
|
|
tracksRegLiveness: true
|
|
body: |
|
|
bb.0:
|
|
; CHECK-LABEL: indirect_call_lr
|
|
; CHECK: mov x1, sp
|
|
; CHECK-NEXT: and x1, x1, x16
|
|
; CHECK-NEXT: mov sp, x1
|
|
; CHECK-NEXT: blr x30
|
|
liveins: $x0, $lr
|
|
BLR killed renamable $lr, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $w0
|
|
$w0 = nsw ADDWri killed $w0, 1, 0
|
|
RET undef $lr, implicit $w0
|
|
...
|
|
---
|
|
name: RS_cannot_find_available_regs
|
|
tracksRegLiveness: true
|
|
body: |
|
|
bb.0:
|
|
; In the rare case when no free temporary register is available for the
|
|
; propagate taint-to-sp operation, just put in a full speculation barrier
|
|
; (isb+dsb sy) at the start of the basic block. And don't put masks on
|
|
; instructions for the rest of the basic block, since speculation in that
|
|
; basic block was already done, so no need to do masking.
|
|
; CHECK-LABEL: RS_cannot_find_available_regs
|
|
; CHECK: dsb sy
|
|
; CHECK-NEXT: isb
|
|
; CHECK-NEXT: ldr x0, [x0]
|
|
; The following 2 instructions come from propagating the taint encoded in
|
|
; sp at function entry to x16. It turns out the taint info in x16 is not
|
|
; used in this function, so those instructions could be optimized away. An
|
|
; optimization for later if it turns out this situation occurs often enough.
|
|
; CHECK-NEXT: cmp sp, #0
|
|
; CHECK-NEXT: csetm x16, ne
|
|
; CHECK-NEXT: ret
|
|
liveins: $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x17, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $fp, $lr
|
|
$x0 = LDRXui killed $x0, 0
|
|
RET undef $lr, implicit $x0
|
|
...
|