Skip to content

Commit 074ea02

Browse files
alexcrichtonTimNN
authored andcommitted
Merge pull request rust-lang#64 from pftbest/sret
[MSP430] Add SRet support to MSP430 target
2 parents 670dac9 + b73e10e commit 074ea02

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
@@ -245,13 +245,20 @@ MSP430TargetLowering::getRegForInlineAsmConstraint(
245245
template<typename ArgT>
246246
static void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args,
247247
SmallVectorImpl<unsigned> &Out) {
248-
unsigned CurrentArgIndex = ~0U;
249-
for (unsigned i = 0, e = Args.size(); i != e; i++) {
250-
if (CurrentArgIndex == Args[i].OrigArgIndex) {
251-
Out.back()++;
248+
unsigned CurrentArgIndex;
249+
250+
if (Args.empty())
251+
return;
252+
253+
CurrentArgIndex = Args[0].OrigArgIndex;
254+
Out.push_back(0);
255+
256+
for (auto &Arg : Args) {
257+
if (CurrentArgIndex == Arg.OrigArgIndex) {
258+
Out.back() += 1;
252259
} else {
253260
Out.push_back(1);
254-
CurrentArgIndex++;
261+
CurrentArgIndex = Arg.OrigArgIndex;
255262
}
256263
}
257264
}
@@ -275,7 +282,7 @@ static void AnalyzeArguments(CCState &State,
275282
SmallVectorImpl<CCValAssign> &ArgLocs,
276283
const SmallVectorImpl<ArgT> &Args) {
277284
static const MCPhysReg RegList[] = {
278-
MSP430::R15, MSP430::R14, MSP430::R13, MSP430::R12
285+
MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15
279286
};
280287
static const unsigned NbRegs = array_lengthof(RegList);
281288

@@ -288,7 +295,7 @@ static void AnalyzeArguments(CCState &State,
288295
ParseFunctionArgs(Args, ArgsParts);
289296

290297
unsigned RegsLeft = NbRegs;
291-
bool UseStack = false;
298+
bool UsedStack = false;
292299
unsigned ValNo = 0;
293300

294301
for (unsigned i = 0, e = ArgsParts.size(); i != e; i++) {
@@ -316,20 +323,22 @@ static void AnalyzeArguments(CCState &State,
316323

317324
unsigned Parts = ArgsParts[i];
318325

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

360365
SDValue MSP430TargetLowering::LowerFormalArguments(
@@ -496,16 +501,42 @@ SDValue MSP430TargetLowering::LowerCCCArguments(
496501
}
497502
}
498503

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

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

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

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

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

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)