From 2d89fea217c1c71f9f16ae7073d9b07dbb5c3838 Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Wed, 12 Jan 2011 05:08:36 +0000 Subject: [PATCH] Implement RETURNADDR and FRAMEADDR lowering in SPARC backend. llvm-svn: 123310 --- lib/Target/Sparc/SparcISelLowering.cpp | 77 +++++++++++++++++++++- lib/Target/Sparc/SparcISelLowering.h | 3 +- lib/Target/Sparc/SparcInstrInfo.td | 9 +++ test/CodeGen/SPARC/2011-01-11-FrameAddr.ll | 46 +++++++++++++ 4 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 test/CodeGen/SPARC/2011-01-11-FrameAddr.ll diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index ec8c7b48097..b7edd8ada46 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 db39e083a83..8b2be7a6b4f 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 44b7e433601..7da86a1f5be 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 { 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. diff --git a/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll b/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll new file mode 100644 index 00000000000..6c821f3ce96 --- /dev/null +++ b/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll @@ -0,0 +1,46 @@ +;RUN: llc -march=sparc < %s | FileCheck %s + + +define i8* @frameaddr() nounwind readnone { +entry: +;CHECK: frameaddr +;CHECK: or %g0, %fp, {{.+}} + %0 = tail call i8* @llvm.frameaddress(i32 0) + ret i8* %0 +} + +define i8* @frameaddr2() nounwind readnone { +entry: +;CHECK: frameaddr2 +;CHECK: flushw +;CHECK: ld [%fp+56], {{.+}} +;CHECK: ld [{{.+}}+56], {{.+}} +;CHECK: ld [{{.+}}+56], {{.+}} + %0 = tail call i8* @llvm.frameaddress(i32 3) + ret i8* %0 +} + +declare i8* @llvm.frameaddress(i32) nounwind readnone + + + +define i8* @retaddr() nounwind readnone { +entry: +;CHECK: retaddr +;CHECK: or %g0, %i7, {{.+}} + %0 = tail call i8* @llvm.returnaddress(i32 0) + ret i8* %0 +} + +define i8* @retaddr2() nounwind readnone { +entry: +;CHECK: retaddr2 +;CHECK: flushw +;CHECK: ld [%fp+56], {{.+}} +;CHECK: ld [{{.+}}+56], {{.+}} +;CHECK: ld [{{.+}}+60], {{.+}} + %0 = tail call i8* @llvm.returnaddress(i32 3) + ret i8* %0 +} + +declare i8* @llvm.returnaddress(i32) nounwind readnone