diff --git a/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll b/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll --- a/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll +++ b/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll @@ -1,52 +1,28 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 -; RUN: llc -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=NOHARDENARM -dump-input-context=100 -; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=NOHARDENTHUMB -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 -; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; RUN: llc -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,NOHARDENARM -dump-input-context=100 +; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,NOHARDENTHUMB +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 ; Function Attrs: norecurse nounwind readnone define dso_local i32 @double_return(i32 %a, i32 %b) local_unnamed_addr { -; NOHARDENARM-LABEL: double_return: -; NOHARDENARM: @ %bb.0: @ %entry -; NOHARDENARM-NEXT: cmp r0, #0 -; NOHARDENARM-NEXT: mulgt r0, r1, r0 -; NOHARDENARM-NEXT: bxgt lr -; NOHARDENARM-NEXT: .LBB0_1: @ %if.else -; NOHARDENARM-NEXT: sdiv r1, r0, r1 -; NOHARDENARM-NEXT: sdiv r1, r0, r1 -; NOHARDENARM-NEXT: sdiv r0, r0, r1 -; NOHARDENARM-NEXT: bx lr -; -; NOHARDENTHUMB-LABEL: double_return: -; NOHARDENTHUMB: @ %bb.0: @ %entry -; NOHARDENTHUMB-NEXT: cmp r0, #0 -; NOHARDENTHUMB-NEXT: ble .LBB0_2 -; NOHARDENTHUMB-NEXT: @ %bb.1: @ %if.then -; NOHARDENTHUMB-NEXT: muls r0, r1, r0 -; NOHARDENTHUMB-NEXT: bx lr -; NOHARDENTHUMB-NEXT: .LBB0_2: @ %if.else -; NOHARDENTHUMB-NEXT: sdiv r1, r0, r1 -; NOHARDENTHUMB-NEXT: sdiv r1, r0, r1 -; NOHARDENTHUMB-NEXT: sdiv r0, r0, r1 -; NOHARDENTHUMB-NEXT: bx lr entry: %cmp = icmp sgt i32 %a, 0 br i1 %cmp, label %if.then, label %if.else @@ -56,6 +32,13 @@ ; it will not get predicated when sls-hardening is enabled. %mul = mul i32 %b, %a ret i32 %mul +; CHECK-LABEL: double_return: +; HARDEN: {{bx lr$}} +; NOHARDENARM: {{bxgt lr$}} +; NOHARDENTHUMB: {{bx lr$}} +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} if.else: ; preds = %entry %div3 = sdiv i32 %a, %b @@ -63,149 +46,79 @@ %div1 = sdiv i32 %a, %div2 ret i32 %div1 +; CHECK: {{bx lr$}} +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} +; CHECK-NEXT: .Lfunc_end } @__const.indirect_branch.ptr = private unnamed_addr constant [2 x i8*] [i8* blockaddress(@indirect_branch, %return), i8* blockaddress(@indirect_branch, %l2)], align 8 ; Function Attrs: norecurse nounwind readnone define dso_local i32 @indirect_branch(i32 %a, i32 %b, i32 %i) { -; NOHARDENARM-LABEL: indirect_branch: -; NOHARDENARM: @ %bb.0: @ %entry -; NOHARDENARM-NEXT: movw r0, :lower16:.L__const.indirect_branch.ptr -; NOHARDENARM-NEXT: movt r0, :upper16:.L__const.indirect_branch.ptr -; NOHARDENARM-NEXT: ldr r0, [r0, r2, lsl #2] -; NOHARDENARM-NEXT: bx r0 -; NOHARDENARM-NEXT: .Ltmp0: @ Block address taken -; NOHARDENARM-NEXT: .LBB1_1: @ %return -; NOHARDENARM-NEXT: mov r0, #0 -; NOHARDENARM-NEXT: bx lr -; NOHARDENARM-NEXT: .Ltmp1: @ Block address taken -; NOHARDENARM-NEXT: .LBB1_2: @ %l2 -; NOHARDENARM-NEXT: mov r0, #1 -; NOHARDENARM-NEXT: bx lr -; -; NOHARDENTHUMB-LABEL: indirect_branch: -; NOHARDENTHUMB: @ %bb.0: @ %entry -; NOHARDENTHUMB-NEXT: movw r0, :lower16:.L__const.indirect_branch.ptr -; NOHARDENTHUMB-NEXT: movt r0, :upper16:.L__const.indirect_branch.ptr -; NOHARDENTHUMB-NEXT: ldr.w r0, [r0, r2, lsl #2] -; NOHARDENTHUMB-NEXT: mov pc, r0 -; NOHARDENTHUMB-NEXT: .Ltmp0: @ Block address taken -; NOHARDENTHUMB-NEXT: .LBB1_1: @ %return -; NOHARDENTHUMB-NEXT: movs r0, #0 -; NOHARDENTHUMB-NEXT: bx lr -; NOHARDENTHUMB-NEXT: .Ltmp1: @ Block address taken -; NOHARDENTHUMB-NEXT: .LBB1_2: @ %l2 -; NOHARDENTHUMB-NEXT: movs r0, #1 -; NOHARDENTHUMB-NEXT: bx lr +; CHECK-LABEL: indirect_branch: entry: %idxprom = sext i32 %i to i64 %arrayidx = getelementptr inbounds [2 x i8*], [2 x i8*]* @__const.indirect_branch.ptr, i64 0, i64 %idxprom %0 = load i8*, i8** %arrayidx, align 8 indirectbr i8* %0, [label %return, label %l2] +; ARM: bx r0 +; THUMB: mov pc, r0 +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} l2: ; preds = %entry br label %return +; CHECK: {{bx lr$}} +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} return: ; preds = %entry, %l2 %retval.0 = phi i32 [ 1, %l2 ], [ 0, %entry ] ret i32 %retval.0 +; CHECK: {{bx lr$}} +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} +; CHECK-NEXT: .Lfunc_end } define i32 @asmgoto() { -; NOHARDENARM-LABEL: asmgoto: -; NOHARDENARM: @ %bb.0: @ %entry -; NOHARDENARM-NEXT: mov r0, #0 -; NOHARDENARM-NEXT: @APP -; NOHARDENARM-NEXT: b .Ltmp2 -; NOHARDENARM-NEXT: @NO_APP -; NOHARDENARM-NEXT: @ %bb.1: @ %common.ret -; NOHARDENARM-NEXT: bx lr -; NOHARDENARM-NEXT: .Ltmp2: @ Block address taken -; NOHARDENARM-NEXT: .LBB2_2: @ %d -; NOHARDENARM-NEXT: mov r0, #1 -; NOHARDENARM-NEXT: bx lr -; -; NOHARDENTHUMB-LABEL: asmgoto: -; NOHARDENTHUMB: @ %bb.0: @ %entry -; NOHARDENTHUMB-NEXT: @APP -; NOHARDENTHUMB-NEXT: b .Ltmp2 -; NOHARDENTHUMB-NEXT: @NO_APP -; NOHARDENTHUMB-NEXT: @ %bb.1: -; NOHARDENTHUMB-NEXT: movs r0, #0 -; NOHARDENTHUMB-NEXT: bx lr -; NOHARDENTHUMB-NEXT: .Ltmp2: @ Block address taken -; NOHARDENTHUMB-NEXT: .LBB2_2: @ %d -; NOHARDENTHUMB-NEXT: movs r0, #1 -; NOHARDENTHUMB-NEXT: bx lr entry: +; CHECK-LABEL: asmgoto: callbr void asm sideeffect "B $0", "X"(i8* blockaddress(@asmgoto, %d)) to label %asm.fallthrough [label %d] ; The asm goto above produces a direct branch: +; CHECK: @APP +; CHECK-NEXT: {{^[ \t]+b }} +; CHECK-NEXT: @NO_APP ; For direct branches, no mitigation is needed. ; ISDDSB-NOT: dsb sy +; SB-NOT: {{ sb$}} asm.fallthrough: ; preds = %entry ret i32 0 +; CHECK: {{bx lr$}} +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} d: ; preds = %asm.fallthrough, %entry ret i32 1 +; CHECK: {{bx lr$}} +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} +; CHECK-NEXT: .Lfunc_end } ; Check that indirect branches produced through switch jump tables are also ; hardened: define dso_local i32 @jumptable(i32 %a, i32 %b) { -; NOHARDENARM-LABEL: jumptable: -; NOHARDENARM: @ %bb.0: @ %entry -; NOHARDENARM-NEXT: cmp r1, #4 -; NOHARDENARM-NEXT: bxhi lr -; NOHARDENARM-NEXT: .LBB3_1: @ %entry -; NOHARDENARM-NEXT: adr r2, .LJTI3_0 -; NOHARDENARM-NEXT: ldr pc, [r2, r1, lsl #2] -; NOHARDENARM-NEXT: @ %bb.2: -; NOHARDENARM-NEXT: .p2align 2 -; NOHARDENARM-NEXT: .LJTI3_0: -; NOHARDENARM-NEXT: .long .LBB3_3 -; NOHARDENARM-NEXT: .long .LBB3_4 -; NOHARDENARM-NEXT: .long .LBB3_7 -; NOHARDENARM-NEXT: .long .LBB3_5 -; NOHARDENARM-NEXT: .long .LBB3_6 -; NOHARDENARM-NEXT: .LBB3_3: @ %sw.bb -; NOHARDENARM-NEXT: lsl r0, r0, #1 -; NOHARDENARM-NEXT: .LBB3_4: @ %sw.bb1 -; NOHARDENARM-NEXT: lsl r0, r0, #1 -; NOHARDENARM-NEXT: .LBB3_5: @ %sw.bb3 -; NOHARDENARM-NEXT: lsl r0, r0, #1 -; NOHARDENARM-NEXT: .LBB3_6: @ %sw.bb5 -; NOHARDENARM-NEXT: lsl r0, r0, #1 -; NOHARDENARM-NEXT: .LBB3_7: @ %sw.epilog -; NOHARDENARM-NEXT: bx lr -; -; NOHARDENTHUMB-LABEL: jumptable: -; NOHARDENTHUMB: @ %bb.0: @ %entry -; NOHARDENTHUMB-NEXT: cmp r1, #4 -; NOHARDENTHUMB-NEXT: bhi .LBB3_7 -; NOHARDENTHUMB-NEXT: @ %bb.1: @ %entry -; NOHARDENTHUMB-NEXT: .LCPI3_0: -; NOHARDENTHUMB-NEXT: tbb [pc, r1] -; NOHARDENTHUMB-NEXT: @ %bb.2: -; NOHARDENTHUMB-NEXT: .LJTI3_0: -; NOHARDENTHUMB-NEXT: .byte (.LBB3_3-(.LCPI3_0+4))/2 -; NOHARDENTHUMB-NEXT: .byte (.LBB3_4-(.LCPI3_0+4))/2 -; NOHARDENTHUMB-NEXT: .byte (.LBB3_7-(.LCPI3_0+4))/2 -; NOHARDENTHUMB-NEXT: .byte (.LBB3_5-(.LCPI3_0+4))/2 -; NOHARDENTHUMB-NEXT: .byte (.LBB3_6-(.LCPI3_0+4))/2 -; NOHARDENTHUMB-NEXT: .p2align 1 -; NOHARDENTHUMB-NEXT: .LBB3_3: @ %sw.bb -; NOHARDENTHUMB-NEXT: lsls r0, r0, #1 -; NOHARDENTHUMB-NEXT: .LBB3_4: @ %sw.bb1 -; NOHARDENTHUMB-NEXT: lsls r0, r0, #1 -; NOHARDENTHUMB-NEXT: .LBB3_5: @ %sw.bb3 -; NOHARDENTHUMB-NEXT: lsls r0, r0, #1 -; NOHARDENTHUMB-NEXT: .LBB3_6: @ %sw.bb5 -; NOHARDENTHUMB-NEXT: lsls r0, r0, #1 -; NOHARDENTHUMB-NEXT: .LBB3_7: @ %sw.epilog -; NOHARDENTHUMB-NEXT: bx lr +; CHECK-LABEL: jumptable: entry: switch i32 %b, label %sw.epilog [ i32 0, label %sw.bb @@ -213,6 +126,12 @@ i32 3, label %sw.bb3 i32 4, label %sw.bb5 ] +; ARM: ldr pc, [{{r[0-9]}}, {{r[0-9]}}, lsl #2] +; NOHARDENTHUMB: tbb [pc, {{r[0-9]}}] +; HARDENTHUMB: mov pc, {{r[0-9]}} +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} sw.bb: ; preds = %entry @@ -237,77 +156,42 @@ sw.epilog: ; preds = %sw.bb5, %entry %a.addr.3 = phi i32 [ %a, %entry ], [ %add6, %sw.bb5 ] ret i32 %a.addr.3 +; CHECK: {{bx lr$}} +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} } define dso_local i32 @indirect_call( -; NOHARDENARM-LABEL: indirect_call: -; NOHARDENARM: @ %bb.0: @ %entry -; NOHARDENARM-NEXT: .save {r4, r5, r11, lr} -; NOHARDENARM-NEXT: push {r4, r5, r11, lr} -; NOHARDENARM-NEXT: mov r4, r1 -; NOHARDENARM-NEXT: blx r0 -; NOHARDENARM-NEXT: mov r5, r0 -; NOHARDENARM-NEXT: blx r4 -; NOHARDENARM-NEXT: add r0, r0, r5 -; NOHARDENARM-NEXT: pop {r4, r5, r11, pc} -; -; NOHARDENTHUMB-LABEL: indirect_call: -; NOHARDENTHUMB: @ %bb.0: @ %entry -; NOHARDENTHUMB-NEXT: .save {r4, r5, r7, lr} -; NOHARDENTHUMB-NEXT: push {r4, r5, r7, lr} -; NOHARDENTHUMB-NEXT: mov r4, r1 -; NOHARDENTHUMB-NEXT: blx r0 -; NOHARDENTHUMB-NEXT: mov r5, r0 -; NOHARDENTHUMB-NEXT: blx r4 -; NOHARDENTHUMB-NEXT: add r0, r5 -; NOHARDENTHUMB-NEXT: pop {r4, r5, r7, pc} i32 (...)* nocapture %f1, i32 (...)* nocapture %f2) { entry: +; CHECK-LABEL: indirect_call: %callee.knr.cast = bitcast i32 (...)* %f1 to i32 ()* %call = tail call i32 %callee.knr.cast() ; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}} +; HARDENTHUMB: bl {{__llvm_slsblr_thunk_thumb_r[0-9]+$}} %callee.knr.cast1 = bitcast i32 (...)* %f2 to i32 ()* %call2 = tail call i32 %callee.knr.cast1() ; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}} +; HARDENTHUMB: bl {{__llvm_slsblr_thunk_thumb_r[0-9]+$}} %add = add nsw i32 %call2, %call ret i32 %add +; CHECK: .Lfunc_end } ; verify calling through a function pointer. @a = dso_local local_unnamed_addr global i32 (...)* null, align 8 @b = dso_local local_unnamed_addr global i32 0, align 4 define dso_local void @indirect_call_global() local_unnamed_addr { -; NOHARDENARM-LABEL: indirect_call_global: -; NOHARDENARM: @ %bb.0: @ %entry -; NOHARDENARM-NEXT: .save {r11, lr} -; NOHARDENARM-NEXT: push {r11, lr} -; NOHARDENARM-NEXT: movw r0, :lower16:a -; NOHARDENARM-NEXT: movt r0, :upper16:a -; NOHARDENARM-NEXT: ldr r0, [r0] -; NOHARDENARM-NEXT: blx r0 -; NOHARDENARM-NEXT: movw r1, :lower16:b -; NOHARDENARM-NEXT: movt r1, :upper16:b -; NOHARDENARM-NEXT: str r0, [r1] -; NOHARDENARM-NEXT: pop {r11, pc} -; -; NOHARDENTHUMB-LABEL: indirect_call_global: -; NOHARDENTHUMB: @ %bb.0: @ %entry -; NOHARDENTHUMB-NEXT: .save {r7, lr} -; NOHARDENTHUMB-NEXT: push {r7, lr} -; NOHARDENTHUMB-NEXT: movw r0, :lower16:a -; NOHARDENTHUMB-NEXT: movt r0, :upper16:a -; NOHARDENTHUMB-NEXT: ldr r0, [r0] -; NOHARDENTHUMB-NEXT: blx r0 -; NOHARDENTHUMB-NEXT: movw r1, :lower16:b -; NOHARDENTHUMB-NEXT: movt r1, :upper16:b -; NOHARDENTHUMB-NEXT: str r0, [r1] -; NOHARDENTHUMB-NEXT: pop {r7, pc} +; CHECK-LABEL: indirect_call_global: entry: %0 = load i32 ()*, i32 ()** bitcast (i32 (...)** @a to i32 ()**), align 8 %call = tail call i32 %0() nounwind ; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}} +; HARDENTHUMB: bl {{__llvm_slsblr_thunk_thumb_r[0-9]+$}} store i32 %call, i32* @b, align 4 ret void +; CHECK: .Lfunc_end } ; Verify that neither r12 nor lr are used as registers in indirect call @@ -316,106 +200,47 @@ ; (b) the hardening transformation isn't correct if lr is the register holding ; the address of the function called. define i32 @check_r12(i32 ()** %fp) { -; NOHARDENARM-LABEL: check_r12: -; NOHARDENARM: @ %bb.0: @ %entry -; NOHARDENARM-NEXT: .save {r11, lr} -; NOHARDENARM-NEXT: push {r11, lr} -; NOHARDENARM-NEXT: ldr r12, [r0] -; NOHARDENARM-NEXT: @APP -; NOHARDENARM-NEXT: add r12, r12, #0 -; NOHARDENARM-NEXT: @NO_APP -; NOHARDENARM-NEXT: blx r12 -; NOHARDENARM-NEXT: pop {r11, pc} -; -; NOHARDENTHUMB-LABEL: check_r12: -; NOHARDENTHUMB: @ %bb.0: @ %entry -; NOHARDENTHUMB-NEXT: .save {r7, lr} -; NOHARDENTHUMB-NEXT: push {r7, lr} -; NOHARDENTHUMB-NEXT: ldr.w r12, [r0] -; NOHARDENTHUMB-NEXT: @APP -; NOHARDENTHUMB-NEXT: add.w r12, r12, #0 -; NOHARDENTHUMB-NEXT: @NO_APP -; NOHARDENTHUMB-NEXT: blx r12 -; NOHARDENTHUMB-NEXT: pop {r7, pc} entry: +; CHECK-LABEL: check_r12: %f = load i32 ()*, i32 ()** %fp, align 4 ; Force f to be moved into r12 %r12_f = tail call i32 ()* asm "add $0, $1, #0", "={r12},{r12}"(i32 ()* %f) nounwind %call = call i32 %r12_f() +; NOHARDENARM: blx r12 +; NOHARDENTHUMB: blx r12 +; HARDEN-NOT: bl {{__llvm_slsblr_thunk_(arm|thumb)_r12}} ret i32 %call +; CHECK: .Lfunc_end } define i32 @check_lr(i32 ()** %fp) { -; NOHARDENARM-LABEL: check_lr: -; NOHARDENARM: @ %bb.0: @ %entry -; NOHARDENARM-NEXT: .save {r11, lr} -; NOHARDENARM-NEXT: push {r11, lr} -; NOHARDENARM-NEXT: ldr lr, [r0] -; NOHARDENARM-NEXT: @APP -; NOHARDENARM-NEXT: add lr, lr, #0 -; NOHARDENARM-NEXT: @NO_APP -; NOHARDENARM-NEXT: blx lr -; NOHARDENARM-NEXT: pop {r11, pc} -; -; NOHARDENTHUMB-LABEL: check_lr: -; NOHARDENTHUMB: @ %bb.0: @ %entry -; NOHARDENTHUMB-NEXT: .save {r7, lr} -; NOHARDENTHUMB-NEXT: push {r7, lr} -; NOHARDENTHUMB-NEXT: ldr.w lr, [r0] -; NOHARDENTHUMB-NEXT: @APP -; NOHARDENTHUMB-NEXT: add.w lr, lr, #0 -; NOHARDENTHUMB-NEXT: @NO_APP -; NOHARDENTHUMB-NEXT: blx lr -; NOHARDENTHUMB-NEXT: pop {r7, pc} entry: +; CHECK-LABEL: check_lr: %f = load i32 ()*, i32 ()** %fp, align 4 ; Force f to be moved into lr %lr_f = tail call i32 ()* asm "add $0, $1, #0", "={lr},{lr}"(i32 ()* %f) nounwind %call = call i32 %lr_f() +; NOHARDENARM: blx lr +; NOHARDENTHUMB: blx lr +; HARDEN-NOT: bl {{__llvm_slsblr_thunk_(arm|thumb)_lr}} ret i32 %call +; CHECK: .Lfunc_end } ; Verify that even when sls-harden-blr is enabled, "blx r12" is still an ; instruction that is accepted by the inline assembler define void @verify_inline_asm_blx_r12(void ()* %g) { -; ISBDSB-LABEL: verify_inline_asm_blx_r12: -; ISBDSB: @ %bb.0: @ %entry -; ISBDSB-NEXT: mov r12, r0 -; ISBDSB-NEXT: @APP -; ISBDSB-NEXT: blx r12 -; ISBDSB-NEXT: @NO_APP -; ISBDSB-NEXT: bx lr -; ISBDSB-NEXT: dsb sy -; ISBDSB-NEXT: isb sy -; -; SB-LABEL: verify_inline_asm_blx_r12: -; SB: @ %bb.0: @ %entry -; SB-NEXT: mov r12, r0 -; SB-NEXT: @APP -; SB-NEXT: blx r12 -; SB-NEXT: @NO_APP -; SB-NEXT: bx lr -; SB-NEXT: sb -; -; NOHARDENARM-LABEL: verify_inline_asm_blx_r12: -; NOHARDENARM: @ %bb.0: @ %entry -; NOHARDENARM-NEXT: mov r12, r0 -; NOHARDENARM-NEXT: @APP -; NOHARDENARM-NEXT: blx r12 -; NOHARDENARM-NEXT: @NO_APP -; NOHARDENARM-NEXT: bx lr -; -; NOHARDENTHUMB-LABEL: verify_inline_asm_blx_r12: -; NOHARDENTHUMB: @ %bb.0: @ %entry -; NOHARDENTHUMB-NEXT: mov r12, r0 -; NOHARDENTHUMB-NEXT: @APP -; NOHARDENTHUMB-NEXT: blx r12 -; NOHARDENTHUMB-NEXT: @NO_APP -; NOHARDENTHUMB-NEXT: bx lr entry: +; CHECK-LABEL: verify_inline_asm_blx_r12: %0 = bitcast void ()* %g to i8* tail call void asm sideeffect "blx $0", "{r12}"(i8* %0) nounwind +; CHECK: blx r12 ret void +; CHECK: {{bx lr$}} +; ISBDSB-NEXT: dsb sy +; ISBDSB-NEXT: isb +; SB-NEXT: {{ sb$}} +; CHECK: .Lfunc_end } ; HARDEN-COMDAT: .section {{.text.__llvm_slsblr_thunk_(arm|thumb)_r5}}