mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 04:39:44 +00:00
Add class MipsCC which provides methods used to analyze formal and call
arguments and inquire about calling convention information. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166840 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3649255e14
commit
7887c90a7b
@ -3808,3 +3808,131 @@ unsigned MipsTargetLowering::getJumpTableEncoding() const {
|
||||
|
||||
return TargetLowering::getJumpTableEncoding();
|
||||
}
|
||||
|
||||
MipsTargetLowering::MipsCC::MipsCC(CallingConv::ID CallConv, bool IsVarArg,
|
||||
bool IsO32, CCState &Info) : CCInfo(Info) {
|
||||
UseRegsForByval = true;
|
||||
|
||||
if (IsO32) {
|
||||
RegSize = 4;
|
||||
NumIntArgRegs = array_lengthof(O32IntRegs);
|
||||
ReservedArgArea = 16;
|
||||
IntArgRegs = ShadowRegs = O32IntRegs;
|
||||
FixedFn = VarFn = CC_MipsO32;
|
||||
} else {
|
||||
RegSize = 8;
|
||||
NumIntArgRegs = array_lengthof(Mips64IntRegs);
|
||||
ReservedArgArea = 0;
|
||||
IntArgRegs = Mips64IntRegs;
|
||||
ShadowRegs = Mips64DPRegs;
|
||||
FixedFn = CC_MipsN;
|
||||
VarFn = CC_MipsN_VarArg;
|
||||
}
|
||||
|
||||
if (CallConv == CallingConv::Fast) {
|
||||
assert(!IsVarArg);
|
||||
UseRegsForByval = false;
|
||||
ReservedArgArea = 0;
|
||||
FixedFn = VarFn = CC_Mips_FastCC;
|
||||
}
|
||||
|
||||
// Pre-allocate reserved argument area.
|
||||
CCInfo.AllocateStack(ReservedArgArea, 1);
|
||||
}
|
||||
|
||||
void MipsTargetLowering::MipsCC::
|
||||
analyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Args) {
|
||||
unsigned NumOpnds = Args.size();
|
||||
|
||||
for (unsigned I = 0; I != NumOpnds; ++I) {
|
||||
MVT ArgVT = Args[I].VT;
|
||||
ISD::ArgFlagsTy ArgFlags = Args[I].Flags;
|
||||
bool R;
|
||||
|
||||
if (ArgFlags.isByVal()) {
|
||||
handleByValArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Args[I].IsFixed)
|
||||
R = FixedFn(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo);
|
||||
else
|
||||
R = VarFn(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MipsTargetLowering::MipsCC::
|
||||
analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Args) {
|
||||
unsigned NumArgs = Args.size();
|
||||
|
||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
MVT ArgVT = Args[I].VT;
|
||||
ISD::ArgFlagsTy ArgFlags = Args[I].Flags;
|
||||
|
||||
if (ArgFlags.isByVal()) {
|
||||
handleByValArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!FixedFn(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo))
|
||||
continue;
|
||||
|
||||
#ifndef NDEBUG
|
||||
dbgs() << "Formal Arg #" << I << " has unhandled type "
|
||||
<< EVT(ArgVT).getEVTString();
|
||||
#endif
|
||||
llvm_unreachable(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MipsTargetLowering::MipsCC::handleByValArg(unsigned ValNo, MVT ValVT,
|
||||
MVT LocVT,
|
||||
CCValAssign::LocInfo LocInfo,
|
||||
ISD::ArgFlagsTy ArgFlags) {
|
||||
assert(ArgFlags.getByValSize() && "Byval argument's size shouldn't be 0.");
|
||||
|
||||
struct ByValArgInfo ByVal;
|
||||
unsigned ByValSize = RoundUpToAlignment(ArgFlags.getByValSize(), RegSize);
|
||||
unsigned Align = std::min(std::max(ArgFlags.getByValAlign(), RegSize),
|
||||
RegSize * 2);
|
||||
|
||||
if (UseRegsForByval)
|
||||
allocateRegs(ByVal, ByValSize, Align);
|
||||
|
||||
// Allocate space on caller's stack.
|
||||
ByVal.Address = CCInfo.AllocateStack(ByValSize - RegSize * ByVal.NumRegs,
|
||||
Align);
|
||||
CCInfo.addLoc(CCValAssign::getMem(ValNo, ValVT, ByVal.Address, LocVT,
|
||||
LocInfo));
|
||||
ByValArgs.push_back(ByVal);
|
||||
}
|
||||
|
||||
void MipsTargetLowering::MipsCC::allocateRegs(ByValArgInfo &ByVal,
|
||||
unsigned ByValSize,
|
||||
unsigned Align) {
|
||||
assert(!(ByValSize % RegSize) && !(Align % RegSize) &&
|
||||
"Byval argument's size and alignment should be a multiple of"
|
||||
"RegSize.");
|
||||
|
||||
ByVal.FirstIdx = CCInfo.getFirstUnallocated(IntArgRegs, NumIntArgRegs);
|
||||
|
||||
// If Align > RegSize, the first arg register must be even.
|
||||
if ((Align > RegSize) && (ByVal.FirstIdx % 2)) {
|
||||
CCInfo.AllocateReg(IntArgRegs[ByVal.FirstIdx], ShadowRegs[ByVal.FirstIdx]);
|
||||
++ByVal.FirstIdx;
|
||||
}
|
||||
|
||||
// Mark the registers allocated.
|
||||
for (unsigned I = ByVal.FirstIdx; ByValSize && (I < NumIntArgRegs);
|
||||
ByValSize -= RegSize, ++I, ++ByVal.NumRegs)
|
||||
CCInfo.AllocateReg(IntArgRegs[I], ShadowRegs[I]);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "Mips.h"
|
||||
#include "MipsSubtarget.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
|
||||
@ -171,6 +172,69 @@ namespace llvm {
|
||||
|
||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||
private:
|
||||
|
||||
/// ByValArgInfo - Byval argument information.
|
||||
struct ByValArgInfo {
|
||||
unsigned FirstIdx; // Index of the first register used.
|
||||
unsigned NumRegs; // Number of registers used for this argument.
|
||||
unsigned Address; // Offset of the stack area used to pass this argument.
|
||||
|
||||
ByValArgInfo() : FirstIdx(0), NumRegs(0), Address(0) {}
|
||||
};
|
||||
|
||||
/// MipsCC - This class provides methods used to analyze formal and call
|
||||
/// arguments and inquire about calling convention information.
|
||||
class MipsCC {
|
||||
public:
|
||||
MipsCC(CallingConv::ID CallConv, bool IsVarArg, bool IsO32,
|
||||
CCState &Info);
|
||||
|
||||
void analyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs);
|
||||
void analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins);
|
||||
void handleByValArg(unsigned ValNo, MVT ValVT, MVT LocVT,
|
||||
CCValAssign::LocInfo LocInfo,
|
||||
ISD::ArgFlagsTy ArgFlags);
|
||||
|
||||
const CCState &getCCInfo() const { return CCInfo; }
|
||||
|
||||
/// hasByValArg - Returns true if function has byval arguments.
|
||||
bool hasByValArg() const { return !ByValArgs.empty(); }
|
||||
|
||||
/// useRegsForByval - Returns true if the calling convention allows the
|
||||
/// use of registers to pass byval arguments.
|
||||
bool useRegsForByval() const { return UseRegsForByval; }
|
||||
|
||||
/// regSize - Size (in number of bits) of integer registers.
|
||||
unsigned regSize() const { return RegSize; }
|
||||
|
||||
/// numIntArgRegs - Number of integer registers available for calls.
|
||||
unsigned numIntArgRegs() const { return NumIntArgRegs; }
|
||||
|
||||
/// reservedArgArea - The size of the area the caller reserves for
|
||||
/// register arguments. This is 16-byte if ABI is O32.
|
||||
unsigned reservedArgArea() const { return ReservedArgArea; }
|
||||
|
||||
/// intArgRegs - Pointer to array of integer registers.
|
||||
const uint16_t *intArgRegs() const { return IntArgRegs; }
|
||||
|
||||
typedef SmallVector<ByValArgInfo, 2>::const_iterator byval_iterator;
|
||||
byval_iterator byval_begin() const { return ByValArgs.begin(); }
|
||||
byval_iterator byval_end() const { return ByValArgs.end(); }
|
||||
|
||||
private:
|
||||
void allocateRegs(ByValArgInfo &ByVal, unsigned ByValSize,
|
||||
unsigned Align);
|
||||
|
||||
CCState &CCInfo;
|
||||
bool UseRegsForByval;
|
||||
unsigned RegSize;
|
||||
unsigned NumIntArgRegs;
|
||||
unsigned ReservedArgArea;
|
||||
const uint16_t *IntArgRegs, *ShadowRegs;
|
||||
SmallVector<ByValArgInfo, 2> ByValArgs;
|
||||
llvm::CCAssignFn *FixedFn, *VarFn;
|
||||
};
|
||||
|
||||
// Subtarget Info
|
||||
const MipsSubtarget *Subtarget;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user