diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/MSP430/MSP430CallingConv.td | 8 | ||||
-rw-r--r-- | llvm/lib/Target/MSP430/MSP430ISelLowering.cpp | 85 | ||||
-rw-r--r-- | llvm/lib/Target/MSP430/MSP430ISelLowering.h | 6 | ||||
-rw-r--r-- | llvm/lib/Target/MSP430/MSP430MachineFunctionInfo.h | 10 |
4 files changed, 85 insertions, 24 deletions
diff --git a/llvm/lib/Target/MSP430/MSP430CallingConv.td b/llvm/lib/Target/MSP430/MSP430CallingConv.td index b38f5781c84..0434f8abfbf 100644 --- a/llvm/lib/Target/MSP430/MSP430CallingConv.td +++ b/llvm/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/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp index 4305f60b15e..40b1dd3cc2e 100644 --- a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/llvm/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/llvm/lib/Target/MSP430/MSP430ISelLowering.h b/llvm/lib/Target/MSP430/MSP430ISelLowering.h index 8864807e999..3a729623c99 100644 --- a/llvm/lib/Target/MSP430/MSP430ISelLowering.h +++ b/llvm/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/llvm/lib/Target/MSP430/MSP430MachineFunctionInfo.h b/llvm/lib/Target/MSP430/MSP430MachineFunctionInfo.h index 2d937318c7e..fcaa8a1d6c7 100644 --- a/llvm/lib/Target/MSP430/MSP430MachineFunctionInfo.h +++ b/llvm/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; } |