Index: llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -4717,7 +4717,19 @@ EntryBlock.addLiveIn(AArch64::LR); MachineIRBuilder EntryBuilder(MF); EntryBuilder.setInstr(*EntryBlock.begin()); - EntryBuilder.buildCopy({DstReg}, {Register(AArch64::LR)}); + if (MF.getFunction().hasFnAttribute("sign-return-address")) { + if (STI.hasV8_3aOps()) { + Register TmpReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass); + EntryBuilder.buildCopy({TmpReg}, {Register(AArch64::LR)}); + EntryBuilder.buildInstr(AArch64::XPACI, {DstReg}, {TmpReg}); + } else { + EntryBuilder.buildInstr(AArch64::XPACLRI); + EntryBuilder.buildCopy({DstReg}, {Register(AArch64::LR)}); + } + } else { + EntryBuilder.buildCopy({DstReg}, {Register(AArch64::LR)}); + } + MFReturnAddr = DstReg; I.eraseFromParent(); return true; @@ -4738,7 +4750,20 @@ MIRBuilder.buildCopy({DstReg}, {FrameAddr}); else { MFI.setReturnAddressIsTaken(true); - MIRBuilder.buildInstr(AArch64::LDRXui, {DstReg}, {FrameAddr}).addImm(1); + + if (MF.getFunction().hasFnAttribute("sign-return-address")) { + if (STI.hasV8_3aOps()) { + Register TmpReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass); + MIRBuilder.buildInstr(AArch64::LDRXui, {TmpReg}, {FrameAddr}).addImm(1); + MIRBuilder.buildInstr(AArch64::XPACI, {DstReg}, {TmpReg}); + } else { + MIRBuilder.buildInstr(AArch64::LDRXui, {Register(AArch64::LR)}, {FrameAddr}).addImm(1); + MIRBuilder.buildInstr(AArch64::XPACLRI); + MIRBuilder.buildCopy({DstReg}, {Register(AArch64::LR)}); + } + } else { + MIRBuilder.buildInstr(AArch64::LDRXui, {DstReg}, {FrameAddr}).addImm(1); + } } I.eraseFromParent(); Index: llvm/test/CodeGen/AArch64/GlobalISel/builtin-return-address-pacret.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/GlobalISel/builtin-return-address-pacret.ll @@ -0,0 +1,100 @@ +;; RUN: llc -mtriple aarch64 -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOP +;; RUN: llc -mtriple aarch64 -mattr=+v8.3a -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-V83 +declare void @g0() #1 +declare void @g1(i8*) #1 +declare void @g2(i32, i8*) #1 + +declare i8* @llvm.returnaddress(i32 immarg) #2 + +define i8* @f0() #0 { +entry: + %0 = call i8* @llvm.returnaddress(i32 0) + call void @g1(i8* %0) + %1 = call i8* @llvm.returnaddress(i32 1) + call void @g2(i32 1, i8* %1) + %2 = call i8* @llvm.returnaddress(i32 2) + ret i8* %2 +} +;; CHECK-LABEL: f0: +;; CHECK-NOT: {{(mov|ldr)}} x30 +;; CHECK-NOP: hint #7 +;; CHECK-V83: xpaci x30 +;; CHECK: bl g1 +;; CHECK: ldr x[[T0:[0-9]+]], [x29] +;; CHECK-NOP-NEXT: ldr x30, [x[[T0]], #8] +;; CHECK-NOP-NEXT: hint #7 +;; CHECK-V83-NEXT: ldr x[[T0]], [x[[T0]], #8] +;; CHECK-V83-NEXT: xpaci x[[T0]] +;; CHECK: bl g2 +;; CHECK: ldr x[[T1:[0-9]+]], [x29] +;; CHECK-NEXT: ldr x[[T1]], [x[[T1]]] +;; CHECK-NOP-NEXT: ldr x30, [x[[T1]], #8] +;; CHECK-NOP-NEXT: hint #7 +;; CHECK-V83-NEXT: ldr x[[T1]], [x[[T1]], #8] +;; CHECK-V83-NEXT: xpaci x[[T1]] + +define i8* @f1() #0 { +entry: + %0 = call i8* @llvm.returnaddress(i32 1) + call void @g1(i8* %0) + %1 = call i8* @llvm.returnaddress(i32 2) + call void @g2(i32 1, i8* %1) + %2 = call i8* @llvm.returnaddress(i32 0) + ret i8* %2 +} +;; CHECK-LABEL: f1: +;; CHECK-NOT: {{(mov|ldr)}} x30 +;; CHECK-NOP: hint #7 +;; CHECK-V83: xpaci x30 +;; CHECK-NOP-DAG: ldr x[[T0:[0-9]+]], [x29] +;; CHECK-NOP-DAG: str x30, [sp, #[[OFF:[0-9]+]] +;; CHECK-NOP: ldr x30, [x[[T0]], #8] +;; CHECK-NOP-NEXT: hint #7 +;; CHECK-V83: ldr x[[T0:[0-9]+]], [x29] +;; CHECK-V83-NEXT: ldr x[[T0]], [x[[T0]], #8] +;; CHECK-V83-NEXT: xpaci x[[T0]] +;; CHECK-V83: str x30, [sp, #[[OFF:[0-9]+]]] +;; CHECK: bl g1 +;; CHECK: ldr x[[T1:[0-9]+]], [x29] +;; CHECK-NOP-NEXT: ldr x[[T1]], [x[[T1]]] +;; CHECK-NOP-NEXT: ldr x30, [x[[T1]], #8] +;; CHECK-NOP-NEXT: hint #7 +;; CHECK-V83-NEXT: ldr x[[T1]], [x[[T1]]] +;; CHECK-V83-NEXT: ldr x[[T1]], [x[[T1]], #8] +;; CHECK-V83-NEXT: xpaci x[[T1]] +;; CHECK: ldr x0, [sp, #[[OFF]]] +;; CHECK-NOT: x0 +;; CHECK: ret + +define i8* @f2() #0 { +entry: + call void bitcast (void ()* @g0 to void ()*)() + %0 = call i8* @llvm.returnaddress(i32 0) + ret i8* %0 +} +;; CHECK-LABEL: f2: +;; CHECK: str x30, [sp, +;; CHECK-NOP-NEXT: hint #7 +;; CHECK-V83-NEXT: xpaci x30 +;; CHECK-NEXT: str x30, [sp, #[[OFF:[0-9]+]]] +;; CHECK: bl g0 +;; CHECK: ldr x0, [sp, #[[OFF]]] +;; CHECK-NOT: x0 +;; CHECK: ret + +define i8* @f3() #0 { +entry: + %0 = call i8* @llvm.returnaddress(i32 0) + ret i8* %0 +} +;; CHECK-LABEL: f3: +;; CHECK: str x30, +;; CHECK-NOP-NEXT: hint #7 +;; CHECK-V83-NEXT: xpaci x30 +;; CHECK-NEXT: mov x0, x30 +;; CHECK-NOT: x0 +;; CHECK: ret + +attributes #0 = { nounwind "sign-return-address"="all" "sign-return-address-key"="a_key" } +attributes #1 = { nounwind } +attributes #2 = { nounwind readnone }