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:
Akira Hatanaka 2012-10-26 23:56:38 +00:00
parent 3649255e14
commit 7887c90a7b
2 changed files with 192 additions and 0 deletions

View File

@ -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]);
}

View File

@ -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;