xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsCallLowering.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
10b57cec5SDimitry Andric //===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements the lowering of LLVM calls to machine code calls for
110b57cec5SDimitry Andric /// GlobalISel.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "MipsCallLowering.h"
160b57cec5SDimitry Andric #include "MipsCCState.h"
170b57cec5SDimitry Andric #include "MipsMachineFunction.h"
180b57cec5SDimitry Andric #include "MipsTargetMachine.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/Analysis.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
2181ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
260b57cec5SDimitry Andric     : CallLowering(&TLI) {}
270b57cec5SDimitry Andric 
28349cc55cSDimitry Andric namespace {
29fe6060f1SDimitry Andric struct MipsOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {
30fe6060f1SDimitry Andric   /// This is the name of the function being called
31fe6060f1SDimitry Andric   /// FIXME: Relying on this is unsound
32fe6060f1SDimitry Andric   const char *Func = nullptr;
330b57cec5SDimitry Andric 
34fe6060f1SDimitry Andric   /// Is this a return value, or an outgoing call operand.
35fe6060f1SDimitry Andric   bool IsReturn;
360b57cec5SDimitry Andric 
37fe6060f1SDimitry Andric   MipsOutgoingValueAssigner(CCAssignFn *AssignFn_, const char *Func,
38fe6060f1SDimitry Andric                             bool IsReturn)
39fe6060f1SDimitry Andric       : OutgoingValueAssigner(AssignFn_), Func(Func), IsReturn(IsReturn) {}
400b57cec5SDimitry Andric 
41fe6060f1SDimitry Andric   bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
42fe6060f1SDimitry Andric                  CCValAssign::LocInfo LocInfo,
43fe6060f1SDimitry Andric                  const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
44fe6060f1SDimitry Andric                  CCState &State_) override {
45fe6060f1SDimitry Andric     MipsCCState &State = static_cast<MipsCCState &>(State_);
460b57cec5SDimitry Andric 
47fe6060f1SDimitry Andric     if (IsReturn)
48fe6060f1SDimitry Andric       State.PreAnalyzeReturnValue(EVT::getEVT(Info.Ty));
49fe6060f1SDimitry Andric     else
50fe6060f1SDimitry Andric       State.PreAnalyzeCallOperand(Info.Ty, Info.IsFixed, Func);
510b57cec5SDimitry Andric 
52fe6060f1SDimitry Andric     return CallLowering::OutgoingValueAssigner::assignArg(
53fe6060f1SDimitry Andric         ValNo, OrigVT, ValVT, LocVT, LocInfo, Info, Flags, State);
54fe6060f1SDimitry Andric   }
55fe6060f1SDimitry Andric };
560b57cec5SDimitry Andric 
57fe6060f1SDimitry Andric struct MipsIncomingValueAssigner : public CallLowering::IncomingValueAssigner {
58fe6060f1SDimitry Andric   /// This is the name of the function being called
59fe6060f1SDimitry Andric   /// FIXME: Relying on this is unsound
60fe6060f1SDimitry Andric   const char *Func = nullptr;
61fe6060f1SDimitry Andric 
62fe6060f1SDimitry Andric   /// Is this a call return value, or an incoming function argument.
63fe6060f1SDimitry Andric   bool IsReturn;
64fe6060f1SDimitry Andric 
65fe6060f1SDimitry Andric   MipsIncomingValueAssigner(CCAssignFn *AssignFn_, const char *Func,
66fe6060f1SDimitry Andric                             bool IsReturn)
67fe6060f1SDimitry Andric       : IncomingValueAssigner(AssignFn_), Func(Func), IsReturn(IsReturn) {}
68fe6060f1SDimitry Andric 
69fe6060f1SDimitry Andric   bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
70fe6060f1SDimitry Andric                  CCValAssign::LocInfo LocInfo,
71fe6060f1SDimitry Andric                  const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
72fe6060f1SDimitry Andric                  CCState &State_) override {
73fe6060f1SDimitry Andric     MipsCCState &State = static_cast<MipsCCState &>(State_);
74fe6060f1SDimitry Andric 
75fe6060f1SDimitry Andric     if (IsReturn)
76fe6060f1SDimitry Andric       State.PreAnalyzeCallResult(Info.Ty, Func);
77fe6060f1SDimitry Andric     else
78fe6060f1SDimitry Andric       State.PreAnalyzeFormalArgument(Info.Ty, Flags);
79fe6060f1SDimitry Andric 
80fe6060f1SDimitry Andric     return CallLowering::IncomingValueAssigner::assignArg(
81fe6060f1SDimitry Andric         ValNo, OrigVT, ValVT, LocVT, LocInfo, Info, Flags, State);
820b57cec5SDimitry Andric   }
83fe6060f1SDimitry Andric };
840b57cec5SDimitry Andric 
85fe6060f1SDimitry Andric class MipsIncomingValueHandler : public CallLowering::IncomingValueHandler {
86fe6060f1SDimitry Andric   const MipsSubtarget &STI;
87fe6060f1SDimitry Andric 
880b57cec5SDimitry Andric public:
89e8d8bef9SDimitry Andric   MipsIncomingValueHandler(MachineIRBuilder &MIRBuilder,
90e8d8bef9SDimitry Andric                            MachineRegisterInfo &MRI)
91fe6060f1SDimitry Andric       : IncomingValueHandler(MIRBuilder, MRI),
92fe6060f1SDimitry Andric         STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()) {}
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric private:
95fe6060f1SDimitry Andric   void assignValueToReg(Register ValVReg, Register PhysReg,
965f757f3fSDimitry Andric                         const CCValAssign &VA) override;
970b57cec5SDimitry Andric 
98fe6060f1SDimitry Andric   Register getStackAddress(uint64_t Size, int64_t Offset,
99fe6060f1SDimitry Andric                            MachinePointerInfo &MPO,
100fe6060f1SDimitry Andric                            ISD::ArgFlagsTy Flags) override;
101fe6060f1SDimitry Andric   void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
1025f757f3fSDimitry Andric                             const MachinePointerInfo &MPO,
1035f757f3fSDimitry Andric                             const CCValAssign &VA) override;
1040b57cec5SDimitry Andric 
105fe6060f1SDimitry Andric   unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
106349cc55cSDimitry Andric                              ArrayRef<CCValAssign> VAs,
107349cc55cSDimitry Andric                              std::function<void()> *Thunk = nullptr) override;
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   virtual void markPhysRegUsed(unsigned PhysReg) {
1108bcb0991SDimitry Andric     MIRBuilder.getMRI()->addLiveIn(PhysReg);
1110b57cec5SDimitry Andric     MIRBuilder.getMBB().addLiveIn(PhysReg);
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric };
1140b57cec5SDimitry Andric 
115e8d8bef9SDimitry Andric class CallReturnHandler : public MipsIncomingValueHandler {
1160b57cec5SDimitry Andric public:
1170b57cec5SDimitry Andric   CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
1180b57cec5SDimitry Andric                     MachineInstrBuilder &MIB)
119e8d8bef9SDimitry Andric       : MipsIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric private:
1220b57cec5SDimitry Andric   void markPhysRegUsed(unsigned PhysReg) override {
1230b57cec5SDimitry Andric     MIB.addDef(PhysReg, RegState::Implicit);
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   MachineInstrBuilder &MIB;
1270b57cec5SDimitry Andric };
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric } // end anonymous namespace
1300b57cec5SDimitry Andric 
131e8d8bef9SDimitry Andric void MipsIncomingValueHandler::assignValueToReg(Register ValVReg,
132fe6060f1SDimitry Andric                                                 Register PhysReg,
1335f757f3fSDimitry Andric                                                 const CCValAssign &VA) {
1340b57cec5SDimitry Andric   markPhysRegUsed(PhysReg);
135fe6060f1SDimitry Andric   IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
138fe6060f1SDimitry Andric Register MipsIncomingValueHandler::getStackAddress(uint64_t Size,
139fe6060f1SDimitry Andric                                                    int64_t Offset,
140fe6060f1SDimitry Andric                                                    MachinePointerInfo &MPO,
141fe6060f1SDimitry Andric                                                    ISD::ArgFlagsTy Flags) {
142fe6060f1SDimitry Andric 
1430b57cec5SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
1440b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
1450b57cec5SDimitry Andric 
146fe6060f1SDimitry Andric   // FIXME: This should only be immutable for non-byval memory arguments.
1470b57cec5SDimitry Andric   int FI = MFI.CreateFixedObject(Size, Offset, true);
148fe6060f1SDimitry Andric   MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
1490b57cec5SDimitry Andric 
1505ffd83dbSDimitry Andric   return MIRBuilder.buildFrameIndex(LLT::pointer(0, 32), FI).getReg(0);
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
1535f757f3fSDimitry Andric void MipsIncomingValueHandler::assignValueToAddress(
1545f757f3fSDimitry Andric     Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,
1555f757f3fSDimitry Andric     const CCValAssign &VA) {
156fe6060f1SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
157fe6060f1SDimitry Andric   auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
158fe6060f1SDimitry Andric                                      inferAlignFromPtrInfo(MF, MPO));
159fe6060f1SDimitry Andric   MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
162fe6060f1SDimitry Andric /// Handle cases when f64 is split into 2 32-bit GPRs. This is a custom
163fe6060f1SDimitry Andric /// assignment because generic code assumes getNumRegistersForCallingConv is
164fe6060f1SDimitry Andric /// accurate. In this case it is not because the type/number are context
165fe6060f1SDimitry Andric /// dependent on other arguments.
166fe6060f1SDimitry Andric unsigned
167fe6060f1SDimitry Andric MipsIncomingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,
168349cc55cSDimitry Andric                                             ArrayRef<CCValAssign> VAs,
169349cc55cSDimitry Andric                                             std::function<void()> *Thunk) {
170fe6060f1SDimitry Andric   const CCValAssign &VALo = VAs[0];
171fe6060f1SDimitry Andric   const CCValAssign &VAHi = VAs[1];
172fe6060f1SDimitry Andric 
173fe6060f1SDimitry Andric   assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
174fe6060f1SDimitry Andric          VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
175fe6060f1SDimitry Andric          "unexpected custom value");
176fe6060f1SDimitry Andric 
177fe6060f1SDimitry Andric   auto CopyLo = MIRBuilder.buildCopy(LLT::scalar(32), VALo.getLocReg());
178fe6060f1SDimitry Andric   auto CopyHi = MIRBuilder.buildCopy(LLT::scalar(32), VAHi.getLocReg());
179fe6060f1SDimitry Andric   if (!STI.isLittle())
180fe6060f1SDimitry Andric     std::swap(CopyLo, CopyHi);
181fe6060f1SDimitry Andric 
182fe6060f1SDimitry Andric   Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
183fe6060f1SDimitry Andric   Arg.Regs = { CopyLo.getReg(0), CopyHi.getReg(0) };
184bdd1243dSDimitry Andric   MIRBuilder.buildMergeLikeInstr(Arg.OrigRegs[0], {CopyLo, CopyHi});
185fe6060f1SDimitry Andric 
186fe6060f1SDimitry Andric   markPhysRegUsed(VALo.getLocReg());
187fe6060f1SDimitry Andric   markPhysRegUsed(VAHi.getLocReg());
188*7a6dacacSDimitry Andric   return 2;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric namespace {
192fe6060f1SDimitry Andric class MipsOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
193fe6060f1SDimitry Andric   const MipsSubtarget &STI;
194fe6060f1SDimitry Andric 
1950b57cec5SDimitry Andric public:
196e8d8bef9SDimitry Andric   MipsOutgoingValueHandler(MachineIRBuilder &MIRBuilder,
197e8d8bef9SDimitry Andric                            MachineRegisterInfo &MRI, MachineInstrBuilder &MIB)
198fe6060f1SDimitry Andric       : OutgoingValueHandler(MIRBuilder, MRI),
199fe6060f1SDimitry Andric         STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()), MIB(MIB) {}
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric private:
202fe6060f1SDimitry Andric   void assignValueToReg(Register ValVReg, Register PhysReg,
2035f757f3fSDimitry Andric                         const CCValAssign &VA) override;
2040b57cec5SDimitry Andric 
205fe6060f1SDimitry Andric   Register getStackAddress(uint64_t Size, int64_t Offset,
206fe6060f1SDimitry Andric                            MachinePointerInfo &MPO,
207fe6060f1SDimitry Andric                            ISD::ArgFlagsTy Flags) override;
2080b57cec5SDimitry Andric 
209fe6060f1SDimitry Andric   void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
2105f757f3fSDimitry Andric                             const MachinePointerInfo &MPO,
2115f757f3fSDimitry Andric                             const CCValAssign &VA) override;
212fe6060f1SDimitry Andric   unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
213349cc55cSDimitry Andric                              ArrayRef<CCValAssign> VAs,
214349cc55cSDimitry Andric                              std::function<void()> *Thunk) override;
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   MachineInstrBuilder &MIB;
2170b57cec5SDimitry Andric };
2180b57cec5SDimitry Andric } // end anonymous namespace
2190b57cec5SDimitry Andric 
220e8d8bef9SDimitry Andric void MipsOutgoingValueHandler::assignValueToReg(Register ValVReg,
221fe6060f1SDimitry Andric                                                 Register PhysReg,
2225f757f3fSDimitry Andric                                                 const CCValAssign &VA) {
2230b57cec5SDimitry Andric   Register ExtReg = extendRegister(ValVReg, VA);
2240b57cec5SDimitry Andric   MIRBuilder.buildCopy(PhysReg, ExtReg);
2250b57cec5SDimitry Andric   MIB.addUse(PhysReg, RegState::Implicit);
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric 
228fe6060f1SDimitry Andric Register MipsOutgoingValueHandler::getStackAddress(uint64_t Size,
229fe6060f1SDimitry Andric                                                    int64_t Offset,
230fe6060f1SDimitry Andric                                                    MachinePointerInfo &MPO,
231fe6060f1SDimitry Andric                                                    ISD::ArgFlagsTy Flags) {
2320b57cec5SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
233fe6060f1SDimitry Andric   MPO = MachinePointerInfo::getStack(MF, Offset);
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   LLT p0 = LLT::pointer(0, 32);
2360b57cec5SDimitry Andric   LLT s32 = LLT::scalar(32);
2375ffd83dbSDimitry Andric   auto SPReg = MIRBuilder.buildCopy(p0, Register(Mips::SP));
2380b57cec5SDimitry Andric 
2395ffd83dbSDimitry Andric   auto OffsetReg = MIRBuilder.buildConstant(s32, Offset);
2405ffd83dbSDimitry Andric   auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
2415ffd83dbSDimitry Andric   return AddrReg.getReg(0);
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
2445f757f3fSDimitry Andric void MipsOutgoingValueHandler::assignValueToAddress(
2455f757f3fSDimitry Andric     Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,
2465f757f3fSDimitry Andric     const CCValAssign &VA) {
247fe6060f1SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
248fe6060f1SDimitry Andric   uint64_t LocMemOffset = VA.getLocMemOffset();
249fe6060f1SDimitry Andric 
250fe6060f1SDimitry Andric   auto MMO = MF.getMachineMemOperand(
251fe6060f1SDimitry Andric       MPO, MachineMemOperand::MOStore, MemTy,
252fe6060f1SDimitry Andric       commonAlignment(STI.getStackAlignment(), LocMemOffset));
253fe6060f1SDimitry Andric 
2540b57cec5SDimitry Andric   Register ExtReg = extendRegister(ValVReg, VA);
2550b57cec5SDimitry Andric   MIRBuilder.buildStore(ExtReg, Addr, *MMO);
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
258fe6060f1SDimitry Andric unsigned
259fe6060f1SDimitry Andric MipsOutgoingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,
260349cc55cSDimitry Andric                                             ArrayRef<CCValAssign> VAs,
261349cc55cSDimitry Andric                                             std::function<void()> *Thunk) {
262fe6060f1SDimitry Andric   const CCValAssign &VALo = VAs[0];
263fe6060f1SDimitry Andric   const CCValAssign &VAHi = VAs[1];
2640b57cec5SDimitry Andric 
265fe6060f1SDimitry Andric   assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
266fe6060f1SDimitry Andric          VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
267fe6060f1SDimitry Andric          "unexpected custom value");
2680b57cec5SDimitry Andric 
269fe6060f1SDimitry Andric   auto Unmerge =
270fe6060f1SDimitry Andric       MIRBuilder.buildUnmerge({LLT::scalar(32), LLT::scalar(32)}, Arg.Regs[0]);
271fe6060f1SDimitry Andric   Register Lo = Unmerge.getReg(0);
272fe6060f1SDimitry Andric   Register Hi = Unmerge.getReg(1);
273fe6060f1SDimitry Andric 
274fe6060f1SDimitry Andric   Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
275fe6060f1SDimitry Andric   Arg.Regs = { Lo, Hi };
276fe6060f1SDimitry Andric   if (!STI.isLittle())
277fe6060f1SDimitry Andric     std::swap(Lo, Hi);
278fe6060f1SDimitry Andric 
279349cc55cSDimitry Andric   // If we can return a thunk, just include the register copies. The unmerge can
280349cc55cSDimitry Andric   // be emitted earlier.
281349cc55cSDimitry Andric   if (Thunk) {
282349cc55cSDimitry Andric     *Thunk = [=]() {
283349cc55cSDimitry Andric       MIRBuilder.buildCopy(VALo.getLocReg(), Lo);
284349cc55cSDimitry Andric       MIRBuilder.buildCopy(VAHi.getLocReg(), Hi);
285349cc55cSDimitry Andric     };
286349cc55cSDimitry Andric     return 2;
287349cc55cSDimitry Andric   }
288fe6060f1SDimitry Andric   MIRBuilder.buildCopy(VALo.getLocReg(), Lo);
289fe6060f1SDimitry Andric   MIRBuilder.buildCopy(VAHi.getLocReg(), Hi);
290fe6060f1SDimitry Andric   return 2;
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric 
2938bcb0991SDimitry Andric static bool isSupportedArgumentType(Type *T) {
2940b57cec5SDimitry Andric   if (T->isIntegerTy())
2950b57cec5SDimitry Andric     return true;
2960b57cec5SDimitry Andric   if (T->isPointerTy())
2970b57cec5SDimitry Andric     return true;
2980b57cec5SDimitry Andric   if (T->isFloatingPointTy())
2990b57cec5SDimitry Andric     return true;
3000b57cec5SDimitry Andric   return false;
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric 
3038bcb0991SDimitry Andric static bool isSupportedReturnType(Type *T) {
3048bcb0991SDimitry Andric   if (T->isIntegerTy())
3058bcb0991SDimitry Andric     return true;
3068bcb0991SDimitry Andric   if (T->isPointerTy())
3078bcb0991SDimitry Andric     return true;
3088bcb0991SDimitry Andric   if (T->isFloatingPointTy())
3098bcb0991SDimitry Andric     return true;
3108bcb0991SDimitry Andric   if (T->isAggregateType())
3118bcb0991SDimitry Andric     return true;
3128bcb0991SDimitry Andric   return false;
3138bcb0991SDimitry Andric }
3148bcb0991SDimitry Andric 
3150b57cec5SDimitry Andric bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
316e8d8bef9SDimitry Andric                                    const Value *Val, ArrayRef<Register> VRegs,
317e8d8bef9SDimitry Andric                                    FunctionLoweringInfo &FLI) const {
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
3200b57cec5SDimitry Andric 
3218bcb0991SDimitry Andric   if (Val != nullptr && !isSupportedReturnType(Val->getType()))
3220b57cec5SDimitry Andric     return false;
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   if (!VRegs.empty()) {
3250b57cec5SDimitry Andric     MachineFunction &MF = MIRBuilder.getMF();
3260b57cec5SDimitry Andric     const Function &F = MF.getFunction();
3270b57cec5SDimitry Andric     const DataLayout &DL = MF.getDataLayout();
3280b57cec5SDimitry Andric     const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric     SmallVector<ArgInfo, 8> RetInfos;
3310b57cec5SDimitry Andric 
332fe6060f1SDimitry Andric     ArgInfo ArgRetInfo(VRegs, *Val, 0);
3338bcb0991SDimitry Andric     setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);
334fe6060f1SDimitry Andric     splitToValueTypes(ArgRetInfo, RetInfos, DL, F.getCallingConv());
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric     SmallVector<CCValAssign, 16> ArgLocs;
337fe6060f1SDimitry Andric     SmallVector<ISD::OutputArg, 8> Outs;
338fe6060f1SDimitry Andric 
3390b57cec5SDimitry Andric     MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
3400b57cec5SDimitry Andric                        F.getContext());
3410b57cec5SDimitry Andric 
342e8d8bef9SDimitry Andric     MipsOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
343fe6060f1SDimitry Andric     std::string FuncName = F.getName().str();
344fe6060f1SDimitry Andric     MipsOutgoingValueAssigner Assigner(TLI.CCAssignFnForReturn(),
345fe6060f1SDimitry Andric                                        FuncName.c_str(), /*IsReturn*/ true);
346fe6060f1SDimitry Andric 
347fe6060f1SDimitry Andric     if (!determineAssignments(Assigner, RetInfos, CCInfo))
348fe6060f1SDimitry Andric       return false;
349fe6060f1SDimitry Andric 
350fe6060f1SDimitry Andric     if (!handleAssignments(RetHandler, RetInfos, CCInfo, ArgLocs, MIRBuilder))
3510b57cec5SDimitry Andric       return false;
3520b57cec5SDimitry Andric   }
353fe6060f1SDimitry Andric 
3540b57cec5SDimitry Andric   MIRBuilder.insertInstr(Ret);
3550b57cec5SDimitry Andric   return true;
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric 
358e8d8bef9SDimitry Andric bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
359e8d8bef9SDimitry Andric                                             const Function &F,
360e8d8bef9SDimitry Andric                                             ArrayRef<ArrayRef<Register>> VRegs,
361e8d8bef9SDimitry Andric                                             FunctionLoweringInfo &FLI) const {
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   // Quick exit if there aren't any args.
3640b57cec5SDimitry Andric   if (F.arg_empty())
3650b57cec5SDimitry Andric     return true;
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   for (auto &Arg : F.args()) {
3688bcb0991SDimitry Andric     if (!isSupportedArgumentType(Arg.getType()))
3690b57cec5SDimitry Andric       return false;
3700b57cec5SDimitry Andric   }
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
3730b57cec5SDimitry Andric   const DataLayout &DL = MF.getDataLayout();
3740b57cec5SDimitry Andric   const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   SmallVector<ArgInfo, 8> ArgInfos;
3770b57cec5SDimitry Andric   unsigned i = 0;
3780b57cec5SDimitry Andric   for (auto &Arg : F.args()) {
379fe6060f1SDimitry Andric     ArgInfo AInfo(VRegs[i], Arg, i);
3800b57cec5SDimitry Andric     setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);
381fe6060f1SDimitry Andric 
382fe6060f1SDimitry Andric     splitToValueTypes(AInfo, ArgInfos, DL, F.getCallingConv());
3830b57cec5SDimitry Andric     ++i;
3840b57cec5SDimitry Andric   }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   SmallVector<ISD::InputArg, 8> Ins;
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
3890b57cec5SDimitry Andric   MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
3900b57cec5SDimitry Andric                      F.getContext());
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   const MipsTargetMachine &TM =
3930b57cec5SDimitry Andric       static_cast<const MipsTargetMachine &>(MF.getTarget());
3940b57cec5SDimitry Andric   const MipsABIInfo &ABI = TM.getABI();
3950b57cec5SDimitry Andric   CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()),
3965ffd83dbSDimitry Andric                        Align(1));
397fe6060f1SDimitry Andric 
398fe6060f1SDimitry Andric   const std::string FuncName = F.getName().str();
399fe6060f1SDimitry Andric   MipsIncomingValueAssigner Assigner(TLI.CCAssignFnForCall(), FuncName.c_str(),
400fe6060f1SDimitry Andric                                      /*IsReturn*/ false);
401fe6060f1SDimitry Andric   if (!determineAssignments(Assigner, ArgInfos, CCInfo))
402fe6060f1SDimitry Andric     return false;
4030b57cec5SDimitry Andric 
404e8d8bef9SDimitry Andric   MipsIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
405fe6060f1SDimitry Andric   if (!handleAssignments(Handler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))
4060b57cec5SDimitry Andric     return false;
4070b57cec5SDimitry Andric 
4088bcb0991SDimitry Andric   if (F.isVarArg()) {
4098bcb0991SDimitry Andric     ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs();
4108bcb0991SDimitry Andric     unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
4118bcb0991SDimitry Andric 
4128bcb0991SDimitry Andric     int VaArgOffset;
4138bcb0991SDimitry Andric     unsigned RegSize = 4;
4148bcb0991SDimitry Andric     if (ArgRegs.size() == Idx)
41506c3fb27SDimitry Andric       VaArgOffset = alignTo(CCInfo.getStackSize(), RegSize);
4168bcb0991SDimitry Andric     else {
4178bcb0991SDimitry Andric       VaArgOffset =
4188bcb0991SDimitry Andric           (int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) -
4198bcb0991SDimitry Andric           (int)(RegSize * (ArgRegs.size() - Idx));
4208bcb0991SDimitry Andric     }
4218bcb0991SDimitry Andric 
4228bcb0991SDimitry Andric     MachineFrameInfo &MFI = MF.getFrameInfo();
4238bcb0991SDimitry Andric     int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
4248bcb0991SDimitry Andric     MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI);
4258bcb0991SDimitry Andric 
4268bcb0991SDimitry Andric     for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) {
4278bcb0991SDimitry Andric       MIRBuilder.getMBB().addLiveIn(ArgRegs[I]);
428fe6060f1SDimitry Andric       LLT RegTy = LLT::scalar(RegSize * 8);
4298bcb0991SDimitry Andric       MachineInstrBuilder Copy =
430fe6060f1SDimitry Andric           MIRBuilder.buildCopy(RegTy, Register(ArgRegs[I]));
4318bcb0991SDimitry Andric       FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
4328bcb0991SDimitry Andric       MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI);
433fe6060f1SDimitry Andric 
434fe6060f1SDimitry Andric       const LLT PtrTy = LLT::pointer(MPO.getAddrSpace(), 32);
435fe6060f1SDimitry Andric       auto FrameIndex = MIRBuilder.buildFrameIndex(PtrTy, FI);
4365ffd83dbSDimitry Andric       MachineMemOperand *MMO = MF.getMachineMemOperand(
437fe6060f1SDimitry Andric           MPO, MachineMemOperand::MOStore, RegTy, Align(RegSize));
4388bcb0991SDimitry Andric       MIRBuilder.buildStore(Copy, FrameIndex, *MMO);
4398bcb0991SDimitry Andric     }
4408bcb0991SDimitry Andric   }
4418bcb0991SDimitry Andric 
4420b57cec5SDimitry Andric   return true;
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
4468bcb0991SDimitry Andric                                  CallLoweringInfo &Info) const {
4470b57cec5SDimitry Andric 
4488bcb0991SDimitry Andric   if (Info.CallConv != CallingConv::C)
4490b57cec5SDimitry Andric     return false;
4500b57cec5SDimitry Andric 
4518bcb0991SDimitry Andric   for (auto &Arg : Info.OrigArgs) {
4528bcb0991SDimitry Andric     if (!isSupportedArgumentType(Arg.Ty))
4530b57cec5SDimitry Andric       return false;
4548bcb0991SDimitry Andric     if (Arg.Flags[0].isByVal())
4558bcb0991SDimitry Andric       return false;
4568bcb0991SDimitry Andric     if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy())
4570b57cec5SDimitry Andric       return false;
4580b57cec5SDimitry Andric   }
4590b57cec5SDimitry Andric 
4608bcb0991SDimitry Andric   if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(Info.OrigRet.Ty))
4610b57cec5SDimitry Andric     return false;
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
4640b57cec5SDimitry Andric   const Function &F = MF.getFunction();
4658bcb0991SDimitry Andric   const DataLayout &DL = MF.getDataLayout();
4660b57cec5SDimitry Andric   const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
4670b57cec5SDimitry Andric   const MipsTargetMachine &TM =
4680b57cec5SDimitry Andric       static_cast<const MipsTargetMachine &>(MF.getTarget());
4690b57cec5SDimitry Andric   const MipsABIInfo &ABI = TM.getABI();
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   MachineInstrBuilder CallSeqStart =
4720b57cec5SDimitry Andric       MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN);
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   const bool IsCalleeGlobalPIC =
4758bcb0991SDimitry Andric       Info.Callee.isGlobal() && TM.isPositionIndependent();
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(
4788bcb0991SDimitry Andric       Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL);
4790b57cec5SDimitry Andric   MIB.addDef(Mips::SP, RegState::Implicit);
4800b57cec5SDimitry Andric   if (IsCalleeGlobalPIC) {
4810b57cec5SDimitry Andric     Register CalleeReg =
4820b57cec5SDimitry Andric         MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32));
4830b57cec5SDimitry Andric     MachineInstr *CalleeGlobalValue =
4848bcb0991SDimitry Andric         MIRBuilder.buildGlobalValue(CalleeReg, Info.Callee.getGlobal());
4858bcb0991SDimitry Andric     if (!Info.Callee.getGlobal()->hasLocalLinkage())
4860b57cec5SDimitry Andric       CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL);
4870b57cec5SDimitry Andric     MIB.addUse(CalleeReg);
4880b57cec5SDimitry Andric   } else
4898bcb0991SDimitry Andric     MIB.add(Info.Callee);
4900b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
491fe6060f1SDimitry Andric   MIB.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric   TargetLowering::ArgListTy FuncOrigArgs;
4948bcb0991SDimitry Andric   FuncOrigArgs.reserve(Info.OrigArgs.size());
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric   SmallVector<ArgInfo, 8> ArgInfos;
497fe6060f1SDimitry Andric   for (auto &Arg : Info.OrigArgs)
498fe6060f1SDimitry Andric     splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv);
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   SmallVector<CCValAssign, 8> ArgLocs;
5018bcb0991SDimitry Andric   bool IsCalleeVarArg = false;
5028bcb0991SDimitry Andric   if (Info.Callee.isGlobal()) {
5038bcb0991SDimitry Andric     const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal());
5048bcb0991SDimitry Andric     IsCalleeVarArg = CF->isVarArg();
5058bcb0991SDimitry Andric   }
506fe6060f1SDimitry Andric 
507fe6060f1SDimitry Andric   // FIXME: Should use MipsCCState::getSpecialCallingConvForCallee, but it
508fe6060f1SDimitry Andric   // depends on looking directly at the call target.
509fe6060f1SDimitry Andric   MipsCCState CCInfo(Info.CallConv, IsCalleeVarArg, MF, ArgLocs,
5100b57cec5SDimitry Andric                      F.getContext());
5110b57cec5SDimitry Andric 
5125ffd83dbSDimitry Andric   CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv),
5135ffd83dbSDimitry Andric                        Align(1));
514fe6060f1SDimitry Andric 
5158bcb0991SDimitry Andric   const char *Call =
5168bcb0991SDimitry Andric       Info.Callee.isSymbol() ? Info.Callee.getSymbolName() : nullptr;
5170b57cec5SDimitry Andric 
518fe6060f1SDimitry Andric   MipsOutgoingValueAssigner Assigner(TLI.CCAssignFnForCall(), Call,
519fe6060f1SDimitry Andric                                      /*IsReturn*/ false);
520fe6060f1SDimitry Andric   if (!determineAssignments(Assigner, ArgInfos, CCInfo))
5210b57cec5SDimitry Andric     return false;
522fe6060f1SDimitry Andric 
523fe6060f1SDimitry Andric   MipsOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), MIB);
524fe6060f1SDimitry Andric   if (!handleAssignments(ArgHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))
525fe6060f1SDimitry Andric     return false;
5260b57cec5SDimitry Andric 
52706c3fb27SDimitry Andric   unsigned StackSize = CCInfo.getStackSize();
528fe6060f1SDimitry Andric   unsigned StackAlignment = F.getParent()->getOverrideStackAlignment();
529fe6060f1SDimitry Andric   if (!StackAlignment) {
5300b57cec5SDimitry Andric     const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
531fe6060f1SDimitry Andric     StackAlignment = TFL->getStackAlignment();
532fe6060f1SDimitry Andric   }
53306c3fb27SDimitry Andric   StackSize = alignTo(StackSize, StackAlignment);
53406c3fb27SDimitry Andric   CallSeqStart.addImm(StackSize).addImm(0);
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric   if (IsCalleeGlobalPIC) {
5370b57cec5SDimitry Andric     MIRBuilder.buildCopy(
5380b57cec5SDimitry Andric       Register(Mips::GP),
5395ffd83dbSDimitry Andric       MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel(MF));
5400b57cec5SDimitry Andric     MIB.addDef(Mips::GP, RegState::Implicit);
5410b57cec5SDimitry Andric   }
5420b57cec5SDimitry Andric   MIRBuilder.insertInstr(MIB);
5430b57cec5SDimitry Andric   if (MIB->getOpcode() == Mips::JALRPseudo) {
54481ad6265SDimitry Andric     const MipsSubtarget &STI = MIRBuilder.getMF().getSubtarget<MipsSubtarget>();
5450b57cec5SDimitry Andric     MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(),
5460b57cec5SDimitry Andric                          *STI.getRegBankInfo());
5470b57cec5SDimitry Andric   }
5480b57cec5SDimitry Andric 
5498bcb0991SDimitry Andric   if (!Info.OrigRet.Ty->isVoidTy()) {
5500b57cec5SDimitry Andric     ArgInfos.clear();
5510b57cec5SDimitry Andric 
552fe6060f1SDimitry Andric     CallLowering::splitToValueTypes(Info.OrigRet, ArgInfos, DL,
553fe6060f1SDimitry Andric                                     F.getCallingConv());
5540b57cec5SDimitry Andric 
555fe6060f1SDimitry Andric     const std::string FuncName = F.getName().str();
5560b57cec5SDimitry Andric     SmallVector<ISD::InputArg, 8> Ins;
5570b57cec5SDimitry Andric     SmallVector<CCValAssign, 8> ArgLocs;
558fe6060f1SDimitry Andric     MipsIncomingValueAssigner Assigner(TLI.CCAssignFnForReturn(),
559fe6060f1SDimitry Andric                                        FuncName.c_str(),
560fe6060f1SDimitry Andric                                        /*IsReturn*/ true);
561fe6060f1SDimitry Andric     CallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);
562fe6060f1SDimitry Andric 
5630b57cec5SDimitry Andric     MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
5640b57cec5SDimitry Andric                        F.getContext());
5650b57cec5SDimitry Andric 
566fe6060f1SDimitry Andric     if (!determineAssignments(Assigner, ArgInfos, CCInfo))
567fe6060f1SDimitry Andric       return false;
5680b57cec5SDimitry Andric 
569fe6060f1SDimitry Andric     if (!handleAssignments(RetHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))
5700b57cec5SDimitry Andric       return false;
5710b57cec5SDimitry Andric   }
5720b57cec5SDimitry Andric 
57306c3fb27SDimitry Andric   MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(StackSize).addImm(0);
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   return true;
5760b57cec5SDimitry Andric }
577