summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
diff options
context:
space:
mode:
authorVadzim Dambrouski <pftbest@gmail.com>2017-03-02 20:25:10 +0000
committerVadzim Dambrouski <pftbest@gmail.com>2017-03-02 20:25:10 +0000
commiteafb8055061000146c88989cbec7d4cd80294051 (patch)
treefe8ade37a6e2ed8772c8d3ca6a25353edaa9aa63 /llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
parent5ad740756f7a61e6ee58727df8e40e1ba1af5986 (diff)
downloadbcm5719-llvm-eafb8055061000146c88989cbec7d4cd80294051.tar.gz
bcm5719-llvm-eafb8055061000146c88989cbec7d4cd80294051.zip
[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 llvm-svn: 296807
Diffstat (limited to 'llvm/lib/Target/MSP430/MSP430ISelLowering.cpp')
-rw-r--r--llvm/lib/Target/MSP430/MSP430ISelLowering.cpp85
1 files changed, 66 insertions, 19 deletions
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);
OpenPOWER on IntegriCloud