mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-24 20:30:06 +00:00
Use the methods and classes that were added to simplify LowerCall and
LowerFormalArguments in MipsTargetLowering. No functionality change intended. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166846 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f084847373
commit
fe30a9be40
@ -35,9 +35,6 @@ def RetCC_MipsO32 : CallingConv<[
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def CC_MipsN : CallingConv<[
|
||||
// Handles byval parameters.
|
||||
CCIfByVal<CCCustom<"CC_Mips64Byval">>,
|
||||
|
||||
// Promote i8/i16 arguments to i32.
|
||||
CCIfType<[i8, i16], CCPromoteToType<i32>>,
|
||||
|
||||
@ -72,9 +69,6 @@ def CC_MipsN : CallingConv<[
|
||||
// N32/64 variable arguments.
|
||||
// All arguments are passed in integer registers.
|
||||
def CC_MipsN_VarArg : CallingConv<[
|
||||
// Handles byval parameters.
|
||||
CCIfByVal<CCCustom<"CC_Mips64Byval">>,
|
||||
|
||||
// Promote i8/i16 arguments to i32.
|
||||
CCIfType<[i8, i16], CCPromoteToType<i32>>,
|
||||
|
||||
@ -211,12 +205,6 @@ def CC_Mips_FastCC : CallingConv<[
|
||||
// Mips Calling Convention Dispatch
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def CC_Mips : CallingConv<[
|
||||
CCIfSubtarget<"isABI_EABI()", CCDelegateTo<CC_MipsEABI>>,
|
||||
CCIfSubtarget<"isABI_N32()", CCDelegateTo<CC_MipsN>>,
|
||||
CCIfSubtarget<"isABI_N64()", CCDelegateTo<CC_MipsN>>
|
||||
]>;
|
||||
|
||||
def RetCC_Mips : CallingConv<[
|
||||
CCIfSubtarget<"isABI_EABI()", CCDelegateTo<RetCC_MipsEABI>>,
|
||||
CCIfSubtarget<"isABI_N32()", CCDelegateTo<RetCC_MipsN>>,
|
||||
|
@ -46,6 +46,20 @@ static cl::opt<bool>
|
||||
EnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden,
|
||||
cl::desc("MIPS: Enable tail calls."), cl::init(false));
|
||||
|
||||
static const uint16_t O32IntRegs[4] = {
|
||||
Mips::A0, Mips::A1, Mips::A2, Mips::A3
|
||||
};
|
||||
|
||||
static const uint16_t Mips64IntRegs[8] = {
|
||||
Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64,
|
||||
Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64
|
||||
};
|
||||
|
||||
static const uint16_t Mips64DPRegs[8] = {
|
||||
Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64,
|
||||
Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64
|
||||
};
|
||||
|
||||
// If I is a shifted mask, set the size (Size) and the first bit of the
|
||||
// mask (Pos), and return true.
|
||||
// For example, if I is 0x003ff800, (Pos, Size) = (11, 11).
|
||||
@ -2541,16 +2555,9 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT,
|
||||
Mips::D6, Mips::D7
|
||||
};
|
||||
|
||||
// ByVal Args
|
||||
if (ArgFlags.isByVal()) {
|
||||
State.HandleByVal(ValNo, ValVT, LocVT, LocInfo,
|
||||
1 /*MinSize*/, 4 /*MinAlign*/, ArgFlags);
|
||||
unsigned NextReg = (State.getNextStackOffset() + 3) / 4;
|
||||
for (unsigned r = State.getFirstUnallocated(IntRegs, IntRegsSize);
|
||||
r < std::min(IntRegsSize, NextReg); ++r)
|
||||
State.AllocateReg(IntRegs[r]);
|
||||
return false;
|
||||
}
|
||||
// Do not process byval args here.
|
||||
if (ArgFlags.isByVal())
|
||||
return true;
|
||||
|
||||
// Promote i8 and i16
|
||||
if (LocVT == MVT::i8 || LocVT == MVT::i16) {
|
||||
@ -2605,280 +2612,30 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT,
|
||||
} else
|
||||
llvm_unreachable("Cannot handle this ValVT.");
|
||||
|
||||
unsigned SizeInBytes = ValVT.getSizeInBits() >> 3;
|
||||
unsigned Offset;
|
||||
if (!ArgFlags.isSRet())
|
||||
Offset = State.AllocateStack(SizeInBytes, OrigAlign);
|
||||
else
|
||||
Offset = State.AllocateStack(SizeInBytes, SizeInBytes);
|
||||
|
||||
if (!Reg)
|
||||
if (!Reg) {
|
||||
unsigned Offset = State.AllocateStack(ValVT.getSizeInBits() >> 3,
|
||||
OrigAlign);
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
||||
else
|
||||
} else
|
||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
||||
|
||||
return false; // CC must always match
|
||||
}
|
||||
|
||||
static const uint16_t Mips64IntRegs[8] =
|
||||
{Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64,
|
||||
Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64};
|
||||
static const uint16_t Mips64DPRegs[8] =
|
||||
{Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64,
|
||||
Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64};
|
||||
|
||||
static bool CC_Mips64Byval(unsigned ValNo, MVT ValVT, MVT LocVT,
|
||||
CCValAssign::LocInfo LocInfo,
|
||||
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
||||
unsigned Align = std::max(ArgFlags.getByValAlign(), (unsigned)8);
|
||||
unsigned Size = (ArgFlags.getByValSize() + 7) / 8 * 8;
|
||||
unsigned FirstIdx = State.getFirstUnallocated(Mips64IntRegs, 8);
|
||||
|
||||
assert(Align <= 16 && "Cannot handle alignments larger than 16.");
|
||||
|
||||
// If byval is 16-byte aligned, the first arg register must be even.
|
||||
if ((Align == 16) && (FirstIdx % 2)) {
|
||||
State.AllocateReg(Mips64IntRegs[FirstIdx], Mips64DPRegs[FirstIdx]);
|
||||
++FirstIdx;
|
||||
}
|
||||
|
||||
// Mark the registers allocated.
|
||||
for (unsigned I = FirstIdx; Size && (I < 8); Size -= 8, ++I)
|
||||
State.AllocateReg(Mips64IntRegs[I], Mips64DPRegs[I]);
|
||||
|
||||
// Allocate space on caller's stack.
|
||||
unsigned Offset = State.AllocateStack(Size, Align);
|
||||
|
||||
if (FirstIdx < 8)
|
||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Mips64IntRegs[FirstIdx],
|
||||
LocVT, LocInfo));
|
||||
else
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "MipsGenCallingConv.inc"
|
||||
|
||||
static void
|
||||
AnalyzeMips64CallOperands(CCState &CCInfo,
|
||||
const SmallVectorImpl<ISD::OutputArg> &Outs) {
|
||||
unsigned NumOps = Outs.size();
|
||||
for (unsigned i = 0; i != NumOps; ++i) {
|
||||
MVT ArgVT = Outs[i].VT;
|
||||
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
|
||||
bool R;
|
||||
|
||||
if (Outs[i].IsFixed)
|
||||
R = CC_MipsN(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo);
|
||||
else
|
||||
R = CC_MipsN_VarArg(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo);
|
||||
|
||||
if (R) {
|
||||
#ifndef NDEBUG
|
||||
dbgs() << "Call operand #" << i << " has unhandled type "
|
||||
<< EVT(ArgVT).getEVTString();
|
||||
#endif
|
||||
llvm_unreachable(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Call Calling Convention Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static const unsigned O32IntRegsSize = 4;
|
||||
|
||||
static const uint16_t O32IntRegs[] = {
|
||||
Mips::A0, Mips::A1, Mips::A2, Mips::A3
|
||||
};
|
||||
|
||||
// Return next O32 integer argument register.
|
||||
static unsigned getNextIntArgReg(unsigned Reg) {
|
||||
assert((Reg == Mips::A0) || (Reg == Mips::A2));
|
||||
return (Reg == Mips::A0) ? Mips::A1 : Mips::A3;
|
||||
}
|
||||
|
||||
// Write ByVal Arg to arg registers and stack.
|
||||
static void
|
||||
WriteByValArg(SDValue Chain, DebugLoc dl,
|
||||
SmallVector<std::pair<unsigned, SDValue>, 16> &RegsToPass,
|
||||
SmallVector<SDValue, 8> &MemOpChains, SDValue StackPtr,
|
||||
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
|
||||
const CCValAssign &VA, const ISD::ArgFlagsTy &Flags,
|
||||
MVT PtrType, bool isLittle) {
|
||||
unsigned LocMemOffset = VA.getLocMemOffset();
|
||||
unsigned Offset = 0;
|
||||
uint32_t RemainingSize = Flags.getByValSize();
|
||||
unsigned ByValAlign = Flags.getByValAlign();
|
||||
|
||||
// Copy the first 4 words of byval arg to registers A0 - A3.
|
||||
// FIXME: Use a stricter alignment if it enables better optimization in passes
|
||||
// run later.
|
||||
for (; RemainingSize >= 4 && LocMemOffset < 4 * 4;
|
||||
Offset += 4, RemainingSize -= 4, LocMemOffset += 4) {
|
||||
SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
|
||||
DAG.getConstant(Offset, MVT::i32));
|
||||
SDValue LoadVal = DAG.getLoad(MVT::i32, dl, Chain, LoadPtr,
|
||||
MachinePointerInfo(), false, false, false,
|
||||
std::min(ByValAlign, (unsigned )4));
|
||||
MemOpChains.push_back(LoadVal.getValue(1));
|
||||
unsigned DstReg = O32IntRegs[LocMemOffset / 4];
|
||||
RegsToPass.push_back(std::make_pair(DstReg, LoadVal));
|
||||
}
|
||||
|
||||
if (RemainingSize == 0)
|
||||
return;
|
||||
|
||||
// If there still is a register available for argument passing, write the
|
||||
// remaining part of the structure to it using subword loads and shifts.
|
||||
if (LocMemOffset < 4 * 4) {
|
||||
assert(RemainingSize <= 3 && RemainingSize >= 1 &&
|
||||
"There must be one to three bytes remaining.");
|
||||
unsigned LoadSize = (RemainingSize == 3 ? 2 : RemainingSize);
|
||||
SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
|
||||
DAG.getConstant(Offset, MVT::i32));
|
||||
unsigned Alignment = std::min(ByValAlign, (unsigned )4);
|
||||
SDValue LoadVal = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, Chain,
|
||||
LoadPtr, MachinePointerInfo(),
|
||||
MVT::getIntegerVT(LoadSize * 8), false,
|
||||
false, Alignment);
|
||||
MemOpChains.push_back(LoadVal.getValue(1));
|
||||
|
||||
// If target is big endian, shift it to the most significant half-word or
|
||||
// byte.
|
||||
if (!isLittle)
|
||||
LoadVal = DAG.getNode(ISD::SHL, dl, MVT::i32, LoadVal,
|
||||
DAG.getConstant(32 - LoadSize * 8, MVT::i32));
|
||||
|
||||
Offset += LoadSize;
|
||||
RemainingSize -= LoadSize;
|
||||
|
||||
// Read second subword if necessary.
|
||||
if (RemainingSize != 0) {
|
||||
assert(RemainingSize == 1 && "There must be one byte remaining.");
|
||||
LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
|
||||
DAG.getConstant(Offset, MVT::i32));
|
||||
unsigned Alignment = std::min(ByValAlign, (unsigned )2);
|
||||
SDValue Subword = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, Chain,
|
||||
LoadPtr, MachinePointerInfo(),
|
||||
MVT::i8, false, false, Alignment);
|
||||
MemOpChains.push_back(Subword.getValue(1));
|
||||
// Insert the loaded byte to LoadVal.
|
||||
// FIXME: Use INS if supported by target.
|
||||
unsigned ShiftAmt = isLittle ? 16 : 8;
|
||||
SDValue Shift = DAG.getNode(ISD::SHL, dl, MVT::i32, Subword,
|
||||
DAG.getConstant(ShiftAmt, MVT::i32));
|
||||
LoadVal = DAG.getNode(ISD::OR, dl, MVT::i32, LoadVal, Shift);
|
||||
}
|
||||
|
||||
unsigned DstReg = O32IntRegs[LocMemOffset / 4];
|
||||
RegsToPass.push_back(std::make_pair(DstReg, LoadVal));
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy remaining part of byval arg using memcpy.
|
||||
SDValue Src = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
|
||||
DAG.getConstant(Offset, MVT::i32));
|
||||
SDValue Dst = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr,
|
||||
DAG.getIntPtrConstant(LocMemOffset));
|
||||
Chain = DAG.getMemcpy(Chain, dl, Dst, Src,
|
||||
DAG.getConstant(RemainingSize, MVT::i32),
|
||||
std::min(ByValAlign, (unsigned)4),
|
||||
/*isVolatile=*/false, /*AlwaysInline=*/false,
|
||||
MachinePointerInfo(0), MachinePointerInfo(0));
|
||||
MemOpChains.push_back(Chain);
|
||||
}
|
||||
|
||||
// Copy Mips64 byVal arg to registers and stack.
|
||||
void static
|
||||
PassByValArg64(SDValue Chain, DebugLoc dl,
|
||||
SmallVector<std::pair<unsigned, SDValue>, 16> &RegsToPass,
|
||||
SmallVector<SDValue, 8> &MemOpChains, SDValue StackPtr,
|
||||
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
|
||||
const CCValAssign &VA, const ISD::ArgFlagsTy &Flags,
|
||||
EVT PtrTy, bool isLittle) {
|
||||
unsigned ByValSize = Flags.getByValSize();
|
||||
unsigned Alignment = std::min(Flags.getByValAlign(), (unsigned)8);
|
||||
bool IsRegLoc = VA.isRegLoc();
|
||||
unsigned Offset = 0; // Offset in # of bytes from the beginning of struct.
|
||||
unsigned LocMemOffset = 0;
|
||||
unsigned MemCpySize = ByValSize;
|
||||
|
||||
if (!IsRegLoc)
|
||||
LocMemOffset = VA.getLocMemOffset();
|
||||
else {
|
||||
const uint16_t *Reg = std::find(Mips64IntRegs, Mips64IntRegs + 8,
|
||||
VA.getLocReg());
|
||||
const uint16_t *RegEnd = Mips64IntRegs + 8;
|
||||
|
||||
// Copy double words to registers.
|
||||
for (; (Reg != RegEnd) && (ByValSize >= Offset + 8); ++Reg, Offset += 8) {
|
||||
SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, PtrTy, Arg,
|
||||
DAG.getConstant(Offset, PtrTy));
|
||||
SDValue LoadVal = DAG.getLoad(MVT::i64, dl, Chain, LoadPtr,
|
||||
MachinePointerInfo(), false, false, false,
|
||||
Alignment);
|
||||
MemOpChains.push_back(LoadVal.getValue(1));
|
||||
RegsToPass.push_back(std::make_pair(*Reg, LoadVal));
|
||||
}
|
||||
|
||||
// Return if the struct has been fully copied.
|
||||
if (!(MemCpySize = ByValSize - Offset))
|
||||
return;
|
||||
|
||||
// If there is an argument register available, copy the remainder of the
|
||||
// byval argument with sub-doubleword loads and shifts.
|
||||
if (Reg != RegEnd) {
|
||||
assert((ByValSize < Offset + 8) &&
|
||||
"Size of the remainder should be smaller than 8-byte.");
|
||||
SDValue Val;
|
||||
for (unsigned LoadSize = 4; Offset < ByValSize; LoadSize /= 2) {
|
||||
unsigned RemSize = ByValSize - Offset;
|
||||
|
||||
if (RemSize < LoadSize)
|
||||
continue;
|
||||
|
||||
SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, PtrTy, Arg,
|
||||
DAG.getConstant(Offset, PtrTy));
|
||||
SDValue LoadVal =
|
||||
DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i64, Chain, LoadPtr,
|
||||
MachinePointerInfo(), MVT::getIntegerVT(LoadSize * 8),
|
||||
false, false, Alignment);
|
||||
MemOpChains.push_back(LoadVal.getValue(1));
|
||||
|
||||
// Offset in number of bits from double word boundary.
|
||||
unsigned OffsetDW = (Offset % 8) * 8;
|
||||
unsigned Shamt = isLittle ? OffsetDW : 64 - (OffsetDW + LoadSize * 8);
|
||||
SDValue Shift = DAG.getNode(ISD::SHL, dl, MVT::i64, LoadVal,
|
||||
DAG.getConstant(Shamt, MVT::i32));
|
||||
|
||||
Val = Val.getNode() ? DAG.getNode(ISD::OR, dl, MVT::i64, Val, Shift) :
|
||||
Shift;
|
||||
Offset += LoadSize;
|
||||
Alignment = std::min(Alignment, LoadSize);
|
||||
}
|
||||
|
||||
RegsToPass.push_back(std::make_pair(*Reg, Val));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assert(MemCpySize && "MemCpySize must not be zero.");
|
||||
|
||||
// Copy remainder of byval arg to it with memcpy.
|
||||
SDValue Src = DAG.getNode(ISD::ADD, dl, PtrTy, Arg,
|
||||
DAG.getConstant(Offset, PtrTy));
|
||||
SDValue Dst = DAG.getNode(ISD::ADD, dl, MVT::i64, StackPtr,
|
||||
DAG.getIntPtrConstant(LocMemOffset));
|
||||
Chain = DAG.getMemcpy(Chain, dl, Dst, Src,
|
||||
DAG.getConstant(MemCpySize, PtrTy), Alignment,
|
||||
/*isVolatile=*/false, /*AlwaysInline=*/false,
|
||||
MachinePointerInfo(0), MachinePointerInfo(0));
|
||||
MemOpChains.push_back(Chain);
|
||||
}
|
||||
|
||||
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
|
||||
/// for tail call optimization.
|
||||
bool MipsTargetLowering::
|
||||
@ -2922,27 +2679,15 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
|
||||
getTargetMachine(), ArgLocs, *DAG.getContext());
|
||||
MipsCC MipsCCInfo(CallConv, isVarArg, IsO32, CCInfo);
|
||||
|
||||
if (CallConv == CallingConv::Fast)
|
||||
CCInfo.AnalyzeCallOperands(Outs, CC_Mips_FastCC);
|
||||
else if (IsO32)
|
||||
CCInfo.AnalyzeCallOperands(Outs, CC_MipsO32);
|
||||
else if (HasMips64)
|
||||
AnalyzeMips64CallOperands(CCInfo, Outs);
|
||||
else
|
||||
CCInfo.AnalyzeCallOperands(Outs, CC_Mips);
|
||||
MipsCCInfo.analyzeCallOperands(Outs);
|
||||
|
||||
// Get a count of how many bytes are to be pushed on the stack.
|
||||
unsigned NextStackOffset = CCInfo.getNextStackOffset();
|
||||
unsigned StackAlignment = TFL->getStackAlignment();
|
||||
NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment);
|
||||
|
||||
// Update size of the maximum argument space.
|
||||
// For O32, a minimum of four words (16 bytes) of argument space is
|
||||
// allocated.
|
||||
if (IsO32 && (CallConv != CallingConv::Fast))
|
||||
NextStackOffset = std::max(NextStackOffset, (unsigned)16);
|
||||
|
||||
// Check if it's really possible to do a tail call.
|
||||
if (isTailCall)
|
||||
isTailCall = IsEligibleForTailCallOptimization(CallConv, NextStackOffset);
|
||||
@ -2965,6 +2710,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
// With EABI is it possible to have 16 args on registers.
|
||||
SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass;
|
||||
SmallVector<SDValue, 8> MemOpChains;
|
||||
MipsCC::byval_iterator ByValArg = MipsCCInfo.byval_begin();
|
||||
|
||||
// Walk the register/memloc assignments, inserting copies/loads.
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
||||
@ -2977,14 +2723,10 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
if (Flags.isByVal()) {
|
||||
assert(Flags.getByValSize() &&
|
||||
"ByVal args of size 0 should have been ignored by front-end.");
|
||||
if (IsO32)
|
||||
WriteByValArg(Chain, dl, RegsToPass, MemOpChains, StackPtr,
|
||||
MFI, DAG, Arg, VA, Flags, getPointerTy(),
|
||||
Subtarget->isLittle());
|
||||
else
|
||||
PassByValArg64(Chain, dl, RegsToPass, MemOpChains, StackPtr,
|
||||
MFI, DAG, Arg, VA, Flags, getPointerTy(),
|
||||
Subtarget->isLittle());
|
||||
assert(ByValArg != MipsCCInfo.byval_end());
|
||||
passByValArg(Chain, dl, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg,
|
||||
MipsCCInfo, *ByValArg, Flags, Subtarget->isLittle());
|
||||
++ByValArg;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3212,70 +2954,6 @@ MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Formal Arguments Calling Convention Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
static void ReadByValArg(MachineFunction &MF, SDValue Chain, DebugLoc dl,
|
||||
std::vector<SDValue> &OutChains,
|
||||
SelectionDAG &DAG, unsigned NumWords, SDValue FIN,
|
||||
const CCValAssign &VA, const ISD::ArgFlagsTy &Flags,
|
||||
const Argument *FuncArg) {
|
||||
unsigned LocMem = VA.getLocMemOffset();
|
||||
unsigned FirstWord = LocMem / 4;
|
||||
|
||||
// copy register A0 - A3 to frame object
|
||||
for (unsigned i = 0; i < NumWords; ++i) {
|
||||
unsigned CurWord = FirstWord + i;
|
||||
if (CurWord >= O32IntRegsSize)
|
||||
break;
|
||||
|
||||
unsigned SrcReg = O32IntRegs[CurWord];
|
||||
unsigned Reg = AddLiveIn(MF, SrcReg, &Mips::CPURegsRegClass);
|
||||
SDValue StorePtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,
|
||||
DAG.getConstant(i * 4, MVT::i32));
|
||||
SDValue Store = DAG.getStore(Chain, dl, DAG.getRegister(Reg, MVT::i32),
|
||||
StorePtr, MachinePointerInfo(FuncArg, i * 4),
|
||||
false, false, 0);
|
||||
OutChains.push_back(Store);
|
||||
}
|
||||
}
|
||||
|
||||
// Create frame object on stack and copy registers used for byval passing to it.
|
||||
static unsigned
|
||||
CopyMips64ByValRegs(MachineFunction &MF, SDValue Chain, DebugLoc dl,
|
||||
std::vector<SDValue> &OutChains, SelectionDAG &DAG,
|
||||
const CCValAssign &VA, const ISD::ArgFlagsTy &Flags,
|
||||
MachineFrameInfo *MFI, bool IsRegLoc,
|
||||
SmallVectorImpl<SDValue> &InVals, MipsFunctionInfo *MipsFI,
|
||||
EVT PtrTy, const Argument *FuncArg) {
|
||||
const uint16_t *Reg = Mips64IntRegs + 8;
|
||||
int FOOffset; // Frame object offset from virtual frame pointer.
|
||||
|
||||
if (IsRegLoc) {
|
||||
Reg = std::find(Mips64IntRegs, Mips64IntRegs + 8, VA.getLocReg());
|
||||
FOOffset = (Reg - Mips64IntRegs) * 8 - 8 * 8;
|
||||
}
|
||||
else
|
||||
FOOffset = VA.getLocMemOffset();
|
||||
|
||||
// Create frame object.
|
||||
unsigned NumRegs = (Flags.getByValSize() + 7) / 8;
|
||||
unsigned LastFI = MFI->CreateFixedObject(NumRegs * 8, FOOffset, true);
|
||||
SDValue FIN = DAG.getFrameIndex(LastFI, PtrTy);
|
||||
InVals.push_back(FIN);
|
||||
|
||||
// Copy arg registers.
|
||||
for (unsigned I = 0; (Reg != Mips64IntRegs + 8) && (I < NumRegs);
|
||||
++Reg, ++I) {
|
||||
unsigned VReg = AddLiveIn(MF, *Reg, &Mips::CPU64RegsRegClass);
|
||||
SDValue StorePtr = DAG.getNode(ISD::ADD, dl, PtrTy, FIN,
|
||||
DAG.getConstant(I * 8, PtrTy));
|
||||
SDValue Store = DAG.getStore(Chain, dl, DAG.getRegister(VReg, MVT::i64),
|
||||
StorePtr, MachinePointerInfo(FuncArg, I * 8),
|
||||
false, false, 0);
|
||||
OutChains.push_back(Store);
|
||||
}
|
||||
|
||||
return LastFI;
|
||||
}
|
||||
|
||||
/// LowerFormalArguments - transform physical registers into virtual registers
|
||||
/// and generate load operations for arguments places on the stack.
|
||||
SDValue
|
||||
@ -3299,17 +2977,13 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
|
||||
getTargetMachine(), ArgLocs, *DAG.getContext());
|
||||
MipsCC MipsCCInfo(CallConv, isVarArg, IsO32, CCInfo);
|
||||
|
||||
if (CallConv == CallingConv::Fast)
|
||||
CCInfo.AnalyzeFormalArguments(Ins, CC_Mips_FastCC);
|
||||
else if (IsO32)
|
||||
CCInfo.AnalyzeFormalArguments(Ins, CC_MipsO32);
|
||||
else
|
||||
CCInfo.AnalyzeFormalArguments(Ins, CC_Mips);
|
||||
MipsCCInfo.analyzeFormalArguments(Ins);
|
||||
|
||||
Function::const_arg_iterator FuncArg =
|
||||
DAG.getMachineFunction().getFunction()->arg_begin();
|
||||
int LastFI = 0;// MipsFI->LastInArgFI is 0 at the entry of this function.
|
||||
MipsCC::byval_iterator ByValArg = MipsCCInfo.byval_begin();
|
||||
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++FuncArg) {
|
||||
CCValAssign &VA = ArgLocs[i];
|
||||
@ -3320,18 +2994,10 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
if (Flags.isByVal()) {
|
||||
assert(Flags.getByValSize() &&
|
||||
"ByVal args of size 0 should have been ignored by front-end.");
|
||||
if (IsO32) {
|
||||
unsigned NumWords = (Flags.getByValSize() + 3) / 4;
|
||||
LastFI = MFI->CreateFixedObject(NumWords * 4, VA.getLocMemOffset(),
|
||||
true);
|
||||
SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy());
|
||||
InVals.push_back(FIN);
|
||||
ReadByValArg(MF, Chain, dl, OutChains, DAG, NumWords, FIN, VA, Flags,
|
||||
&*FuncArg);
|
||||
} else // N32/64
|
||||
LastFI = CopyMips64ByValRegs(MF, Chain, dl, OutChains, DAG, VA, Flags,
|
||||
MFI, IsRegLoc, InVals, MipsFI,
|
||||
getPointerTy(), &*FuncArg);
|
||||
assert(ByValArg != MipsCCInfo.byval_end());
|
||||
copyByValRegs(Chain, dl, OutChains, DAG, Flags, InVals, &*FuncArg,
|
||||
MipsCCInfo, *ByValArg);
|
||||
++ByValArg;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3393,13 +3059,13 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
assert(VA.isMemLoc());
|
||||
|
||||
// The stack pointer offset is relative to the caller stack frame.
|
||||
LastFI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8,
|
||||
int FI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8,
|
||||
VA.getLocMemOffset(), true);
|
||||
|
||||
// Create load nodes to retrieve arguments from the stack
|
||||
SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy());
|
||||
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
|
||||
InVals.push_back(DAG.getLoad(ValVT, dl, Chain, FIN,
|
||||
MachinePointerInfo::getFixedStack(LastFI),
|
||||
MachinePointerInfo::getFixedStack(FI),
|
||||
false, false, false, 0));
|
||||
}
|
||||
}
|
||||
@ -3418,46 +3084,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
|
||||
}
|
||||
|
||||
if (isVarArg) {
|
||||
unsigned NumOfRegs = IsO32 ? 4 : 8;
|
||||
const uint16_t *ArgRegs = IsO32 ? O32IntRegs : Mips64IntRegs;
|
||||
unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs, NumOfRegs);
|
||||
int FirstRegSlotOffset = IsO32 ? 0 : -64 ; // offset of $a0's slot.
|
||||
const TargetRegisterClass *RC = IsO32 ?
|
||||
(const TargetRegisterClass*)&Mips::CPURegsRegClass :
|
||||
(const TargetRegisterClass*)&Mips::CPU64RegsRegClass;
|
||||
unsigned RegSize = RC->getSize();
|
||||
int RegSlotOffset = FirstRegSlotOffset + Idx * RegSize;
|
||||
|
||||
// Offset of the first variable argument from stack pointer.
|
||||
int FirstVaArgOffset;
|
||||
|
||||
if (IsO32 || (Idx == NumOfRegs)) {
|
||||
FirstVaArgOffset =
|
||||
(CCInfo.getNextStackOffset() + RegSize - 1) / RegSize * RegSize;
|
||||
} else
|
||||
FirstVaArgOffset = RegSlotOffset;
|
||||
|
||||
// Record the frame index of the first variable argument
|
||||
// which is a value necessary to VASTART.
|
||||
LastFI = MFI->CreateFixedObject(RegSize, FirstVaArgOffset, true);
|
||||
MipsFI->setVarArgsFrameIndex(LastFI);
|
||||
|
||||
// Copy the integer registers that have not been used for argument passing
|
||||
// to the argument register save area. For O32, the save area is allocated
|
||||
// in the caller's stack frame, while for N32/64, it is allocated in the
|
||||
// callee's stack frame.
|
||||
for (int StackOffset = RegSlotOffset;
|
||||
Idx < NumOfRegs; ++Idx, StackOffset += RegSize) {
|
||||
unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegs[Idx], RC);
|
||||
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg,
|
||||
MVT::getIntegerVT(RegSize * 8));
|
||||
LastFI = MFI->CreateFixedObject(RegSize, StackOffset, true);
|
||||
SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy());
|
||||
OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff,
|
||||
MachinePointerInfo(), false, false, 0));
|
||||
}
|
||||
}
|
||||
if (isVarArg)
|
||||
writeVarArgRegs(OutChains, MipsCCInfo, Chain, dl, DAG);
|
||||
|
||||
// All stores are grouped in one node to allow the matching between
|
||||
// the size of Ins and InVals. This only happens when on varg functions
|
||||
|
Loading…
Reference in New Issue
Block a user