danielkiss updated this revision to Diff 254921.
danielkiss added a comment.
Rebased.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D75044/new/
https://reviews.llvm.org/D75044
Files:
clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGen/arm64-extractreturnaddress.c
llvm/docs/LangRef.rst
llvm/include/llvm/CodeGen/ISDOpcodes.h
llvm/include/llvm/IR/Intrinsics.td
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/lib/Target/AArch64/AArch64ISelLowering.h
llvm/test/CodeGen/AArch64/aarch64-extractreturnaddress.ll
Index: llvm/test/CodeGen/AArch64/aarch64-extractreturnaddress.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AArch64/aarch64-extractreturnaddress.ll
@@ -0,0 +1,29 @@
+; 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* @era0(i8* %x) nounwind readnone #0 {
+entry:
+; CHECK-LABEL: era0:
+; CHECK: hint #25
+; CHECK-NEXT: str x30, [sp, #-16]!
+; CHECK-NEXT: mov x30, x0
+; 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: xpaci x0
+; CHECKV83-NEXT: retaa
+ %0 = tail call i8* @llvm.extractreturnaddress(i8* %x)
+ ret i8* %0
+}
+attributes #0 = { "sign-return-address"="all" }
+
+declare i8* @llvm.extractreturnaddress(i8*) nounwind readnone
Index: llvm/lib/Target/AArch64/AArch64ISelLowering.h
===================================================================
--- llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -768,6 +768,7 @@
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSPONENTRY(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerEXTRACTRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3323,6 +3323,8 @@
return LowerSPONENTRY(Op, DAG);
case ISD::RETURNADDR:
return LowerRETURNADDR(Op, DAG);
+ case ISD::EXTRACTRETURNADDR:
+ return LowerEXTRACTRETURNADDR(Op, DAG);
case ISD::ADDROFRETURNADDR:
return LowerADDROFRETURNADDR(Op, DAG);
case ISD::INSERT_VECTOR_ELT:
@@ -6027,6 +6029,29 @@
return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT);
}
+SDValue AArch64TargetLowering::LowerEXTRACTRETURNADDR(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ EVT VT = Op.getValueType();
+
+ // 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.
+ if (Subtarget->hasV8_3aOps()) {
+ SDValue Reg =
+ DAG.getCopyToReg(DAG.getEntryNode(), DL, AArch64::X0, Op.getOperand(0));
+ SDNode *St = DAG.getMachineNode(AArch64::XPACI, DL, VT, Reg);
+ return SDValue(St, 0);
+ } else {
+ // XPACLRI operates on LR therefore we must move the operand accordingly.
+ SDValue Reg =
+ DAG.getCopyToReg(DAG.getEntryNode(), DL, AArch64::LR, Op.getOperand(0));
+ SDNode *St = DAG.getMachineNode(AArch64::XPACLRI, DL, VT, Reg);
+ return SDValue(St, 0);
+ }
+}
+
/// LowerShiftRightParts - Lower SRA_PARTS, which returns two
/// i64 values and take a 2 x i64 value to shift plus a shift amount.
SDValue AArch64TargetLowering::LowerShiftRightParts(SDValue Op,
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -5642,6 +5642,11 @@
TLI.getPointerTy(DAG.getDataLayout()),
getValue(I.getArgOperand(0))));
return;
+ case Intrinsic::extractreturnaddress:
+ setValue(&I, DAG.getNode(ISD::EXTRACTRETURNADDR, sdl,
+ TLI.getPointerTy(DAG.getDataLayout()),
+ getValue(I.getArgOperand(0))));
+ return;
case Intrinsic::addressofreturnaddress:
setValue(&I, DAG.getNode(ISD::ADDROFRETURNADDR, sdl,
TLI.getPointerTy(DAG.getDataLayout())));
Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -1088,6 +1088,7 @@
case ISD::ADJUST_TRAMPOLINE:
case ISD::FRAMEADDR:
case ISD::RETURNADDR:
+ case ISD::EXTRACTRETURNADDR:
case ISD::ADDROFRETURNADDR:
case ISD::SPONENTRY:
// These operations lie about being legal: when they claim to be legal,
Index: llvm/include/llvm/IR/Intrinsics.td
===================================================================
--- llvm/include/llvm/IR/Intrinsics.td
+++ llvm/include/llvm/IR/Intrinsics.td
@@ -430,6 +430,7 @@
def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>;
def int_addressofreturnaddress : Intrinsic<[llvm_anyptr_ty], [], [IntrNoMem]>;
def int_frameaddress : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>;
+def int_extractreturnaddress : Intrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty], [IntrNoMem]>;
def int_sponentry : Intrinsic<[llvm_anyptr_ty], [], [IntrNoMem]>;
def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty],
[IntrReadMem], "llvm.read_register">;
Index: llvm/include/llvm/CodeGen/ISDOpcodes.h
===================================================================
--- llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -71,7 +71,7 @@
/// of the frame or return address to return. An index of zero corresponds
/// to the current function's frame or return address, an index of one to
/// the parent's frame or return address, and so on.
- FRAMEADDR, RETURNADDR, ADDROFRETURNADDR, SPONENTRY,
+ FRAMEADDR, RETURNADDR, ADDROFRETURNADDR, EXTRACTRETURNADDR, SPONENTRY,
/// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic.
/// Materializes the offset from the local object pointer of another
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -11311,6 +11311,36 @@
other aggressive transformations, so the value returned may not be that
of the obvious source-language caller.
+'``llvm.extractreturnaddress``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare i8* @llvm.extractreturnaddress(i8* <addr>)
+
+Overview:
+"""""""""
+
+The '``llvm.extractreturnaddress``' intrinsic post processes the return
+address. On most architechutre it could return with the address as it is.
+
+Arguments:
+""""""""""
+
+The argument to this intrinsic is an address from '``llvm.returnaddress``'.
+
+Semantics:
+""""""""""
+
+The '``llvm.extractreturnaddress``' intrinsic returns a pointer that is
+post processed. There is no validation on the address therefore the required
+transformation will be performed on any argument.
+
+This intrinsic is only implemented for aarch64.
+
'``llvm.addressofreturnaddress``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Index: clang/test/CodeGen/arm64-extractreturnaddress.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/arm64-extractreturnaddress.c
@@ -0,0 +1,23 @@
+// REQUIRES: aarch64-registered-target
+// RUN: %clang -target arm64-none-linux-gnu -march=armv8-a \
+// RUN: -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang -target arm64-none-linux-gnu -march=armv8-a -mbranch-protection=pac-ret \
+// RUN: -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-PAC
+// RUN: %clang -target arm64-none-linux-gnu -march=armv8.3-a -mbranch-protection=pac-ret \
+// RUN: -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-PAC83
+// RUN: %clang -target arm64-none-linux-gnu -march=armv8-a -mbranch-protection=standard \
+// RUN: -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BPROT8
+// RUN: %clang -target arm64-none-linux-gnu -march=armv8.5-a -mbranch-protection=standard \
+// RUN: -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BPROT83
+
+// CHECK:; Function Attrs: noinline nounwind optnone
+// CHECK: define dso_local i8* @bar() #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i8* inttoptr (i64 42 to i8*)
+// CHECK-PAC: %0 = call i8* @llvm.extractreturnaddress.p0i8.p0i8(i8* inttoptr (i64 42 to i8*))
+// CHECK-PAC83: %0 = call i8* @llvm.extractreturnaddress.p0i8.p0i8(i8* inttoptr (i64 42 to i8*))
+// CHECK-BPROT8: %0 = call i8* @llvm.extractreturnaddress.p0i8.p0i8(i8* inttoptr (i64 42 to i8*))
+// CHECK-BPROT83: %0 = call i8* @llvm.extractreturnaddress.p0i8.p0i8(i8* inttoptr (i64 42 to i8*))
+void *bar() {
+ return __builtin_extract_return_addr((void *)42);
+}
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -5142,6 +5142,20 @@
if (BranchTargetEnforcement)
Fn->addFnAttr("branch-target-enforcement");
}
+ llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const override {
+ LangOptions::SignReturnAddressScopeKind Scope =
+ CGF.CGM.getLangOpts().getSignReturnAddressScope();
+ if (Scope == LangOptions::SignReturnAddressScopeKind::None) {
+ return Address;
+ }
+ llvm::Function *F =
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::extractreturnaddress,
+ {Address->getType(), Address->getType()});
+ llvm::CallInst *Call = CGF.Builder.CreateCall(F, Address);
+ Call->setDoesNotAccessMemory();
+ return Call;
+ }
};
class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits