Index: llvm/lib/Target/Xtensa/XtensaISelLowering.h =================================================================== --- llvm/lib/Target/Xtensa/XtensaISelLowering.h +++ llvm/lib/Target/Xtensa/XtensaISelLowering.h @@ -79,6 +79,10 @@ SDValue LowerJumpTable(JumpTableSDNode *JT, SelectionDAG &DAG) const; SDValue LowerConstantPool(ConstantPoolSDNode *CP, 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 getAddrPCRel(SDValue Op, SelectionDAG &DAG) const; CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const; Index: llvm/lib/Target/Xtensa/XtensaISelLowering.cpp =================================================================== --- llvm/lib/Target/Xtensa/XtensaISelLowering.cpp +++ llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -75,6 +75,12 @@ setOperationAction(ISD::BlockAddress, PtrVT, Custom); setOperationAction(ISD::JumpTable, PtrVT, Custom); + // Implement custom stack allocations + setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom); + // Implement custom stack save and restore + setOperationAction(ISD::STACKSAVE, MVT::Other, Custom); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Custom); + // Compute derived properties from the register classes computeRegisterProperties(STI.getRegisterInfo()); } @@ -664,6 +670,43 @@ return getAddrPCRel(Result, DAG); } +SDValue XtensaTargetLowering::LowerSTACKSAVE(SDValue Op, + SelectionDAG &DAG) const { + unsigned sp = Xtensa::SP; + return DAG.getCopyFromReg(Op.getOperand(0), SDLoc(Op), sp, Op.getValueType()); +} + +SDValue XtensaTargetLowering::LowerSTACKRESTORE(SDValue Op, + SelectionDAG &DAG) const { + unsigned sp = Xtensa::SP; + return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), sp, Op.getOperand(1)); +} + +SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, + SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); // Legalize the chain. + SDValue Size = Op.getOperand(1); // Legalize the size. + EVT VT = Size->getValueType(0); + SDLoc DL(Op); + + // Round up Size to 32 + SDValue Size1 = + DAG.getNode(ISD::ADD, DL, VT, Size, DAG.getConstant(31, DL, MVT::i32)); + SDValue SizeRoundUp = + DAG.getNode(ISD::AND, DL, VT, Size1, DAG.getConstant(~31, DL, MVT::i32)); + + unsigned SPReg = Xtensa::SP; + SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT); + SDValue NewSP = DAG.getNode(ISD::SUB, DL, VT, SP, SizeRoundUp); // Value + Chain = DAG.getCopyToReg(SP.getValue(1), DL, SPReg, NewSP); // Output chain + + SDValue NewVal = DAG.getCopyFromReg(Chain, DL, SPReg, MVT::i32); + Chain = NewVal.getValue(1); + + SDValue Ops[2] = {NewVal, Chain}; + return DAG.getMergeValues(Ops, DL); +} + SDValue XtensaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { @@ -679,6 +722,12 @@ return LowerJumpTable(cast(Op), DAG); case ISD::ConstantPool: return LowerConstantPool(cast(Op), DAG); + case ISD::STACKSAVE: + return LowerSTACKSAVE(Op, DAG); + case ISD::STACKRESTORE: + return LowerSTACKRESTORE(Op, DAG); + case ISD::DYNAMIC_STACKALLOC: + return LowerDYNAMIC_STACKALLOC(Op, DAG); default: llvm_unreachable("Unexpected node to lower"); }