diff options
author | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2011-01-12 05:08:36 +0000 |
---|---|---|
committer | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2011-01-12 05:08:36 +0000 |
commit | 860b64cb1efba110bf81bcc243a6fbaae4c655a4 (patch) | |
tree | 0fbcd6ecf3039ba4ef61992f15f573f5ad716211 /lib/Target/Sparc | |
parent | c178308b23f796b6f5c15c8b3f742cc7b3336d6b (diff) |
Implement RETURNADDR and FRAMEADDR lowering in SPARC backend.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123310 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/Sparc')
-rw-r--r-- | lib/Target/Sparc/SparcISelLowering.cpp | 77 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcISelLowering.h | 3 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcInstrInfo.td | 9 |
3 files changed, 85 insertions, 4 deletions
diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index ec8c7b4809..b7edd8ada4 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -743,6 +743,8 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { case SPISD::ITOF: return "SPISD::ITOF"; case SPISD::CALL: return "SPISD::CALL"; case SPISD::RET_FLAG: return "SPISD::RET_FLAG"; + case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG"; + case SPISD::FLUSH: return "SPISD::FLUSH"; } } @@ -990,13 +992,82 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) { } +static SDValue getFLUSH(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + SDValue Chain = DAG.getNode(SPISD::FLUSH, + dl, MVT::Other, DAG.getEntryNode()); + return Chain; +} + +static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MFI->setFrameAddressIsTaken(true); + + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned FrameReg = SP::I6; + + uint64_t depth = Op.getConstantOperandVal(0); + + SDValue FrameAddr; + if (depth == 0) + FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); + else { + // flush first to make sure the windowed registers' values are in stack + SDValue Chain = getFLUSH(Op, DAG); + FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT); + + for (uint64_t i = 0; i != depth; ++i) { + SDValue Ptr = DAG.getNode(ISD::ADD, + dl, MVT::i32, + FrameAddr, DAG.getIntPtrConstant(56)); + FrameAddr = DAG.getLoad(MVT::i32, dl, + Chain, + Ptr, + MachinePointerInfo(), false, false, 0); + } + } + return FrameAddr; +} + +static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MFI->setReturnAddressIsTaken(true); + + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned RetReg = SP::I7; + + uint64_t depth = Op.getConstantOperandVal(0); + + SDValue RetAddr; + if (depth == 0) + RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT); + else { + // flush first to make sure the windowed registers' values are in stack + SDValue Chain = getFLUSH(Op, DAG); + RetAddr = DAG.getCopyFromReg(Chain, dl, SP::I6, VT); + + for (uint64_t i = 0; i != depth; ++i) { + SDValue Ptr = DAG.getNode(ISD::ADD, + dl, MVT::i32, + RetAddr, + DAG.getIntPtrConstant((i == depth-1)?60:56)); + RetAddr = DAG.getLoad(MVT::i32, dl, + Chain, + Ptr, + MachinePointerInfo(), false, false, 0); + } + } + return RetAddr; +} + SDValue SparcTargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { default: llvm_unreachable("Should not custom lower this!"); - // Frame & Return address. Currently unimplemented - case ISD::RETURNADDR: return SDValue(); - case ISD::FRAMEADDR: return SDValue(); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); + case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); case ISD::GlobalTLSAddress: llvm_unreachable("TLS not implemented for Sparc."); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); diff --git a/lib/Target/Sparc/SparcISelLowering.h b/lib/Target/Sparc/SparcISelLowering.h index db39e083a8..8b2be7a6b4 100644 --- a/lib/Target/Sparc/SparcISelLowering.h +++ b/lib/Target/Sparc/SparcISelLowering.h @@ -36,7 +36,8 @@ namespace llvm { CALL, // A call instruction. RET_FLAG, // Return with a flag operand. - GLOBAL_BASE_REG // Global base reg for PIC + GLOBAL_BASE_REG, // Global base reg for PIC + FLUSH // FLUSH registers to stack }; } diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index 44b7e43360..7da86a1f5b 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -127,6 +127,9 @@ def call : SDNode<"SPISD::CALL", SDT_SPCall, def retflag : SDNode<"SPISD::RET_FLAG", SDTNone, [SDNPHasChain, SDNPOptInGlue]>; +def flush : SDNode<"SPISD::FLUSH", SDTNone, + [SDNPHasChain]>; + def getPCX : Operand<i32> { let PrintMethod = "printGetPCX"; } @@ -218,6 +221,12 @@ def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), [(callseq_end timm:$amt1, timm:$amt2)]>; } +let hasSideEffects = 1, mayStore = 1 in + let rs2 = 0 in + def FLUSH : F3_1<0b10, 0b101011, (outs), (ins), + "flushw", + [(flush)]>; + // FpMOVD/FpNEGD/FpABSD - These are lowered to single-precision ops by the // fpmover pass. let Predicates = [HasNoV9] in { // Only emit these in V8 mode. |