/// class abstracts the differences.
struct ValueHandler {
ValueHandler(bool IsIncoming, MachineIRBuilder &MIRBuilder,
- MachineRegisterInfo &MRI, CCAssignFn *AssignFn)
- : MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn),
- IsIncomingArgumentHandler(IsIncoming) {}
+ MachineRegisterInfo &MRI, CCAssignFn *AssignFn_,
+ CCAssignFn *AssignFnVarArg_ = nullptr)
+ : MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn_),
+ AssignFnVarArg(AssignFnVarArg_),
+ IsIncomingArgumentHandler(IsIncoming) {
+
+ // Some targets change the handler depending on whether the call is
+ // varargs or not. If
+ if (!AssignFnVarArg)
+ AssignFnVarArg = AssignFn;
+ }
virtual ~ValueHandler() = default;
virtual bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, const ArgInfo &Info,
ISD::ArgFlagsTy Flags, CCState &State) {
- return AssignFn(ValNo, ValVT, LocVT, LocInfo, Flags, State);
+ return getAssignFn(State.isVarArg())(ValNo, ValVT, LocVT, LocInfo, Flags,
+ State);
}
MachineIRBuilder &MIRBuilder;
MachineRegisterInfo &MRI;
+
+ /// Assignment function to use for a general call.
CCAssignFn *AssignFn;
+ /// Assignment function to use for a variadic call. This is usually the same
+ /// as AssignFn.
+ CCAssignFn *AssignFnVarArg;
+
+ /// Select the appropriate assignment function depending on whether this is
+ /// a variadic call.
+ CCAssignFn *getAssignFn(bool IsVarArg) const {
+ return IsVarArg ? AssignFnVarArg : AssignFn;
+ }
+
private:
bool IsIncomingArgumentHandler;
virtual void anchor();
struct IncomingValueHandler : public ValueHandler {
IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
- CCAssignFn *AssignFn)
- : ValueHandler(true, MIRBuilder, MRI, AssignFn) {}
+ CCAssignFn *AssignFn_,
+ CCAssignFn *AssignFnVarArg_ = nullptr)
+ : ValueHandler(true, MIRBuilder, MRI, AssignFn_, AssignFnVarArg_) {}
/// Insert G_ASSERT_ZEXT/G_ASSERT_SEXT or other hint instruction based on \p
/// VA, returning the new register if a hint was inserted.
struct OutgoingValueHandler : public ValueHandler {
OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
- CCAssignFn *AssignFn)
- : ValueHandler(false, MIRBuilder, MRI, AssignFn) {}
+ CCAssignFn *AssignFn,
+ CCAssignFn *AssignFnVarArg = nullptr)
+ : ValueHandler(false, MIRBuilder, MRI, AssignFn, AssignFnVarArg) {}
};
protected:
const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
CCState &State) override {
applyStackPassedSmallTypeDAGHack(OrigVT, ValVT, LocVT);
- return AssignFn(ValNo, ValVT, LocVT, LocInfo, Flags, State);
+ return getAssignFn(State.isVarArg())(ValNo, ValVT, LocVT, LocInfo, Flags,
+ State);
}
/// How the physical register gets marked varies between formal
MachineInstrBuilder MIB, CCAssignFn *AssignFn,
CCAssignFn *AssignFnVarArg, bool IsReturn,
bool IsTailCall = false, int FPDiff = 0)
- : OutgoingValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB),
- AssignFnVarArg(AssignFnVarArg), IsReturn(IsReturn),
- IsTailCall(IsTailCall), FPDiff(FPDiff), StackSize(0), SPReg(0),
+ : OutgoingValueHandler(MIRBuilder, MRI, AssignFn, AssignFnVarArg),
+ MIB(MIB), IsReturn(IsReturn), IsTailCall(IsTailCall), FPDiff(FPDiff),
+ StackSize(0), SPReg(0),
Subtarget(MIRBuilder.getMF().getSubtarget<AArch64Subtarget>()) {}
Register getStackAddress(uint64_t Size, int64_t Offset,
}
MachineInstrBuilder MIB;
- CCAssignFn *AssignFnVarArg;
/// Track if this is used for a return instead of function argument
/// passing. We apply a hack to i1/i8/i16 stack passed values, but do not use