mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:49:45 +00:00
Create llvm.addressofreturnaddress intrinsic
Summary: We need a new LLVM intrinsic to implement MS _AddressOfReturnAddress builtin on 64-bit Windows. Reviewers: majnemer, rnk Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D25293 llvm-svn: 284061
This commit is contained in:
parent
e56bde4149
commit
14303dbdfa
@ -9294,6 +9294,32 @@ Note that calling this intrinsic does not prevent function inlining or
|
||||
other aggressive transformations, so the value returned may not be that
|
||||
of the obvious source-language caller.
|
||||
|
||||
'``llvm.addressofreturnaddress``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Syntax:
|
||||
"""""""
|
||||
|
||||
::
|
||||
|
||||
declare i8 *@llvm.addressofreturnaddress()
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The '``llvm.addressofreturnaddress``' intrinsic returns a target-specific
|
||||
pointer to the place in the stack frame where the return address of the
|
||||
current function is stored.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
Note that calling this intrinsic does not prevent function inlining or
|
||||
other aggressive transformations, so the value returned may not be that
|
||||
of the obvious source-language caller.
|
||||
|
||||
This intrinsic is only implemented for x86.
|
||||
|
||||
'``llvm.frameaddress``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -70,7 +70,7 @@ namespace ISD {
|
||||
/// 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,
|
||||
FRAMEADDR, RETURNADDR, ADDROFRETURNADDR,
|
||||
|
||||
/// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic.
|
||||
/// Materializes the offset from the local object pointer of another
|
||||
|
@ -290,6 +290,7 @@ def int_gcwrite : Intrinsic<[],
|
||||
//===--------------------- Code Generator Intrinsics ----------------------===//
|
||||
//
|
||||
def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_addressofreturnaddress : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
|
||||
def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty],
|
||||
[IntrReadMem], "llvm.read_register">;
|
||||
|
@ -184,6 +184,7 @@ static bool isInertIntrinsic(unsigned ID) {
|
||||
// TODO: Make this into a covered switch.
|
||||
switch (ID) {
|
||||
case Intrinsic::returnaddress:
|
||||
case Intrinsic::addressofreturnaddress:
|
||||
case Intrinsic::frameaddress:
|
||||
case Intrinsic::stacksave:
|
||||
case Intrinsic::stackrestore:
|
||||
|
@ -436,8 +436,14 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
|
||||
errs() << "WARNING: this target does not support the llvm."
|
||||
<< (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
|
||||
"return" : "frame") << "address intrinsic.\n";
|
||||
CI->replaceAllUsesWith(ConstantPointerNull::get(
|
||||
cast<PointerType>(CI->getType())));
|
||||
CI->replaceAllUsesWith(
|
||||
ConstantPointerNull::get(cast<PointerType>(CI->getType())));
|
||||
break;
|
||||
case Intrinsic::addressofreturnaddress:
|
||||
errs() << "WARNING: this target does not support the "
|
||||
"llvm.addressofreturnaddress intrinsic.\n";
|
||||
CI->replaceAllUsesWith(
|
||||
ConstantPointerNull::get(cast<PointerType>(CI->getType())));
|
||||
break;
|
||||
|
||||
case Intrinsic::prefetch:
|
||||
|
@ -1019,6 +1019,7 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
|
||||
case ISD::ADJUST_TRAMPOLINE:
|
||||
case ISD::FRAMEADDR:
|
||||
case ISD::RETURNADDR:
|
||||
case ISD::ADDROFRETURNADDR:
|
||||
// These operations lie about being legal: when they claim to be legal,
|
||||
// they should actually be custom-lowered.
|
||||
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
|
||||
|
@ -4770,6 +4770,10 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
||||
TLI.getPointerTy(DAG.getDataLayout()),
|
||||
getValue(I.getArgOperand(0))));
|
||||
return nullptr;
|
||||
case Intrinsic::addressofreturnaddress:
|
||||
setValue(&I, DAG.getNode(ISD::ADDROFRETURNADDR, sdl,
|
||||
TLI.getPointerTy(DAG.getDataLayout())));
|
||||
return nullptr;
|
||||
case Intrinsic::frameaddress:
|
||||
setValue(&I, DAG.getNode(ISD::FRAMEADDR, sdl,
|
||||
TLI.getPointerTy(DAG.getDataLayout()),
|
||||
|
@ -100,6 +100,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||
case ISD::JumpTable: return "JumpTable";
|
||||
case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE";
|
||||
case ISD::RETURNADDR: return "RETURNADDR";
|
||||
case ISD::ADDROFRETURNADDR: return "ADDROFRETURNADDR";
|
||||
case ISD::FRAMEADDR: return "FRAMEADDR";
|
||||
case ISD::LOCAL_RECOVER: return "LOCAL_RECOVER";
|
||||
case ISD::READ_REGISTER: return "READ_REGISTER";
|
||||
|
@ -18931,6 +18931,12 @@ SDValue X86TargetLowering::LowerRETURNADDR(SDValue Op,
|
||||
MachinePointerInfo());
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerADDROFRETURNADDR(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
DAG.getMachineFunction().getFrameInfo().setReturnAddressIsTaken(true);
|
||||
return getReturnAddressFrameIndex(DAG);
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
MachineFrameInfo &MFI = MF.getFrameInfo();
|
||||
@ -22056,6 +22062,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
case ISD::INTRINSIC_VOID:
|
||||
case ISD::INTRINSIC_W_CHAIN: return LowerINTRINSIC_W_CHAIN(Op, Subtarget, DAG);
|
||||
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
|
||||
case ISD::ADDROFRETURNADDR: return LowerADDROFRETURNADDR(Op, DAG);
|
||||
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
|
||||
case ISD::FRAME_TO_ARGS_OFFSET:
|
||||
return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
|
||||
|
@ -1130,6 +1130,7 @@ namespace llvm {
|
||||
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerADDROFRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
19
test/CodeGen/X86/addr-of-ret-addr.ll
Normal file
19
test/CodeGen/X86/addr-of-ret-addr.ll
Normal file
@ -0,0 +1,19 @@
|
||||
; RUN: llc < %s -disable-fp-elim -march=x86 | FileCheck %s --check-prefix=CHECK-X86
|
||||
; RUN: llc < %s -disable-fp-elim -march=x86-64 | FileCheck %s --check-prefix=CHECK-X64
|
||||
|
||||
define i8* @f() nounwind readnone optsize {
|
||||
entry:
|
||||
%0 = tail call i8* @llvm.addressofreturnaddress() ; <i8*> [#uses=1]
|
||||
ret i8* %0
|
||||
; CHECK-X86-LABEL: _f:
|
||||
; CHECK-X86: pushl %ebp
|
||||
; CHECK-X86: movl %esp, %ebp
|
||||
; CHECK-X86: leal 4(%ebp), %eax
|
||||
|
||||
; CHECK-X64-LABEL: f:
|
||||
; CHECK-X64: pushq %rbp
|
||||
; CHECK-X64: movq %rsp, %rbp
|
||||
; CHECK-X64: leaq 8(%rbp), %rax
|
||||
}
|
||||
|
||||
declare i8* @llvm.addressofreturnaddress() nounwind readnone
|
@ -184,7 +184,26 @@ define i64 @f10(i64* %foo, i64 %bar, i64 %baz) {
|
||||
; CHECK-NEXT: popq %rbp
|
||||
}
|
||||
|
||||
define i8* @f11() "no-frame-pointer-elim"="true" {
|
||||
; CHECK-LABEL: f11:
|
||||
; CHECK: pushq %rbp
|
||||
; CHECK: movq %rsp, %rbp
|
||||
; CHECK: .seh_setframe 5, 0
|
||||
; CHECK: leaq 8(%rbp), %rax
|
||||
%aora = call i8* @llvm.addressofreturnaddress()
|
||||
ret i8* %aora
|
||||
}
|
||||
|
||||
define i8* @f12() {
|
||||
; CHECK-LABEL: f12:
|
||||
; CHECK-NOT: push
|
||||
; CHECK: movq %rsp, %rax
|
||||
%aora = call i8* @llvm.addressofreturnaddress()
|
||||
ret i8* %aora
|
||||
}
|
||||
|
||||
declare i8* @llvm.returnaddress(i32) nounwind readnone
|
||||
declare i8* @llvm.addressofreturnaddress() nounwind readnone
|
||||
declare i64 @llvm.x86.flags.read.u64()
|
||||
|
||||
declare void @llvm.va_start(i8*) nounwind
|
||||
|
Loading…
Reference in New Issue
Block a user