mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-23 02:29:18 +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();
|
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 "Mips.h"
|
||||||
#include "MipsSubtarget.h"
|
#include "MipsSubtarget.h"
|
||||||
|
#include "llvm/CodeGen/CallingConvLower.h"
|
||||||
#include "llvm/CodeGen/SelectionDAG.h"
|
#include "llvm/CodeGen/SelectionDAG.h"
|
||||||
#include "llvm/Target/TargetLowering.h"
|
#include "llvm/Target/TargetLowering.h"
|
||||||
|
|
||||||
@ -171,6 +172,69 @@ namespace llvm {
|
|||||||
|
|
||||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
private:
|
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
|
// Subtarget Info
|
||||||
const MipsSubtarget *Subtarget;
|
const MipsSubtarget *Subtarget;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user