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

Commit 859fb26

Browse files
authored
Merge pull request #64 from pftbest/sret
[MSP430] Add SRet support to MSP430 target
2 parents 50ab09f + 9c467a8 commit 859fb26

26 files changed

+277
-172
lines changed

lib/Target/MSP430/MSP430CallingConv.td

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
// MSP430 Return Value Calling Convention
1414
//===----------------------------------------------------------------------===//
1515
def RetCC_MSP430 : CallingConv<[
16-
// i8 are returned in registers R15B, R14B, R13B, R12B
17-
CCIfType<[i8], CCAssignToReg<[R15B, R14B, R13B, R12B]>>,
16+
// i8 are returned in registers R12B, R13B, R14B, R15B
17+
CCIfType<[i8], CCAssignToReg<[R12B, R13B, R14B, R15B]>>,
1818

19-
// i16 are returned in registers R15, R14, R13, R12
20-
CCIfType<[i16], CCAssignToReg<[R15, R14, R13, R12]>>
19+
// i16 are returned in registers R12, R13, R14, R15
20+
CCIfType<[i16], CCAssignToReg<[R12, R13, R14, R15]>>
2121
]>;
2222

2323
//===----------------------------------------------------------------------===//

lib/Target/MSP430/MSP430ISelLowering.cpp

+66-19
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,20 @@ MSP430TargetLowering::getRegForInlineAsmConstraint(
246246
template<typename ArgT>
247247
static void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args,
248248
SmallVectorImpl<unsigned> &Out) {
249-
unsigned CurrentArgIndex = ~0U;
250-
for (unsigned i = 0, e = Args.size(); i != e; i++) {
251-
if (CurrentArgIndex == Args[i].OrigArgIndex) {
252-
Out.back()++;
249+
unsigned CurrentArgIndex;
250+
251+
if (Args.empty())
252+
return;
253+
254+
CurrentArgIndex = Args[0].OrigArgIndex;
255+
Out.push_back(0);
256+
257+
for (auto &Arg : Args) {
258+
if (CurrentArgIndex == Arg.OrigArgIndex) {
259+
Out.back() += 1;
253260
} else {
254261
Out.push_back(1);
255-
CurrentArgIndex++;
262+
CurrentArgIndex = Arg.OrigArgIndex;
256263
}
257264
}
258265
}
@@ -276,7 +283,7 @@ static void AnalyzeArguments(CCState &State,
276283
SmallVectorImpl<CCValAssign> &ArgLocs,
277284
const SmallVectorImpl<ArgT> &Args) {
278285
static const MCPhysReg RegList[] = {
279-
MSP430::R15, MSP430::R14, MSP430::R13, MSP430::R12
286+
MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15
280287
};
281288
static const unsigned NbRegs = array_lengthof(RegList);
282289

@@ -289,7 +296,7 @@ static void AnalyzeArguments(CCState &State,
289296
ParseFunctionArgs(Args, ArgsParts);
290297

291298
unsigned RegsLeft = NbRegs;
292-
bool UseStack = false;
299+
bool UsedStack = false;
293300
unsigned ValNo = 0;
294301

295302
for (unsigned i = 0, e = ArgsParts.size(); i != e; i++) {
@@ -317,20 +324,22 @@ static void AnalyzeArguments(CCState &State,
317324

318325
unsigned Parts = ArgsParts[i];
319326

320-
if (!UseStack && Parts <= RegsLeft) {
321-
unsigned FirstVal = ValNo;
327+
if (!UsedStack && Parts == 2 && RegsLeft == 1) {
328+
// Special case for 32-bit register split, see EABI section 3.3.3
329+
unsigned Reg = State.AllocateReg(RegList);
330+
State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo));
331+
RegsLeft -= 1;
332+
333+
UsedStack = true;
334+
CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, State);
335+
} else if (Parts <= RegsLeft) {
322336
for (unsigned j = 0; j < Parts; j++) {
323337
unsigned Reg = State.AllocateReg(RegList);
324338
State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo));
325339
RegsLeft--;
326340
}
327-
328-
// Reverse the order of the pieces to agree with the "big endian" format
329-
// required in the calling convention ABI.
330-
SmallVectorImpl<CCValAssign>::iterator B = ArgLocs.begin() + FirstVal;
331-
std::reverse(B, B + Parts);
332341
} else {
333-
UseStack = true;
342+
UsedStack = true;
334343
for (unsigned j = 0; j < Parts; j++)
335344
CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, State);
336345
}
@@ -352,10 +361,6 @@ static void AnalyzeReturnValues(CCState &State,
352361
SmallVectorImpl<CCValAssign> &RVLocs,
353362
const SmallVectorImpl<ArgT> &Args) {
354363
AnalyzeRetResult(State, Args);
355-
356-
// Reverse splitted return values to get the "big endian" format required
357-
// to agree with the calling convention ABI.
358-
std::reverse(RVLocs.begin(), RVLocs.end());
359364
}
360365

361366
SDValue MSP430TargetLowering::LowerFormalArguments(
@@ -497,16 +502,42 @@ SDValue MSP430TargetLowering::LowerCCCArguments(
497502
}
498503
}
499504

505+
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
506+
if (Ins[i].Flags.isSRet()) {
507+
unsigned Reg = FuncInfo->getSRetReturnReg();
508+
if (!Reg) {
509+
Reg = MF.getRegInfo().createVirtualRegister(
510+
getRegClassFor(MVT::i16));
511+
FuncInfo->setSRetReturnReg(Reg);
512+
}
513+
SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[i]);
514+
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
515+
}
516+
}
517+
500518
return Chain;
501519
}
502520

521+
bool
522+
MSP430TargetLowering::CanLowerReturn(CallingConv::ID CallConv,
523+
MachineFunction &MF,
524+
bool IsVarArg,
525+
const SmallVectorImpl<ISD::OutputArg> &Outs,
526+
LLVMContext &Context) const {
527+
SmallVector<CCValAssign, 16> RVLocs;
528+
CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
529+
return CCInfo.CheckReturn(Outs, RetCC_MSP430);
530+
}
531+
503532
SDValue
504533
MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
505534
bool isVarArg,
506535
const SmallVectorImpl<ISD::OutputArg> &Outs,
507536
const SmallVectorImpl<SDValue> &OutVals,
508537
const SDLoc &dl, SelectionDAG &DAG) const {
509538

539+
MachineFunction &MF = DAG.getMachineFunction();
540+
510541
// CCValAssign - represent the assignment of the return value to a location
511542
SmallVector<CCValAssign, 16> RVLocs;
512543

@@ -538,6 +569,22 @@ MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
538569
RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
539570
}
540571

572+
if (MF.getFunction()->hasStructRetAttr()) {
573+
MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();
574+
unsigned Reg = FuncInfo->getSRetReturnReg();
575+
576+
if (!Reg)
577+
llvm_unreachable("sret virtual register not created in entry block");
578+
579+
SDValue Val =
580+
DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy(DAG.getDataLayout()));
581+
unsigned R12 = MSP430::R12;
582+
583+
Chain = DAG.getCopyToReg(Chain, dl, R12, Val, Flag);
584+
Flag = Chain.getValue(1);
585+
RetOps.push_back(DAG.getRegister(R12, getPointerTy(DAG.getDataLayout())));
586+
}
587+
541588
unsigned Opc = (CallConv == CallingConv::MSP430_INTR ?
542589
MSP430ISD::RETI_FLAG : MSP430ISD::RET_FLAG);
543590

lib/Target/MSP430/MSP430ISelLowering.h

+6
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@ namespace llvm {
158158
LowerCall(TargetLowering::CallLoweringInfo &CLI,
159159
SmallVectorImpl<SDValue> &InVals) const override;
160160

161+
bool CanLowerReturn(CallingConv::ID CallConv,
162+
MachineFunction &MF,
163+
bool IsVarArg,
164+
const SmallVectorImpl<ISD::OutputArg> &Outs,
165+
LLVMContext &Context) const override;
166+
161167
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
162168
const SmallVectorImpl<ISD::OutputArg> &Outs,
163169
const SmallVectorImpl<SDValue> &OutVals,

lib/Target/MSP430/MSP430MachineFunctionInfo.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,23 @@ class MSP430MachineFunctionInfo : public MachineFunctionInfo {
3333
/// VarArgsFrameIndex - FrameIndex for start of varargs area.
3434
int VarArgsFrameIndex;
3535

36+
/// SRetReturnReg - Some subtargets require that sret lowering includes
37+
/// returning the value of the returned struct in a register. This field
38+
/// holds the virtual register into which the sret argument is passed.
39+
unsigned SRetReturnReg;
40+
3641
public:
3742
MSP430MachineFunctionInfo() : CalleeSavedFrameSize(0) {}
3843

3944
explicit MSP430MachineFunctionInfo(MachineFunction &MF)
40-
: CalleeSavedFrameSize(0), ReturnAddrIndex(0) {}
45+
: CalleeSavedFrameSize(0), ReturnAddrIndex(0), SRetReturnReg(0) {}
4146

4247
unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
4348
void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; }
4449

50+
unsigned getSRetReturnReg() const { return SRetReturnReg; }
51+
void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
52+
4553
int getRAIndex() const { return ReturnAddrIndex; }
4654
void setRAIndex(int Index) { ReturnAddrIndex = Index; }
4755

test/CodeGen/MSP430/AddrMode-bis-rx.ll

+7-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ define i16 @am1(i16 %x, i16* %a) nounwind {
88
ret i16 %2
99
}
1010
; CHECK-LABEL: am1:
11-
; CHECK: bis.w 0(r14), r15
11+
; CHECK: bis.w 0(r13), r12
1212

1313
@foo = external global i16
1414

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

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

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

3434
define i16 @am4(i16 %x) nounwind {
3535
%1 = load volatile i16, i16* inttoptr(i16 32 to i16*)
3636
%2 = or i16 %1,%x
3737
ret i16 %2
3838
}
3939
; CHECK-LABEL: am4:
40-
; CHECK: bis.w &32, r15
40+
; CHECK: bis.w &32, r12
4141

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

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

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

test/CodeGen/MSP430/AddrMode-bis-xr.ll

+7-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ define void @am1(i16* %a, i16 %x) nounwind {
99
ret void
1010
}
1111
; CHECK-LABEL: am1:
12-
; CHECK: bis.w r14, 0(r15)
12+
; CHECK: bis.w r13, 0(r12)
1313

1414
@foo = external global i16
1515

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

2525
@bar = external global [2 x i8]
2626

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

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

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

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

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

test/CodeGen/MSP430/AddrMode-mov-rx.ll

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ define i16 @am1(i16* %a) nounwind {
77
ret i16 %1
88
}
99
; CHECK-LABEL: am1:
10-
; CHECK: mov.w 0(r15), r15
10+
; CHECK: mov.w 0(r12), r12
1111

1212
@foo = external global i16
1313

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

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

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

3131
define i16 @am4() nounwind {
3232
%1 = load volatile i16, i16* inttoptr(i16 32 to i16*)
3333
ret i16 %1
3434
}
3535
; CHECK-LABEL: am4:
36-
; CHECK: mov.w &32, r15
36+
; CHECK: mov.w &32, r12
3737

3838
define i16 @am5(i16* %a) nounwind {
3939
%1 = getelementptr i16, i16* %a, i16 2
4040
%2 = load i16, i16* %1
4141
ret i16 %2
4242
}
4343
; CHECK-LABEL: am5:
44-
; CHECK: mov.w 4(r15), r15
44+
; CHECK: mov.w 4(r12), r12
4545

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

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

0 commit comments

Comments
 (0)