diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp index 0d2ce26a942e0..bc1360e212307 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -594,6 +594,27 @@ SDValue XtensaTargetLowering::LowerSELECT_CC(SDValue Op, FalseValue, TargetCC); } +SDValue XtensaTargetLowering::LowerRETURNADDR(SDValue Op, + SelectionDAG &DAG) const { + // This nodes represent llvm.returnaddress on the DAG. + // It takes one operand, the index of the return address to return. + // An index of zero corresponds to the current function's return address. + // An index of one to the parent's return address, and so on. + // Depths > 0 not supported yet! + if (Op.getConstantOperandVal(0) != 0) + return SDValue(); + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + EVT VT = Op.getValueType(); + MFI.setReturnAddressIsTaken(true); + + // Return RA, which contains the return address. Mark it an implicit + // live-in. + Register RA = MF.addLiveIn(Xtensa::A0, getRegClassFor(MVT::i32)); + return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), RA, VT); +} + SDValue XtensaTargetLowering::LowerImmediate(SDValue Op, SelectionDAG &DAG) const { const ConstantSDNode *CN = cast(Op); @@ -722,6 +743,28 @@ SDValue XtensaTargetLowering::LowerSTACKRESTORE(SDValue Op, Op.getOperand(1)); } +SDValue XtensaTargetLowering::LowerFRAMEADDR(SDValue Op, + SelectionDAG &DAG) const { + // This nodes represent llvm.frameaddress on the DAG. + // It takes one operand, the index of the frame address to return. + // An index of zero corresponds to the current function's frame address. + // An index of one to the parent's frame address, and so on. + // Depths > 0 not supported yet! + if (Op.getConstantOperandVal(0) != 0) + return SDValue(); + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + MFI.setFrameAddressIsTaken(true); + EVT VT = Op.getValueType(); + SDLoc DL(Op); + + Register FrameRegister = Subtarget.getRegisterInfo()->getFrameRegister(MF); + SDValue FrameAddr = + DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameRegister, VT); + return FrameAddr; +} + SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const { SDValue Chain = Op.getOperand(0); // Legalize the chain. @@ -867,6 +910,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op, return LowerBR_JT(Op, DAG); case ISD::Constant: return LowerImmediate(Op, DAG); + case ISD::RETURNADDR: + return LowerRETURNADDR(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::BlockAddress: @@ -883,6 +928,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op, return LowerSTACKSAVE(Op, DAG); case ISD::STACKRESTORE: return LowerSTACKRESTORE(Op, DAG); + case ISD::FRAMEADDR: + return LowerFRAMEADDR(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); case ISD::SHL_PARTS: diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h index 8e7346b40dfe5..2a878e45047d2 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h @@ -125,12 +125,16 @@ class XtensaTargetLowering : public TargetLowering { SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; diff --git a/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll b/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll new file mode 100644 index 0000000000000..e7e5094ac9bc4 --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll @@ -0,0 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=xtensa < %s \ +; RUN: | FileCheck %s + +declare ptr @llvm.frameaddress(i32) +declare ptr @llvm.returnaddress(i32) + +define ptr @test_frameaddress_0() nounwind { +; CHECK-LABEL: test_frameaddress_0: +; CHECK: or a2, a1, a1 +; CHECK-NEXT: ret + %frameaddr = call ptr @llvm.frameaddress(i32 0) + ret ptr %frameaddr +} + +define ptr @test_returnaddress_0() nounwind { +; CHECK-LABEL: test_returnaddress_0: +; CHECK: or a2, a0, a0 +; CHECK-NEXT: ret + %retaddr = call ptr @llvm.returnaddress(i32 0) + ret ptr %retaddr +} + +define ptr @test_frameaddress_1() nounwind { +; CHECK-LABEL: test_frameaddress_1: +; CHECK: movi a2, 0 +; CHECK-NEXT: ret + %frameaddr = call ptr @llvm.frameaddress(i32 1) + ret ptr %frameaddr +} + +define ptr @test_returnaddress_1() nounwind { +; CHECK-LABEL: test_returnaddress_1: +; CHECK: movi a2, 0 +; CHECK-NEXT: ret + %retaddr = call ptr @llvm.returnaddress(i32 1) + ret ptr %retaddr +}