diff options
author | Vadzim Dambrouski <pftbest@gmail.com> | 2017-03-02 20:25:10 +0000 |
---|---|---|
committer | Vadzim Dambrouski <pftbest@gmail.com> | 2017-03-02 20:25:10 +0000 |
commit | c5a81e86186e31fefbd1feb1b9eacb3ce4a63fb4 (patch) | |
tree | b0fe20084f1d1df3c39427513c59860dc2cf042f /lib/Target/MSP430 | |
parent | 8c81a9ed040e9b9eac971db955c0acc52687f9c8 (diff) |
[MSP430] Add SRet support to MSP430 target
This patch adds support for struct return values to the MSP430
target backend. It also reverses the order of argument and return
registers in the calling convention to bring it into closer
alignment with the published EABI from TI.
Patch by Andrew Wygle (awygle).
Differential Revision: https://reviews.llvm.org/D29069
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296807 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/MSP430')
-rw-r--r-- | lib/Target/MSP430/MSP430CallingConv.td | 8 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430ISelLowering.cpp | 85 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430ISelLowering.h | 6 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430MachineFunctionInfo.h | 10 |
4 files changed, 85 insertions, 24 deletions
diff --git a/lib/Target/MSP430/MSP430CallingConv.td b/lib/Target/MSP430/MSP430CallingConv.td index b38f5781c84..0434f8abfbf 100644 --- a/lib/Target/MSP430/MSP430CallingConv.td +++ b/lib/Target/MSP430/MSP430CallingConv.td @@ -13,11 +13,11 @@ // MSP430 Return Value Calling Convention //===----------------------------------------------------------------------===// def RetCC_MSP430 : CallingConv<[ - // i8 are returned in registers R15B, R14B, R13B, R12B - CCIfType<[i8], CCAssignToReg<[R15B, R14B, R13B, R12B]>>, + // i8 are returned in registers R12B, R13B, R14B, R15B + CCIfType<[i8], CCAssignToReg<[R12B, R13B, R14B, R15B]>>, - // i16 are returned in registers R15, R14, R13, R12 - CCIfType<[i16], CCAssignToReg<[R15, R14, R13, R12]>> + // i16 are returned in registers R12, R13, R14, R15 + CCIfType<[i16], CCAssignToReg<[R12, R13, R14, R15]>> ]>; //===----------------------------------------------------------------------===// diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index 4305f60b15e..40b1dd3cc2e 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -245,13 +245,20 @@ MSP430TargetLowering::getRegForInlineAsmConstraint( template<typename ArgT> static void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args, SmallVectorImpl<unsigned> &Out) { - unsigned CurrentArgIndex = ~0U; - for (unsigned i = 0, e = Args.size(); i != e; i++) { - if (CurrentArgIndex == Args[i].OrigArgIndex) { - Out.back()++; + unsigned CurrentArgIndex; + + if (Args.empty()) + return; + + CurrentArgIndex = Args[0].OrigArgIndex; + Out.push_back(0); + + for (auto &Arg : Args) { + if (CurrentArgIndex == Arg.OrigArgIndex) { + Out.back() += 1; } else { Out.push_back(1); - CurrentArgIndex++; + CurrentArgIndex = Arg.OrigArgIndex; } } } @@ -275,7 +282,7 @@ static void AnalyzeArguments(CCState &State, SmallVectorImpl<CCValAssign> &ArgLocs, const SmallVectorImpl<ArgT> &Args) { static const MCPhysReg RegList[] = { - MSP430::R15, MSP430::R14, MSP430::R13, MSP430::R12 + MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15 }; static const unsigned NbRegs = array_lengthof(RegList); @@ -288,7 +295,7 @@ static void AnalyzeArguments(CCState &State, ParseFunctionArgs(Args, ArgsParts); unsigned RegsLeft = NbRegs; - bool UseStack = false; + bool UsedStack = false; unsigned ValNo = 0; for (unsigned i = 0, e = ArgsParts.size(); i != e; i++) { @@ -316,20 +323,22 @@ static void AnalyzeArguments(CCState &State, unsigned Parts = ArgsParts[i]; - if (!UseStack && Parts <= RegsLeft) { - unsigned FirstVal = ValNo; + if (!UsedStack && Parts == 2 && RegsLeft == 1) { + // Special case for 32-bit register split, see EABI section 3.3.3 + unsigned Reg = State.AllocateReg(RegList); + State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo)); + RegsLeft -= 1; + + UsedStack = true; + CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, State); + } else if (Parts <= RegsLeft) { for (unsigned j = 0; j < Parts; j++) { unsigned Reg = State.AllocateReg(RegList); State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo)); RegsLeft--; } - - // Reverse the order of the pieces to agree with the "big endian" format - // required in the calling convention ABI. - SmallVectorImpl<CCValAssign>::iterator B = ArgLocs.begin() + FirstVal; - std::reverse(B, B + Parts); } else { - UseStack = true; + UsedStack = true; for (unsigned j = 0; j < Parts; j++) CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, State); } @@ -351,10 +360,6 @@ static void AnalyzeReturnValues(CCState &State, SmallVectorImpl<CCValAssign> &RVLocs, const SmallVectorImpl<ArgT> &Args) { AnalyzeRetResult(State, Args); - - // Reverse splitted return values to get the "big endian" format required - // to agree with the calling convention ABI. - std::reverse(RVLocs.begin(), RVLocs.end()); } SDValue MSP430TargetLowering::LowerFormalArguments( @@ -496,9 +501,33 @@ SDValue MSP430TargetLowering::LowerCCCArguments( } } + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + if (Ins[i].Flags.isSRet()) { + unsigned Reg = FuncInfo->getSRetReturnReg(); + if (!Reg) { + Reg = MF.getRegInfo().createVirtualRegister( + getRegClassFor(MVT::i16)); + FuncInfo->setSRetReturnReg(Reg); + } + SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[i]); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); + } + } + return Chain; } +bool +MSP430TargetLowering::CanLowerReturn(CallingConv::ID CallConv, + MachineFunction &MF, + bool IsVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + LLVMContext &Context) const { + SmallVector<CCValAssign, 16> RVLocs; + CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); + return CCInfo.CheckReturn(Outs, RetCC_MSP430); +} + SDValue MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, @@ -506,6 +535,8 @@ MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl, SelectionDAG &DAG) const { + MachineFunction &MF = DAG.getMachineFunction(); + // CCValAssign - represent the assignment of the return value to a location SmallVector<CCValAssign, 16> RVLocs; @@ -537,6 +568,22 @@ MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } + if (MF.getFunction()->hasStructRetAttr()) { + MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>(); + unsigned Reg = FuncInfo->getSRetReturnReg(); + + if (!Reg) + llvm_unreachable("sret virtual register not created in entry block"); + + SDValue Val = + DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy(DAG.getDataLayout())); + unsigned R12 = MSP430::R12; + + Chain = DAG.getCopyToReg(Chain, dl, R12, Val, Flag); + Flag = Chain.getValue(1); + RetOps.push_back(DAG.getRegister(R12, getPointerTy(DAG.getDataLayout()))); + } + unsigned Opc = (CallConv == CallingConv::MSP430_INTR ? MSP430ISD::RETI_FLAG : MSP430ISD::RET_FLAG); diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h index 8864807e999..3a729623c99 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.h +++ b/lib/Target/MSP430/MSP430ISelLowering.h @@ -158,6 +158,12 @@ namespace llvm { LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const override; + bool CanLowerReturn(CallingConv::ID CallConv, + MachineFunction &MF, + bool IsVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + LLVMContext &Context) const override; + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, diff --git a/lib/Target/MSP430/MSP430MachineFunctionInfo.h b/lib/Target/MSP430/MSP430MachineFunctionInfo.h index 2d937318c7e..fcaa8a1d6c7 100644 --- a/lib/Target/MSP430/MSP430MachineFunctionInfo.h +++ b/lib/Target/MSP430/MSP430MachineFunctionInfo.h @@ -33,15 +33,23 @@ class MSP430MachineFunctionInfo : public MachineFunctionInfo { /// VarArgsFrameIndex - FrameIndex for start of varargs area. int VarArgsFrameIndex; + /// SRetReturnReg - Some subtargets require that sret lowering includes + /// returning the value of the returned struct in a register. This field + /// holds the virtual register into which the sret argument is passed. + unsigned SRetReturnReg; + public: MSP430MachineFunctionInfo() : CalleeSavedFrameSize(0) {} explicit MSP430MachineFunctionInfo(MachineFunction &MF) - : CalleeSavedFrameSize(0), ReturnAddrIndex(0) {} + : CalleeSavedFrameSize(0), ReturnAddrIndex(0), SRetReturnReg(0) {} unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; } void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; } + unsigned getSRetReturnReg() const { return SRetReturnReg; } + void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } + int getRAIndex() const { return ReturnAddrIndex; } void setRAIndex(int Index) { ReturnAddrIndex = Index; } |