Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

[MSP430] Add SRet support to MSP430 target #64

Merged
merged 1 commit into from
Mar 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/Target/MSP430/MSP430CallingConv.td
Original file line number Diff line number Diff line change
Expand Up @@ -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]>>
]>;

//===----------------------------------------------------------------------===//
Expand Down
85 changes: 66 additions & 19 deletions lib/Target/MSP430/MSP430ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,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;
}
}
}
Expand All @@ -276,7 +283,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);

Expand All @@ -289,7 +296,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++) {
Expand Down Expand Up @@ -317,20 +324,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);
}
Expand All @@ -352,10 +361,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(
Expand Down Expand Up @@ -497,16 +502,42 @@ 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,
const SmallVectorImpl<ISD::OutputArg> &Outs,
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;

Expand Down Expand Up @@ -538,6 +569,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);

Expand Down
6 changes: 6 additions & 0 deletions lib/Target/MSP430/MSP430ISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 9 additions & 1 deletion lib/Target/MSP430/MSP430MachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down
14 changes: 7 additions & 7 deletions test/CodeGen/MSP430/AddrMode-bis-rx.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ define i16 @am1(i16 %x, i16* %a) nounwind {
ret i16 %2
}
; CHECK-LABEL: am1:
; CHECK: bis.w 0(r14), r15
; CHECK: bis.w 0(r13), r12

@foo = external global i16

Expand All @@ -18,7 +18,7 @@ define i16 @am2(i16 %x) nounwind {
ret i16 %2
}
; CHECK-LABEL: am2:
; CHECK: bis.w &foo, r15
; CHECK: bis.w &foo, r12

@bar = internal constant [2 x i8] [ i8 32, i8 64 ]

Expand All @@ -29,15 +29,15 @@ define i8 @am3(i8 %x, i16 %n) nounwind {
ret i8 %3
}
; CHECK-LABEL: am3:
; CHECK: bis.b bar(r14), r15
; CHECK: bis.b bar(r13), r12

define i16 @am4(i16 %x) nounwind {
%1 = load volatile i16, i16* inttoptr(i16 32 to i16*)
%2 = or i16 %1,%x
ret i16 %2
}
; CHECK-LABEL: am4:
; CHECK: bis.w &32, r15
; CHECK: bis.w &32, r12

define i16 @am5(i16 %x, i16* %a) nounwind {
%1 = getelementptr i16, i16* %a, i16 2
Expand All @@ -46,7 +46,7 @@ define i16 @am5(i16 %x, i16* %a) nounwind {
ret i16 %3
}
; CHECK-LABEL: am5:
; CHECK: bis.w 4(r14), r15
; CHECK: bis.w 4(r13), r12

%S = type { i16, i16 }
@baz = common global %S zeroinitializer, align 1
Expand All @@ -57,7 +57,7 @@ define i16 @am6(i16 %x) nounwind {
ret i16 %2
}
; CHECK-LABEL: am6:
; CHECK: bis.w &baz+2, r15
; CHECK: bis.w &baz+2, r12

%T = type { i16, [2 x i8] }
@duh = internal constant %T { i16 16, [2 x i8][i8 32, i8 64 ] }
Expand All @@ -70,5 +70,5 @@ define i8 @am7(i8 %x, i16 %n) nounwind {
ret i8 %4
}
; CHECK-LABEL: am7:
; CHECK: bis.b duh+2(r14), r15
; CHECK: bis.b duh+2(r13), r12

14 changes: 7 additions & 7 deletions test/CodeGen/MSP430/AddrMode-bis-xr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ define void @am1(i16* %a, i16 %x) nounwind {
ret void
}
; CHECK-LABEL: am1:
; CHECK: bis.w r14, 0(r15)
; CHECK: bis.w r13, 0(r12)

@foo = external global i16

Expand All @@ -20,7 +20,7 @@ define void @am2(i16 %x) nounwind {
ret void
}
; CHECK-LABEL: am2:
; CHECK: bis.w r15, &foo
; CHECK: bis.w r12, &foo

@bar = external global [2 x i8]

Expand All @@ -32,7 +32,7 @@ define void @am3(i16 %i, i8 %x) nounwind {
ret void
}
; CHECK-LABEL: am3:
; CHECK: bis.b r14, bar(r15)
; CHECK: bis.b r13, bar(r12)

define void @am4(i16 %x) nounwind {
%1 = load volatile i16, i16* inttoptr(i16 32 to i16*)
Expand All @@ -41,7 +41,7 @@ define void @am4(i16 %x) nounwind {
ret void
}
; CHECK-LABEL: am4:
; CHECK: bis.w r15, &32
; CHECK: bis.w r12, &32

define void @am5(i16* %a, i16 %x) readonly {
%1 = getelementptr inbounds i16, i16* %a, i16 2
Expand All @@ -51,7 +51,7 @@ define void @am5(i16* %a, i16 %x) readonly {
ret void
}
; CHECK-LABEL: am5:
; CHECK: bis.w r14, 4(r15)
; CHECK: bis.w r13, 4(r12)

%S = type { i16, i16 }
@baz = common global %S zeroinitializer
Expand All @@ -63,7 +63,7 @@ define void @am6(i16 %x) nounwind {
ret void
}
; CHECK-LABEL: am6:
; CHECK: bis.w r15, &baz+2
; CHECK: bis.w r12, &baz+2

%T = type { i16, [2 x i8] }
@duh = external global %T
Expand All @@ -77,5 +77,5 @@ define void @am7(i16 %n, i8 %x) nounwind {
ret void
}
; CHECK-LABEL: am7:
; CHECK: bis.b r14, duh+2(r15)
; CHECK: bis.b r13, duh+2(r12)

14 changes: 7 additions & 7 deletions test/CodeGen/MSP430/AddrMode-mov-rx.ll
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ define i16 @am1(i16* %a) nounwind {
ret i16 %1
}
; CHECK-LABEL: am1:
; CHECK: mov.w 0(r15), r15
; CHECK: mov.w 0(r12), r12

@foo = external global i16

Expand All @@ -16,7 +16,7 @@ define i16 @am2() nounwind {
ret i16 %1
}
; CHECK-LABEL: am2:
; CHECK: mov.w &foo, r15
; CHECK: mov.w &foo, r12

@bar = internal constant [2 x i8] [ i8 32, i8 64 ]

Expand All @@ -26,22 +26,22 @@ define i8 @am3(i16 %n) nounwind {
ret i8 %2
}
; CHECK-LABEL: am3:
; CHECK: mov.b bar(r15), r15
; CHECK: mov.b bar(r12), r12

define i16 @am4() nounwind {
%1 = load volatile i16, i16* inttoptr(i16 32 to i16*)
ret i16 %1
}
; CHECK-LABEL: am4:
; CHECK: mov.w &32, r15
; CHECK: mov.w &32, r12

define i16 @am5(i16* %a) nounwind {
%1 = getelementptr i16, i16* %a, i16 2
%2 = load i16, i16* %1
ret i16 %2
}
; CHECK-LABEL: am5:
; CHECK: mov.w 4(r15), r15
; CHECK: mov.w 4(r12), r12

%S = type { i16, i16 }
@baz = common global %S zeroinitializer, align 1
Expand All @@ -51,7 +51,7 @@ define i16 @am6() nounwind {
ret i16 %1
}
; CHECK-LABEL: am6:
; CHECK: mov.w &baz+2, r15
; CHECK: mov.w &baz+2, r12

%T = type { i16, [2 x i8] }
@duh = internal constant %T { i16 16, [2 x i8][i8 32, i8 64 ] }
Expand All @@ -63,5 +63,5 @@ define i8 @am7(i16 %n) nounwind {
ret i8 %3
}
; CHECK-LABEL: am7:
; CHECK: mov.b duh+2(r15), r15
; CHECK: mov.b duh+2(r12), r12

Loading