1# RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu \ 2# RUN: -start-before aarch64-sls-hardening -o - %s \ 3# RUN: -asm-verbose=0 \ 4# RUN: | FileCheck %s \ 5# RUN: --implicit-check-not=__llvm_slsblr_thunk_aa_x5_x8 \ 6# RUN: --implicit-check-not=__llvm_slsblr_thunk_ab_x5_x8 \ 7# RUN: --implicit-check-not=__llvm_slsblr_thunk_aaz_x5 \ 8# RUN: --implicit-check-not=__llvm_slsblr_thunk_abz_x5 9 10# Pointer Authentication extension introduces more branch-with-link-to-register 11# instructions for the BLR SLS hardening to handle, namely BLRAA, BLRAB, BLRAAZ 12# and BLRABZ. Unlike the non-authenticating BLR instruction, BLRAA and BLRAB 13# accept two register operands (almost 900 combinations for each instruction). 14# For that reason, it is not practical to create all possible thunks. 15 16# Check that the BLR SLS hardening transforms BLRA* instructions into 17# unconditional BL calls to the correct thunk functions. 18# Check that only relevant thunk functions are generated. 19--- | 20 define void @test_instructions() #0 { 21 entry: 22 ret void 23 } 24 25 define void @test_no_redef() #0 { 26 entry: 27 ret void 28 } 29 30 define void @test_regs() #0 { 31 entry: 32 ret void 33 } 34 35 attributes #0 = { "target-features"="+pauth,+harden-sls-blr" } 36... 37 38# Test that all BLRA* instructions are handled. 39--- 40name: test_instructions 41tracksRegLiveness: true 42body: | 43 bb.0.entry: 44 liveins: $lr, $x0, $x1, $x2, $x3 45 46 BLRAA $x0, $x1, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 47 BLRAB $x1, $x2, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 48 BLRAAZ $x2, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 49 BLRABZ $x3, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 50 RET undef $lr 51... 52 53# Test that the same thunk function is not created twice. 54--- 55name: test_no_redef 56tracksRegLiveness: true 57body: | 58 bb.0.entry: 59 liveins: $lr, $x0, $x1, $x2, $x3, $x4 60 61 ; thunk used by @test_instructions 62 BLRAB $x1, $x2, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 63 64 ; thunk used by this function twice 65 BLRAB $x3, $x4, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 66 BLRAB $x3, $x4, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 67 68 RET undef $lr 69... 70 71# Test that all xN registers (except x16, x17, x30 and xzr) are handled. 72--- 73name: test_regs 74tracksRegLiveness: true 75body: | 76 bb.0.entry: 77 liveins: $lr, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $fp 78 79 BLRAA $x0, $x1, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 80 BLRAA $x2, $x3, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 81 BLRAA $x4, $x5, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 82 BLRAA $x6, $x7, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 83 BLRAA $x8, $x9, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 84 BLRAA $x10, $x11, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 85 BLRAA $x12, $x13, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 86 BLRAA $x14, $x15, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 87 ; skipping x16 and x17 88 BLRAA $x18, $x19, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 89 BLRAA $x20, $x21, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 90 BLRAA $x22, $x23, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 91 BLRAA $x24, $x25, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 92 BLRAA $x26, $x27, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 93 BLRAA $x28, $fp, implicit-def $lr, implicit $sp, implicit-def $sp, implicit-def $w0 94 RET undef $lr 95... 96 97# CHECK-LABEL: test_instructions: 98# CHECK-NEXT: .cfi_startproc 99# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x0_x1 100# CHECK-NEXT: bl __llvm_slsblr_thunk_ab_x1_x2 101# CHECK-NEXT: bl __llvm_slsblr_thunk_aaz_x2 102# CHECK-NEXT: bl __llvm_slsblr_thunk_abz_x3 103# CHECK-NEXT: ret 104 105# CHECK-LABEL: test_no_redef: 106# CHECK-NEXT: .cfi_startproc 107# CHECK-NEXT: bl __llvm_slsblr_thunk_ab_x1_x2 108# CHECK-NEXT: bl __llvm_slsblr_thunk_ab_x3_x4 109# CHECK-NEXT: bl __llvm_slsblr_thunk_ab_x3_x4 110# CHECK-NEXT: ret 111 112# CHECK-LABEL: test_regs: 113# CHECK-NEXT: .cfi_startproc 114# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x0_x1 115# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x2_x3 116# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x4_x5 117# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x6_x7 118# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x8_x9 119# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x10_x11 120# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x12_x13 121# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x14_x15 122# skipping x16 and x17 123# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x18_x19 124# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x20_x21 125# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x22_x23 126# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x24_x25 127# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x26_x27 128# CHECK-NEXT: bl __llvm_slsblr_thunk_aa_x28_x29 129# CHECK-NEXT: ret 130 131# CHECK-LABEL: __llvm_slsblr_thunk_aa_x0_x1: 132# CHECK-NEXT: mov x16, x0 133# CHECK-NEXT: braa x16, x1 134# CHECK-NEXT: dsb sy 135# CHECK-NEXT: isb 136 137# CHECK-LABEL: __llvm_slsblr_thunk_ab_x1_x2: 138# CHECK-NEXT: mov x16, x1 139# CHECK-NEXT: brab x16, x2 140# CHECK-NEXT: dsb sy 141# CHECK-NEXT: isb 142 143# CHECK-LABEL: __llvm_slsblr_thunk_aaz_x2: 144# CHECK-NEXT: mov x16, x2 145# CHECK-NEXT: braaz x16 146# CHECK-NEXT: dsb sy 147# CHECK-NEXT: isb 148 149# CHECK-LABEL: __llvm_slsblr_thunk_abz_x3: 150# CHECK-NEXT: mov x16, x3 151# CHECK-NEXT: brabz x16 152# CHECK-NEXT: dsb sy 153# CHECK-NEXT: isb 154 155# The instruction *operands* should correspond to the thunk function *name* 156# (check that the name is parsed correctly when populating the thunk). 157 158# CHECK-LABEL: __llvm_slsblr_thunk_aa_x2_x3: 159# CHECK-NEXT: mov x16, x2 160# CHECK: braa x16, x3 161 162# CHECK-LABEL: __llvm_slsblr_thunk_aa_x4_x5: 163# CHECK-NEXT: mov x16, x4 164# CHECK: braa x16, x5 165 166# CHECK-LABEL: __llvm_slsblr_thunk_aa_x6_x7: 167# CHECK-NEXT: mov x16, x6 168# CHECK: braa x16, x7 169 170# CHECK-LABEL: __llvm_slsblr_thunk_aa_x8_x9: 171# CHECK-NEXT: mov x16, x8 172# CHECK: braa x16, x9 173 174# CHECK-LABEL: __llvm_slsblr_thunk_aa_x10_x11: 175# CHECK-NEXT: mov x16, x10 176# CHECK: braa x16, x11 177 178# CHECK-LABEL: __llvm_slsblr_thunk_aa_x12_x13: 179# CHECK-NEXT: mov x16, x12 180# CHECK: braa x16, x13 181 182# CHECK-LABEL: __llvm_slsblr_thunk_aa_x14_x15: 183# CHECK-NEXT: mov x16, x14 184# CHECK: braa x16, x15 185 186# skipping x16 and x17 187 188# CHECK-LABEL: __llvm_slsblr_thunk_aa_x18_x19: 189# CHECK-NEXT: mov x16, x18 190# CHECK: braa x16, x19 191 192# CHECK-LABEL: __llvm_slsblr_thunk_aa_x20_x21: 193# CHECK-NEXT: mov x16, x20 194# CHECK: braa x16, x21 195 196# CHECK-LABEL: __llvm_slsblr_thunk_aa_x22_x23: 197# CHECK-NEXT: mov x16, x22 198# CHECK: braa x16, x23 199 200# CHECK-LABEL: __llvm_slsblr_thunk_aa_x24_x25: 201# CHECK-NEXT: mov x16, x24 202# CHECK: braa x16, x25 203 204# CHECK-LABEL: __llvm_slsblr_thunk_aa_x26_x27: 205# CHECK-NEXT: mov x16, x26 206# CHECK: braa x16, x27 207 208# CHECK-LABEL: __llvm_slsblr_thunk_aa_x28_x29: 209# CHECK-NEXT: mov x16, x28 210# CHECK: braa x16, x29 211