summaryrefslogtreecommitdiff
path: root/lib/Target/MSP430
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/MSP430')
-rw-r--r--lib/Target/MSP430/MSP430BranchSelector.cpp4
-rw-r--r--lib/Target/MSP430/MSP430CallingConv.td8
-rw-r--r--lib/Target/MSP430/MSP430ISelDAGToDAG.cpp4
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.cpp87
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.h6
-rw-r--r--lib/Target/MSP430/MSP430MCInstLower.cpp2
-rw-r--r--lib/Target/MSP430/MSP430MachineFunctionInfo.h10
7 files changed, 92 insertions, 29 deletions
diff --git a/lib/Target/MSP430/MSP430BranchSelector.cpp b/lib/Target/MSP430/MSP430BranchSelector.cpp
index 5fd6b6305f68..424b5ae418f7 100644
--- a/lib/Target/MSP430/MSP430BranchSelector.cpp
+++ b/lib/Target/MSP430/MSP430BranchSelector.cpp
@@ -194,8 +194,8 @@ bool MSP430BSel::expandBranches(OffsetVector &BlockOffsets) {
// Jump over the long branch on the opposite condition
TII->reverseBranchCondition(Cond);
MI = BuildMI(*MBB, MI, dl, TII->get(MSP430::JCC))
- .addMBB(NextMBB)
- .addOperand(Cond[0]);
+ .addMBB(NextMBB)
+ .add(Cond[0]);
InstrSizeDiff += TII->getInstSizeInBytes(*MI);
++MI;
}
diff --git a/lib/Target/MSP430/MSP430CallingConv.td b/lib/Target/MSP430/MSP430CallingConv.td
index b38f5781c84a..0434f8abfbf4 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/MSP430ISelDAGToDAG.cpp b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
index 6e481b68e038..cd58eda5d924 100644
--- a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
+++ b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
@@ -61,7 +61,8 @@ namespace {
return GV != nullptr || CP != nullptr || ES != nullptr || JT != -1;
}
- void dump() {
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() {
errs() << "MSP430ISelAddressMode " << this << '\n';
if (BaseType == RegBase && Base.Reg.getNode() != nullptr) {
errs() << "Base.Reg ";
@@ -83,6 +84,7 @@ namespace {
} else if (JT != -1)
errs() << " JT" << JT << " Align" << Align << '\n';
}
+#endif
};
}
diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp
index 73346b9ce41d..40b1dd3cc2eb 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);
@@ -1219,7 +1266,7 @@ MSP430TargetLowering::EmitShiftInstr(MachineInstr &MI,
BB->end());
RemBB->transferSuccessorsAndUpdatePHIs(BB);
- // Add adges BB => LoopBB => RemBB, BB => RemBB, LoopBB => LoopBB
+ // Add edges BB => LoopBB => RemBB, BB => RemBB, LoopBB => LoopBB
BB->addSuccessor(LoopBB);
BB->addSuccessor(RemBB);
LoopBB->addSuccessor(RemBB);
diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h
index 8864807e999e..3a729623c99a 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/MSP430MCInstLower.cpp b/lib/Target/MSP430/MSP430MCInstLower.cpp
index 47b0e270c5b3..e7716382b222 100644
--- a/lib/Target/MSP430/MSP430MCInstLower.cpp
+++ b/lib/Target/MSP430/MSP430MCInstLower.cpp
@@ -119,7 +119,7 @@ void MSP430MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
MCOperand MCOp;
switch (MO.getType()) {
default:
- MI->dump();
+ MI->print(errs());
llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register:
// Ignore all implicit register operands.
diff --git a/lib/Target/MSP430/MSP430MachineFunctionInfo.h b/lib/Target/MSP430/MSP430MachineFunctionInfo.h
index 2d937318c7e5..fcaa8a1d6c72 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; }