diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -9720,7 +9720,13 @@ // that instead. SDNode *St; if (Subtarget->hasPAuth()) { - St = DAG.getMachineNode(AArch64::XPACI, DL, VT, ReturnAddress); + MachineRegisterInfo &MRI = MF.getRegInfo(); + Register TmpReg = MRI.createVirtualRegister(&AArch64::GPR64noipRegClass); + + SDValue Chain = + DAG.getCopyToReg(DAG.getEntryNode(), DL, TmpReg, ReturnAddress); + SDValue ReturnAddressCopy = DAG.getCopyFromReg(Chain, DL, TmpReg, VT); + St = DAG.getMachineNode(AArch64::XPACI, DL, VT, ReturnAddressCopy); } else { // XPACLRI operates on LR therefore we must move the operand accordingly. SDValue Chain = diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -6016,7 +6016,10 @@ } if (STI.hasPAuth()) { - MIB.buildInstr(AArch64::XPACI, {DstReg}, {MFReturnAddr}); + Register TmpReg = + MRI.createVirtualRegister(&AArch64::GPR64noipRegClass); + MIB.buildCopy(TmpReg, MFReturnAddr); + MIB.buildInstr(AArch64::XPACI, {DstReg}, {TmpReg}); } else { MIB.buildCopy({Register(AArch64::LR)}, {MFReturnAddr}); MIB.buildInstr(AArch64::XPACLRI); diff --git a/llvm/test/CodeGen/AArch64/aarch64-signedreturnaddress.ll b/llvm/test/CodeGen/AArch64/aarch64-signedreturnaddress.ll --- a/llvm/test/CodeGen/AArch64/aarch64-signedreturnaddress.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-signedreturnaddress.ll @@ -1,5 +1,7 @@ ; RUN: llc < %s -mtriple=arm64-eabi -asm-verbose=false -mattr=v8.2a | FileCheck %s ; RUN: llc < %s -mtriple=arm64-eabi -asm-verbose=false -mattr=v8.3a | FileCheck %s --check-prefix=CHECKV83 +; RUN: llc < %s -mtriple=arm64-eabi -asm-verbose=false -mattr=v8.2a -global-isel=1 -global-isel-abort=1 | FileCheck %s +; RUN: llc < %s -mtriple=arm64-eabi -asm-verbose=false -mattr=v8.3a -global-isel=1 -global-isel-abort=1 | FileCheck %s --check-prefix=CHECKV83 ; Armv8.3-A Pointer Authetication requires a special intsruction to strip the ; pointer authentication code from the pointer. @@ -7,43 +9,96 @@ ; therefore this instruction can be safely used for any pre Armv8.3-A architectures. ; On Armv8.3-A and onwards XPACI is available so use that instead. -define ptr @ra0() nounwind readnone { +define ptr @retaddr_0() nounwind readnone "sign-return-address"="none" { entry: -; CHECK-LABEL: ra0: +; CHECK-LABEL: retaddr_0: ; CHECK-NEXT: str x30, [sp, #-16]! ; CHECK-NEXT: hint #7 ; CHECK-NEXT: mov x0, x30 ; CHECK-NEXT: ldr x30, [sp], #16 ; CHECK-NEXT: ret -; CHECKV83: str x30, [sp, #-16]! -; CHECKV83-NEXT: xpaci x30 -; CHECKV83-NEXT: mov x0, x30 -; CHECKV83-NEXT: ldr x30, [sp], #16 -; CHECKV83-NEXT: ret +; +; CHECKV83-LABEL: retaddr_0: +; CHECKV83: mov x0, x30 +; CHECKV83-NEXT: xpaci x0 +; CHECKV83-NEXT: ret %0 = tail call ptr @llvm.returnaddress(i32 0) ret ptr %0 } -define ptr @ra1() nounwind readnone #0 { +define ptr @retaddr_sign_all_0() nounwind readnone "sign-return-address"="all" { entry: -; CHECK-LABEL: ra1: -; CHECK: hint #25 +; CHECK-LABEL: retaddr_sign_all_0: +; CHECK-NEXT: hint #25 ; CHECK-NEXT: str x30, [sp, #-16]! ; CHECK-NEXT: hint #7 ; CHECK-NEXT: mov x0, x30 ; CHECK-NEXT: ldr x30, [sp], #16 ; CHECK-NEXT: hint #29 ; CHECK-NEXT: ret -; CHECKV83: paciasp -; CHECKV83-NEXT: str x30, [sp, #-16]! -; CHECKV83-NEXT: xpaci x30 -; CHECKV83-NEXT: mov x0, x30 -; CHECKV83-NEXT: ldr x30, [sp], #16 -; CHECKV83-NEXT: retaa +; +; CHECKV83-LABEL: retaddr_sign_all_0: +; CHECKV83-NEXT: paciasp +; CHECKV83-NEXT: mov x0, x30 +; CHECKV83-NEXT: xpaci x0 +; CHECKV83-NEXT: retaa %0 = tail call ptr @llvm.returnaddress(i32 0) ret ptr %0 } -attributes #0 = { "sign-return-address"="all" } +; x29 and x30 are saved because @llvm.returnaddress with non-zero argument +; takes frame address internally. + +define ptr @retaddr_1() nounwind readnone "sign-return-address"="none" { +entry: +; CHECK-LABEL: retaddr_1: +; CHECK-NEXT: stp x29, x30, [sp, #-16]! +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: ldr x8, [x29] +; CHECK-NEXT: ldr x30, [x8, #8] +; CHECK-NEXT: hint #7 +; CHECK-NEXT: mov x0, x30 +; CHECK-NEXT: ldp x29, x30, [sp], #16 +; CHECK-NEXT: ret +; +; CHECKV83-LABEL: retaddr_1: +; CHECKV83-NEXT: stp x29, x30, [sp, #-16]! +; CHECKV83-NEXT: mov x29, sp +; CHECKV83-NEXT: ldr x8, [x29] +; CHECKV83-NEXT: ldr x0, [x8, #8] +; CHECKV83-NEXT: xpaci x0 +; CHECKV83-NEXT: ldp x29, x30, [sp], #16 +; CHECKV83-NEXT: ret + %0 = tail call ptr @llvm.returnaddress(i32 1) + ret ptr %0 +} + +define ptr @retaddr_sign_all_1() nounwind readnone "sign-return-address"="all" { +entry: +; CHECK-LABEL: retaddr_sign_all_1: +; CHECK-NEXT: hint #25 +; CHECK-NEXT: stp x29, x30, [sp, #-16]! +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: ldr x8, [x29] +; CHECK-NEXT: ldr x30, [x8, #8] +; CHECK-NEXT: hint #7 +; CHECK-NEXT: mov x0, x30 +; CHECK-NEXT: ldp x29, x30, [sp], #16 +; CHECK-NEXT: hint #29 +; CHECK-NEXT: ret +; +; CHECKV83-LABEL: retaddr_sign_all_1: +; CHECKV83-NEXT: paciasp +; CHECKV83-NEXT: stp x29, x30, [sp, #-16]! +; CHECKV83-NEXT: mov x29, sp +; CHECKV83-NEXT: ldr x8, [x29] +; CHECKV83-NEXT: ldr x0, [x8, #8] +; CHECKV83-NEXT: xpaci x0 +; CHECKV83-NEXT: ldp x29, x30, [sp], #16 +; CHECKV83-NEXT: retaa + + %0 = tail call ptr @llvm.returnaddress(i32 1) + ret ptr %0 +} declare ptr @llvm.returnaddress(i32) nounwind readnone