[llvm] 2a96f47 - [AArch64] __builtin_return_address for PAuth.

Daniel Kiss via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 14:23:57 PDT 2020


Author: Daniel Kiss
Date: 2020-09-24T23:23:49+02:00
New Revision: 2a96f47c5ffca84cd774ad402cacd137f4bf45e2

URL: https://github.com/llvm/llvm-project/commit/2a96f47c5ffca84cd774ad402cacd137f4bf45e2
DIFF: https://github.com/llvm/llvm-project/commit/2a96f47c5ffca84cd774ad402cacd137f4bf45e2.diff

LOG: [AArch64] __builtin_return_address for PAuth.

This change adds the support for __builtin_return_address
for ARMv8.3A Pointer Authentication.
Location of the authentication code in the pointer depends on
the system configuration, therefore a dedicated instruction is used for
effectively removing the authentication code without
authenticating the pointer.

Reviewed By: chill

Differential Revision: https://reviews.llvm.org/D75044

Added: 
    llvm/test/CodeGen/AArch64/aarch64-signedreturnaddress.ll

Modified: 
    llvm/include/llvm/CodeGen/ISDOpcodes.h
    llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
    llvm/test/CodeGen/AArch64/arm64-returnaddr.ll
    llvm/test/CodeGen/AArch64/arm64_32.ll
    llvm/test/CodeGen/AArch64/returnaddr.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index ba5a5d6e8751..19d730738755 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -86,7 +86,16 @@ enum NodeType {
   /// 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.

diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 772f88d4f9d1..444b36ecf8c1 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -6628,17 +6628,34 @@ SDValue AArch64TargetLowering::LowerRETURNADDR(SDValue Op,
   EVT VT = Op.getValueType();
   SDLoc DL(Op);
   unsigned Depth = cast<ConstantSDNode>(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

diff  --git a/llvm/test/CodeGen/AArch64/aarch64-signedreturnaddress.ll b/llvm/test/CodeGen/AArch64/aarch64-signedreturnaddress.ll
new file mode 100644
index 000000000000..f7488d874fd1
--- /dev/null
+++ b/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

diff  --git a/llvm/test/CodeGen/AArch64/arm64-returnaddr.ll b/llvm/test/CodeGen/AArch64/arm64-returnaddr.ll
index 1e0ec5b2e5a1..006d4a77d841 100644
--- a/llvm/test/CodeGen/AArch64/arm64-returnaddr.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-returnaddr.ll
@@ -3,6 +3,7 @@
 define i8* @rt0(i32 %x) nounwind readnone {
 entry:
 ; CHECK-LABEL: rt0:
+; CHECK: hint #7
 ; CHECK: mov x0, x30
 ; CHECK: ret
   %0 = tail call i8* @llvm.returnaddress(i32 0)
@@ -16,7 +17,9 @@ entry:
 ; CHECK: mov x29, sp
 ; CHECK: ldr x[[REG:[0-9]+]], [x29]
 ; CHECK: ldr x[[REG2:[0-9]+]], [x[[REG]]]
-; CHECK: ldr x0, [x[[REG2]], #8]
+; CHECK: ldr x30, [x[[REG2]], #8]
+; CHECK: hint #7
+; CHECK: mov x0, x30
 ; CHECK: ldp x29, x30, [sp], #16
 ; CHECK: ret
   %0 = tail call i8* @llvm.returnaddress(i32 2)

diff  --git a/llvm/test/CodeGen/AArch64/arm64_32.ll b/llvm/test/CodeGen/AArch64/arm64_32.ll
index f129c463b126..4e764a7c37c0 100644
--- a/llvm/test/CodeGen/AArch64/arm64_32.ll
+++ b/llvm/test/CodeGen/AArch64/arm64_32.ll
@@ -253,7 +253,9 @@ define i8* @test_toplevel_returnaddr() {
 define i8* @test_deep_returnaddr() {
 ; CHECK-LABEL: test_deep_returnaddr:
 ; CHECK: ldr x[[FRAME_REC:[0-9]+]], [x29]
-; CHECK-OPT: ldr x0, [x[[FRAME_REC]], #8]
+; CHECK-OPT: ldr x30, [x[[FRAME_REC]], #8]
+; CHECK-OPT: hint #7
+; CHECK-OPT: mov x0, x30
 ; CHECK-FAST: ldr [[TMP:x[0-9]+]], [x[[FRAME_REC]], #8]
 ; CHECK-FAST: and x0, [[TMP]], #0xffffffff
   %val = call i8* @llvm.returnaddress(i32 1)

diff  --git a/llvm/test/CodeGen/AArch64/returnaddr.ll b/llvm/test/CodeGen/AArch64/returnaddr.ll
index b136f044cad8..3f74bfb4bcf7 100644
--- a/llvm/test/CodeGen/AArch64/returnaddr.ll
+++ b/llvm/test/CodeGen/AArch64/returnaddr.ll
@@ -3,6 +3,7 @@
 define i8* @rt0(i32 %x) nounwind readnone {
 entry:
 ; CHECK-LABEL: rt0:
+; CHECK: hint #7
 ; CHECK: mov x0, x30
   %0 = tail call i8* @llvm.returnaddress(i32 0)
   ret i8* %0
@@ -13,7 +14,9 @@ entry:
 ; CHECK-LABEL: rt2:
 ; CHECK: ldr x[[reg:[0-9]+]], [x29]
 ; CHECK: ldr x[[reg]], [x[[reg]]]
-; CHECK: ldr x0, [x[[reg]], #8]
+; CHECK: ldr x30, [x[[reg]], #8]
+; CHECK: hint #7
+; CHECK: mov x0, x30
   %0 = tail call i8* @llvm.returnaddress(i32 2)
   ret i8* %0
 }


        


More information about the llvm-commits mailing list