};
private:
+ // Holds one of:
+ // - the register that the value is assigned to;
+ // - the memory offset at which the value resides;
+ // - additional information about pending location; the exact interpretation
+ // of the data is target-dependent.
+ std::variant<Register, int64_t, unsigned> Data;
+
/// ValNo - This is the value number being assigned (e.g. an argument number).
unsigned ValNo;
- /// Loc is either a stack offset or a register number.
- unsigned Loc;
-
- /// isMem - True if this is a memory loc, false if it is a register loc.
- unsigned isMem : 1;
-
/// isCustom - True if this arg/retval requires special handling.
unsigned isCustom : 1;
/// LocVT - The type of the location being assigned to.
MVT LocVT;
-public:
- static CCValAssign getReg(unsigned ValNo, MVT ValVT,
- unsigned RegNo, MVT LocVT,
- LocInfo HTP) {
- CCValAssign Ret;
- Ret.ValNo = ValNo;
- Ret.Loc = RegNo;
- Ret.isMem = false;
- Ret.isCustom = false;
- Ret.HTP = HTP;
- Ret.ValVT = ValVT;
- Ret.LocVT = LocVT;
- return Ret;
+ CCValAssign(LocInfo HTP, unsigned ValNo, MVT ValVT, MVT LocVT, bool IsCustom)
+ : ValNo(ValNo), isCustom(IsCustom), HTP(HTP), ValVT(ValVT), LocVT(LocVT) {
}
- static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT,
- unsigned RegNo, MVT LocVT,
- LocInfo HTP) {
- CCValAssign Ret;
- Ret = getReg(ValNo, ValVT, RegNo, LocVT, HTP);
- Ret.isCustom = true;
+public:
+ static CCValAssign getReg(unsigned ValNo, MVT ValVT, unsigned RegNo,
+ MVT LocVT, LocInfo HTP, bool IsCustom = false) {
+ CCValAssign Ret(HTP, ValNo, ValVT, LocVT, IsCustom);
+ Ret.Data = Register(RegNo);
return Ret;
}
- static CCValAssign getMem(unsigned ValNo, MVT ValVT,
- unsigned Offset, MVT LocVT,
- LocInfo HTP) {
- CCValAssign Ret;
- Ret.ValNo = ValNo;
- Ret.Loc = Offset;
- Ret.isMem = true;
- Ret.isCustom = false;
- Ret.HTP = HTP;
- Ret.ValVT = ValVT;
- Ret.LocVT = LocVT;
- return Ret;
+ static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, unsigned RegNo,
+ MVT LocVT, LocInfo HTP) {
+ return getReg(ValNo, ValVT, RegNo, LocVT, HTP, /*IsCustom=*/true);
}
- static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT,
- unsigned Offset, MVT LocVT,
- LocInfo HTP) {
- CCValAssign Ret;
- Ret = getMem(ValNo, ValVT, Offset, LocVT, HTP);
- Ret.isCustom = true;
+ static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset,
+ MVT LocVT, LocInfo HTP, bool IsCustom = false) {
+ CCValAssign Ret(HTP, ValNo, ValVT, LocVT, IsCustom);
+ Ret.Data = int64_t(Offset);
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 getCustomMem(unsigned ValNo, MVT ValVT, unsigned Offset,
+ MVT LocVT, LocInfo HTP) {
+ return getMem(ValNo, ValVT, Offset, LocVT, HTP, /*IsCustom=*/true);
+ }
+
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT,
LocInfo HTP, unsigned ExtraInfo = 0) {
- return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP);
+ CCValAssign Ret(HTP, ValNo, ValVT, LocVT, false);
+ Ret.Data = ExtraInfo;
+ return Ret;
}
- void convertToReg(unsigned RegNo) {
- Loc = RegNo;
- isMem = false;
- }
+ void convertToReg(unsigned RegNo) { Data = Register(RegNo); }
- void convertToMem(unsigned Offset) {
- Loc = Offset;
- isMem = true;
- }
+ void convertToMem(unsigned Offset) { Data = int64_t(Offset); }
unsigned getValNo() const { return ValNo; }
MVT getValVT() const { return ValVT; }
- bool isRegLoc() const { return !isMem; }
- bool isMemLoc() const { return isMem; }
+ bool isRegLoc() const { return std::holds_alternative<Register>(Data); }
+ bool isMemLoc() const { return std::holds_alternative<int64_t>(Data); }
+ bool isPendingLoc() const { return std::holds_alternative<unsigned>(Data); }
bool needsCustom() const { return isCustom; }
- Register getLocReg() const { assert(isRegLoc()); return Loc; }
- unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; }
- unsigned getExtraInfo() const { return Loc; }
+ Register getLocReg() const { return std::get<Register>(Data); }
+ unsigned getLocMemOffset() const { return std::get<int64_t>(Data); }
+ unsigned getExtraInfo() const { return std::get<unsigned>(Data); }
+
MVT getLocVT() const { return LocVT; }
LocInfo getLocInfo() const { return HTP; }
// when i64 and f64 are both passed in GPRs.
StackOffset = SavedStackOffset;
MaxStackArgAlign = SavedMaxStackArgAlign;
- Locs.resize(NumLocs);
+ Locs.truncate(NumLocs);
}
void CCState::analyzeMustTailForwardedRegisters(
CCState CCInfo2(CallerCC, false, MF, RVLocs2, C);
CCInfo2.AnalyzeCallResult(Ins, CallerFn);
- if (RVLocs1.size() != RVLocs2.size())
- return false;
- for (unsigned I = 0, E = RVLocs1.size(); I != E; ++I) {
- const CCValAssign &Loc1 = RVLocs1[I];
- const CCValAssign &Loc2 = RVLocs2[I];
-
- if ( // Must both be in registers, or both in memory
- Loc1.isRegLoc() != Loc2.isRegLoc() ||
- // Must fill the same part of their locations
- Loc1.getLocInfo() != Loc2.getLocInfo() ||
- // Memory offset/register number must be the same
- Loc1.getExtraInfo() != Loc2.getExtraInfo())
+ auto AreCompatible = [](const CCValAssign &Loc1, const CCValAssign &Loc2) {
+ assert(!Loc1.isPendingLoc() && !Loc2.isPendingLoc() &&
+ "The location must have been decided by now");
+ // Must fill the same part of their locations.
+ if (Loc1.getLocInfo() != Loc2.getLocInfo())
return false;
- }
- return true;
+ // Must both be in the same registers, or both in memory at the same offset.
+ if (Loc1.isRegLoc() && Loc2.isRegLoc())
+ return Loc1.getLocReg() == Loc2.getLocReg();
+ if (Loc1.isMemLoc() && Loc2.isMemLoc())
+ return Loc1.getLocMemOffset() == Loc2.getLocMemOffset();
+ llvm_unreachable("Unknown location kind");
+ };
+
+ return std::equal(RVLocs1.begin(), RVLocs1.end(), RVLocs2.begin(),
+ RVLocs2.end(), AreCompatible);
}
static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs,
ArrayRef<ISD::OutputArg> Outs) {
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- const CCValAssign &VA = ArgLocs[i];
+ CCValAssign &VA = ArgLocs[i];
MVT ValTy = VA.getLocVT();
// FIXME: What about f32 arguments? C promotes them to f64 when calling
// varargs functions.
continue;
// This floating point argument should be reassigned.
- CCValAssign NewVA;
-
// Determine the offset into the argument array.
Register firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0;
unsigned argSize = (ValTy == MVT::f64) ? 8 : 16;
unsigned IReg = SP::I0 + Offset/8;
if (ValTy == MVT::f64)
// Full register, just bitconvert into i64.
- NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
- IReg, MVT::i64, CCValAssign::BCvt);
+ VA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), IReg, MVT::i64,
+ CCValAssign::BCvt);
else {
assert(ValTy == MVT::f128 && "Unexpected type!");
// Full register, just bitconvert into i128 -- We will lower this into
// two i64s in LowerCall_64.
- NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(),
- IReg, MVT::i128, CCValAssign::BCvt);
+ VA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), IReg,
+ MVT::i128, CCValAssign::BCvt);
}
} else {
// This needs to go to memory, we're out of integer registers.
- NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(),
- Offset, VA.getLocVT(), VA.getLocInfo());
+ VA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), Offset,
+ VA.getLocVT(), VA.getLocInfo());
}
- ArgLocs[i] = NewVA;
}
}