Index: llvm/include/llvm/CodeGen/ISDOpcodes.h =================================================================== --- llvm/include/llvm/CodeGen/ISDOpcodes.h +++ llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -86,7 +86,16 @@ /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, + + /// ADDROFRETURNADDR - Represents the llvm.addressofreturnaddress intrinsic. + /// This node takes no operand, returns a target-specific pointer to the + /// place in the stack frame where the return address of the current + /// function is stored. ADDROFRETURNADDR, + + /// SPONENTRY - Represents the llvm.sponentry intrinsic. Takes no argument + /// and returns the stack pointer value at the entry of the current + /// function calling this intrinsic. SPONENTRY, /// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic. Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -6388,17 +6388,34 @@ EVT VT = Op.getValueType(); SDLoc DL(Op); unsigned Depth = cast(Op.getOperand(0))->getZExtValue(); + SDValue ReturnAddress; if (Depth) { SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); SDValue Offset = DAG.getConstant(8, DL, getPointerTy(DAG.getDataLayout())); - return DAG.getLoad(VT, DL, DAG.getEntryNode(), - DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset), - MachinePointerInfo()); + ReturnAddress = DAG.getLoad( + VT, DL, DAG.getEntryNode(), + DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset), MachinePointerInfo()); + } else { + // Return LR, which contains the return address. Mark it an implicit + // live-in. + unsigned Reg = MF.addLiveIn(AArch64::LR, &AArch64::GPR64RegClass); + ReturnAddress = DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT); + } + + // The XPACLRI instruction assembles to a hint-space instruction before + // Armv8.3-A 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. + SDNode *St; + if (Subtarget->hasV8_3aOps()) { + St = DAG.getMachineNode(AArch64::XPACI, DL, VT, ReturnAddress); + } else { + // XPACLRI operates on LR therefore we must move the operand accordingly. + SDValue Chain = + DAG.getCopyToReg(DAG.getEntryNode(), DL, AArch64::LR, ReturnAddress); + St = DAG.getMachineNode(AArch64::XPACLRI, DL, VT, Chain); } - - // Return LR, which contains the return address. Mark it an implicit live-in. - unsigned Reg = MF.addLiveIn(AArch64::LR, &AArch64::GPR64RegClass); - return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT); + return SDValue(St, 0); } /// LowerShiftRightParts - Lower SRA_PARTS, which returns two Index: llvm/test/CodeGen/AArch64/aarch64-signedreturnaddress.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/aarch64-signedreturnaddress.ll @@ -0,0 +1,49 @@ +; 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 + +; Armv8.3-A Pointer Authetication requires a special intsruction to strip the +; pointer authentication code from the pointer. +; The XPACLRI instruction assembles to a hint-space instruction before Armv8.3-A +; 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 i8* @ra0() nounwind readnone { +entry: +; CHECK-LABEL: ra0: +; 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 + %0 = tail call i8* @llvm.returnaddress(i32 0) + ret i8* %0 +} + +define i8* @ra1() nounwind readnone #0 { +entry: +; CHECK-LABEL: ra1: +; CHECK: 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 + %0 = tail call i8* @llvm.returnaddress(i32 0) + ret i8* %0 +} + +attributes #0 = { "sign-return-address"="all" } + +declare i8* @llvm.returnaddress(i32) nounwind readnone