Index: llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -144,9 +144,17 @@ /// 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; @@ -226,13 +234,26 @@ 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(); @@ -240,8 +261,9 @@ 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. @@ -254,8 +276,9 @@ 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: Index: llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp +++ llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp @@ -138,7 +138,8 @@ 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 @@ -187,9 +188,9 @@ 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()) {} Register getStackAddress(uint64_t Size, int64_t Offset, @@ -296,7 +297,6 @@ } 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