#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/CallingConv.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Target/TargetCallingConv.h"
namespace llvm {
- class TargetRegisterInfo;
- class TargetMachine;
- class CCState;
+class CCState;
+class MVT;
+class TargetMachine;
+class TargetRegisterInfo;
/// CCValAssign - Represent assignment of one arg/retval to a location.
class CCValAssign {
public:
enum LocInfo {
- Full, // The value fills the full location.
- SExt, // The value is sign extended in the location.
- ZExt, // The value is zero extended in the location.
- AExt, // The value is extended with undefined upper bits.
- BCvt, // The value is bit-converted in the location.
- VExt, // The value is vector-widened in the location.
- // FIXME: Not implemented yet. Code that uses AExt to mean
- // vector-widen should be fixed to use VExt instead.
- Indirect // The location contains pointer to the value.
+ Full, // The value fills the full location.
+ SExt, // The value is sign extended in the location.
+ ZExt, // The value is zero extended in the location.
+ AExt, // The value is extended with undefined upper bits.
+ SExtUpper, // The value is in the upper bits of the location and should be
+ // sign extended when retrieved.
+ ZExtUpper, // The value is in the upper bits of the location and should be
+ // zero extended when retrieved.
+ AExtUpper, // The value is in the upper bits of the location and should be
+ // extended with undefined upper bits when retrieved.
+ BCvt, // The value is bit-converted in the location.
+ VExt, // The value is vector-widened in the location.
+ // FIXME: Not implemented yet. Code that uses AExt to mean
+ // vector-widen should be fixed to use VExt instead.
+ FPExt, // The floating-point value is fp-extended in the location.
+ Indirect // The location contains pointer to the value.
// TODO: a subset of the value is in the location.
};
+
private:
/// ValNo - This is the value number begin assigned (e.g. an argument number).
unsigned ValNo;
return Ret;
}
+ // There is no need to differentiate between a pending CCValAssign and other
+ // kinds, as they are stored in a different list.
+ static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT,
+ LocInfo HTP, unsigned ExtraInfo = 0) {
+ return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP);
+ }
+
+ void convertToReg(unsigned RegNo) {
+ Loc = RegNo;
+ isMem = false;
+ }
+
+ void convertToMem(unsigned Offset) {
+ Loc = Offset;
+ isMem = true;
+ }
+
unsigned getValNo() const { return ValNo; }
MVT getValVT() const { return ValVT; }
unsigned getLocReg() const { assert(isRegLoc()); return Loc; }
unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; }
+ unsigned getExtraInfo() const { return Loc; }
MVT getLocVT() const { return LocVT; }
LocInfo getLocInfo() const { return HTP; }
return (HTP == AExt || HTP == SExt || HTP == ZExt);
}
+ bool isUpperBitsInLoc() const {
+ return HTP == AExtUpper || HTP == SExtUpper || HTP == ZExtUpper;
+ }
+};
+
+/// Describes a register that needs to be forwarded from the prologue to a
+/// musttail call.
+struct ForwardedRegister {
+ ForwardedRegister(unsigned VReg, MCPhysReg PReg, MVT VT)
+ : VReg(VReg), PReg(PReg), VT(VT) {}
+ unsigned VReg;
+ MCPhysReg PReg;
+ MVT VT;
};
/// CCAssignFn - This function assigns a location for Val, updating State to
CallingConv::ID CallingConv;
bool IsVarArg;
MachineFunction &MF;
- const TargetMachine &TM;
const TargetRegisterInfo &TRI;
- SmallVector<CCValAssign, 16> &Locs;
+ SmallVectorImpl<CCValAssign> &Locs;
LLVMContext &Context;
unsigned StackOffset;
SmallVector<uint32_t, 16> UsedRegs;
+ SmallVector<CCValAssign, 4> PendingLocs;
// ByValInfo and SmallVector<ByValInfo, 4> ByValRegs:
//
// while "%t" goes to the stack: it wouldn't be described in ByValRegs.
//
// Supposed use-case for this collection:
- // 1. Initially ByValRegs is empty, InRegsParamsProceed is 0.
+ // 1. Initially ByValRegs is empty, InRegsParamsProcessed is 0.
// 2. HandleByVal fillups ByValRegs.
// 3. Argument analysis (LowerFormatArguments, for example). After
- // some byval argument was analyzed, InRegsParamsProceed is increased.
+ // some byval argument was analyzed, InRegsParamsProcessed is increased.
struct ByValInfo {
ByValInfo(unsigned B, unsigned E, bool IsWaste = false) :
Begin(B), End(E), Waste(IsWaste) {}
};
SmallVector<ByValInfo, 4 > ByValRegs;
- // InRegsParamsProceed - shows how many instances of ByValRegs was proceed
+ // InRegsParamsProcessed - shows how many instances of ByValRegs was proceed
// during argument analysis.
- unsigned InRegsParamsProceed;
+ unsigned InRegsParamsProcessed;
protected:
ParmContext CallOrPrologue;
public:
CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
- const TargetMachine &TM, SmallVector<CCValAssign, 16> &locs,
- LLVMContext &C);
+ SmallVectorImpl<CCValAssign> &locs, LLVMContext &C);
void addLoc(const CCValAssign &V) {
Locs.push_back(V);
}
LLVMContext &getContext() const { return Context; }
- const TargetMachine &getTarget() const { return TM; }
MachineFunction &getMachineFunction() const { return MF; }
CallingConv::ID getCallingConv() const { return CallingConv; }
bool isVarArg() const { return IsVarArg; }
/// produce a single value.
void AnalyzeCallResult(MVT VT, CCAssignFn Fn);
- /// getFirstUnallocated - Return the first unallocated register in the set, or
- /// NumRegs if they are all allocated.
- unsigned getFirstUnallocated(const uint16_t *Regs, unsigned NumRegs) const {
- for (unsigned i = 0; i != NumRegs; ++i)
+ /// getFirstUnallocated - Return the index of the first unallocated register
+ /// in the set, or Regs.size() if they are all allocated.
+ unsigned getFirstUnallocated(ArrayRef<MCPhysReg> Regs) const {
+ for (unsigned i = 0; i < Regs.size(); ++i)
if (!isAllocated(Regs[i]))
return i;
- return NumRegs;
+ return Regs.size();
}
/// AllocateReg - Attempt to allocate one register. If it is not available,
/// AllocateReg - Attempt to allocate one of the specified registers. If none
/// are available, return zero. Otherwise, return the first one available,
/// marking it and any aliases as allocated.
- unsigned AllocateReg(const uint16_t *Regs, unsigned NumRegs) {
- unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
- if (FirstUnalloc == NumRegs)
+ unsigned AllocateReg(ArrayRef<MCPhysReg> Regs) {
+ unsigned FirstUnalloc = getFirstUnallocated(Regs);
+ if (FirstUnalloc == Regs.size())
return 0; // Didn't find the reg.
// Mark the register and any aliases as allocated.
return Reg;
}
+ /// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive
+ /// registers. If this is not possible, return zero. Otherwise, return the first
+ /// register of the block that were allocated, marking the entire block as allocated.
+ unsigned AllocateRegBlock(ArrayRef<uint16_t> Regs, unsigned RegsRequired) {
+ if (RegsRequired > Regs.size())
+ return 0;
+
+ for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired;
+ ++StartIdx) {
+ bool BlockAvailable = true;
+ // Check for already-allocated regs in this block
+ for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) {
+ if (isAllocated(Regs[StartIdx + BlockIdx])) {
+ BlockAvailable = false;
+ break;
+ }
+ }
+ if (BlockAvailable) {
+ // Mark the entire block as allocated
+ for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) {
+ MarkAllocated(Regs[StartIdx + BlockIdx]);
+ }
+ return Regs[StartIdx];
+ }
+ }
+ // No block was available
+ return 0;
+ }
+
/// Version of AllocateReg with list of registers to be shadowed.
- unsigned AllocateReg(const uint16_t *Regs, const uint16_t *ShadowRegs,
- unsigned NumRegs) {
- unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
- if (FirstUnalloc == NumRegs)
+ unsigned AllocateReg(ArrayRef<MCPhysReg> Regs, const MCPhysReg *ShadowRegs) {
+ unsigned FirstUnalloc = getFirstUnallocated(Regs);
+ if (FirstUnalloc == Regs.size())
return 0; // Didn't find the reg.
// Mark the register and any aliases as allocated.
/// AllocateStack - Allocate a chunk of stack space with the specified size
/// and alignment.
unsigned AllocateStack(unsigned Size, unsigned Align) {
- assert(Align && ((Align-1) & Align) == 0); // Align is power of 2.
- StackOffset = ((StackOffset + Align-1) & ~(Align-1));
+ assert(Align && ((Align - 1) & Align) == 0); // Align is power of 2.
+ StackOffset = ((StackOffset + Align - 1) & ~(Align - 1));
unsigned Result = StackOffset;
StackOffset += Size;
MF.getFrameInfo()->ensureMaxAlignment(Align);
return AllocateStack(Size, Align);
}
+ /// Version of AllocateStack with list of extra registers to be shadowed.
+ /// Note that, unlike AllocateReg, this shadows ALL of the shadow registers.
+ unsigned AllocateStack(unsigned Size, unsigned Align,
+ ArrayRef<MCPhysReg> ShadowRegs) {
+ for (unsigned i = 0; i < ShadowRegs.size(); ++i)
+ MarkAllocated(ShadowRegs[i]);
+ return AllocateStack(Size, Align);
+ }
+
// HandleByVal - Allocate a stack slot large enough to pass an argument by
// value. The size and alignment information of the argument is encoded in its
// parameter attribute.
unsigned getInRegsParamsCount() const { return ByValRegs.size(); }
// Returns count of byval in-regs arguments proceed.
- unsigned getInRegsParamsProceed() const { return InRegsParamsProceed; }
+ unsigned getInRegsParamsProcessed() const { return InRegsParamsProcessed; }
// Get information about N-th byval parameter that is stored in registers.
// Here "ByValParamIndex" is N.
// Returns false, if end is reached.
bool nextInRegsParam() {
unsigned e = ByValRegs.size();
- if (InRegsParamsProceed < e)
- ++InRegsParamsProceed;
- return InRegsParamsProceed < e;
+ if (InRegsParamsProcessed < e)
+ ++InRegsParamsProcessed;
+ return InRegsParamsProcessed < e;
}
// Clear byval registers tracking info.
void clearByValRegsInfo() {
- InRegsParamsProceed = 0;
+ InRegsParamsProcessed = 0;
ByValRegs.clear();
}
+ // Rewind byval registers tracking info.
+ void rewindByValRegsInfo() {
+ InRegsParamsProcessed = 0;
+ }
+
ParmContext getCallOrPrologue() const { return CallOrPrologue; }
+ // Get list of pending assignments
+ SmallVectorImpl<llvm::CCValAssign> &getPendingLocs() {
+ return PendingLocs;
+ }
+
+ /// Compute the remaining unused register parameters that would be used for
+ /// the given value type. This is useful when varargs are passed in the
+ /// registers that normal prototyped parameters would be passed in, or for
+ /// implementing perfect forwarding.
+ void getRemainingRegParmsForType(SmallVectorImpl<MCPhysReg> &Regs, MVT VT,
+ CCAssignFn Fn);
+
+ /// Compute the set of registers that need to be preserved and forwarded to
+ /// any musttail calls.
+ void analyzeMustTailForwardedRegisters(
+ SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> RegParmTypes,
+ CCAssignFn Fn);
+
private:
/// MarkAllocated - Mark a register and all of its aliases as allocated.
void MarkAllocated(unsigned Reg);