1fac93e28SPetar Jovanovic //===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===//
2fac93e28SPetar Jovanovic //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fac93e28SPetar Jovanovic //
7fac93e28SPetar Jovanovic //===----------------------------------------------------------------------===//
8fac93e28SPetar Jovanovic //
9fac93e28SPetar Jovanovic /// \file
10fac93e28SPetar Jovanovic /// This file implements the lowering of LLVM calls to machine code calls for
11fac93e28SPetar Jovanovic /// GlobalISel.
12fac93e28SPetar Jovanovic //
13fac93e28SPetar Jovanovic //===----------------------------------------------------------------------===//
14fac93e28SPetar Jovanovic
15fac93e28SPetar Jovanovic #include "MipsCallLowering.h"
16366857a2SPetar Jovanovic #include "MipsCCState.h"
17efcd3c00SPetar Avramovic #include "MipsMachineFunction.h"
18326ec324SPetar Jovanovic #include "MipsTargetMachine.h"
1949168f67SAlexander Ivchenko #include "llvm/CodeGen/Analysis.h"
20fac93e28SPetar Jovanovic #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
21989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineFrameInfo.h"
22fac93e28SPetar Jovanovic
23fac93e28SPetar Jovanovic using namespace llvm;
24fac93e28SPetar Jovanovic
MipsCallLowering(const MipsTargetLowering & TLI)25fac93e28SPetar Jovanovic MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
26fac93e28SPetar Jovanovic : CallLowering(&TLI) {}
27fac93e28SPetar Jovanovic
289b8b1645SBenjamin Kramer namespace {
29121541fdSMatt Arsenault struct MipsOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {
30121541fdSMatt Arsenault /// This is the name of the function being called
31121541fdSMatt Arsenault /// FIXME: Relying on this is unsound
32121541fdSMatt Arsenault const char *Func = nullptr;
33366857a2SPetar Jovanovic
34121541fdSMatt Arsenault /// Is this a return value, or an outgoing call operand.
35121541fdSMatt Arsenault bool IsReturn;
36ff1bc621SPetar Jovanovic
MipsOutgoingValueAssigner__anonbef6db3a0111::MipsOutgoingValueAssigner37121541fdSMatt Arsenault MipsOutgoingValueAssigner(CCAssignFn *AssignFn_, const char *Func,
38121541fdSMatt Arsenault bool IsReturn)
39121541fdSMatt Arsenault : OutgoingValueAssigner(AssignFn_), Func(Func), IsReturn(IsReturn) {}
40ff1bc621SPetar Jovanovic
assignArg__anonbef6db3a0111::MipsOutgoingValueAssigner41121541fdSMatt Arsenault bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
42121541fdSMatt Arsenault CCValAssign::LocInfo LocInfo,
43121541fdSMatt Arsenault const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
44121541fdSMatt Arsenault CCState &State_) override {
45121541fdSMatt Arsenault MipsCCState &State = static_cast<MipsCCState &>(State_);
46ff1bc621SPetar Jovanovic
47121541fdSMatt Arsenault if (IsReturn)
48121541fdSMatt Arsenault State.PreAnalyzeReturnValue(EVT::getEVT(Info.Ty));
49121541fdSMatt Arsenault else
50121541fdSMatt Arsenault State.PreAnalyzeCallOperand(Info.Ty, Info.IsFixed, Func);
5169ce1c13SDiana Picus
52121541fdSMatt Arsenault return CallLowering::OutgoingValueAssigner::assignArg(
53121541fdSMatt Arsenault ValNo, OrigVT, ValVT, LocVT, LocInfo, Info, Flags, State);
54121541fdSMatt Arsenault }
55121541fdSMatt Arsenault };
56ff1bc621SPetar Jovanovic
57121541fdSMatt Arsenault struct MipsIncomingValueAssigner : public CallLowering::IncomingValueAssigner {
58121541fdSMatt Arsenault /// This is the name of the function being called
59121541fdSMatt Arsenault /// FIXME: Relying on this is unsound
60121541fdSMatt Arsenault const char *Func = nullptr;
61121541fdSMatt Arsenault
62121541fdSMatt Arsenault /// Is this a call return value, or an incoming function argument.
63121541fdSMatt Arsenault bool IsReturn;
64121541fdSMatt Arsenault
MipsIncomingValueAssigner__anonbef6db3a0111::MipsIncomingValueAssigner65121541fdSMatt Arsenault MipsIncomingValueAssigner(CCAssignFn *AssignFn_, const char *Func,
66121541fdSMatt Arsenault bool IsReturn)
67121541fdSMatt Arsenault : IncomingValueAssigner(AssignFn_), Func(Func), IsReturn(IsReturn) {}
68121541fdSMatt Arsenault
assignArg__anonbef6db3a0111::MipsIncomingValueAssigner69121541fdSMatt Arsenault bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
70121541fdSMatt Arsenault CCValAssign::LocInfo LocInfo,
71121541fdSMatt Arsenault const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
72121541fdSMatt Arsenault CCState &State_) override {
73121541fdSMatt Arsenault MipsCCState &State = static_cast<MipsCCState &>(State_);
74121541fdSMatt Arsenault
75121541fdSMatt Arsenault if (IsReturn)
76121541fdSMatt Arsenault State.PreAnalyzeCallResult(Info.Ty, Func);
77121541fdSMatt Arsenault else
78121541fdSMatt Arsenault State.PreAnalyzeFormalArgument(Info.Ty, Flags);
79121541fdSMatt Arsenault
80121541fdSMatt Arsenault return CallLowering::IncomingValueAssigner::assignArg(
81121541fdSMatt Arsenault ValNo, OrigVT, ValVT, LocVT, LocInfo, Info, Flags, State);
82ff1bc621SPetar Jovanovic }
83121541fdSMatt Arsenault };
84ff1bc621SPetar Jovanovic
85121541fdSMatt Arsenault class MipsIncomingValueHandler : public CallLowering::IncomingValueHandler {
86121541fdSMatt Arsenault const MipsSubtarget &STI;
87121541fdSMatt Arsenault
88366857a2SPetar Jovanovic public:
MipsIncomingValueHandler(MachineIRBuilder & MIRBuilder,MachineRegisterInfo & MRI)890c92bfa4SMatt Arsenault MipsIncomingValueHandler(MachineIRBuilder &MIRBuilder,
900c92bfa4SMatt Arsenault MachineRegisterInfo &MRI)
91121541fdSMatt Arsenault : IncomingValueHandler(MIRBuilder, MRI),
92121541fdSMatt Arsenault STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()) {}
93366857a2SPetar Jovanovic
94366857a2SPetar Jovanovic private:
95121541fdSMatt Arsenault void assignValueToReg(Register ValVReg, Register PhysReg,
968bde5e58SAmara Emerson CCValAssign VA) override;
97226e6117SPetar Jovanovic
98121541fdSMatt Arsenault Register getStackAddress(uint64_t Size, int64_t Offset,
99121541fdSMatt Arsenault MachinePointerInfo &MPO,
100121541fdSMatt Arsenault ISD::ArgFlagsTy Flags) override;
101121541fdSMatt Arsenault void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
102121541fdSMatt Arsenault MachinePointerInfo &MPO, CCValAssign &VA) override;
103226e6117SPetar Jovanovic
104121541fdSMatt Arsenault unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
1058bde5e58SAmara Emerson ArrayRef<CCValAssign> VAs,
1068bde5e58SAmara Emerson std::function<void()> *Thunk = nullptr) override;
107ff1bc621SPetar Jovanovic
markPhysRegUsed(unsigned PhysReg)108326ec324SPetar Jovanovic virtual void markPhysRegUsed(unsigned PhysReg) {
109522fb7eeSTim Northover MIRBuilder.getMRI()->addLiveIn(PhysReg);
110366857a2SPetar Jovanovic MIRBuilder.getMBB().addLiveIn(PhysReg);
111366857a2SPetar Jovanovic }
112366857a2SPetar Jovanovic };
113326ec324SPetar Jovanovic
1140c92bfa4SMatt Arsenault class CallReturnHandler : public MipsIncomingValueHandler {
115326ec324SPetar Jovanovic public:
CallReturnHandler(MachineIRBuilder & MIRBuilder,MachineRegisterInfo & MRI,MachineInstrBuilder & MIB)116326ec324SPetar Jovanovic CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
117326ec324SPetar Jovanovic MachineInstrBuilder &MIB)
1180c92bfa4SMatt Arsenault : MipsIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
119326ec324SPetar Jovanovic
120326ec324SPetar Jovanovic private:
markPhysRegUsed(unsigned PhysReg)121226e6117SPetar Jovanovic void markPhysRegUsed(unsigned PhysReg) override {
122326ec324SPetar Jovanovic MIB.addDef(PhysReg, RegState::Implicit);
123326ec324SPetar Jovanovic }
124326ec324SPetar Jovanovic
125326ec324SPetar Jovanovic MachineInstrBuilder &MIB;
126326ec324SPetar Jovanovic };
127326ec324SPetar Jovanovic
128366857a2SPetar Jovanovic } // end anonymous namespace
129366857a2SPetar Jovanovic
assignValueToReg(Register ValVReg,Register PhysReg,CCValAssign VA)1300c92bfa4SMatt Arsenault void MipsIncomingValueHandler::assignValueToReg(Register ValVReg,
131121541fdSMatt Arsenault Register PhysReg,
1328bde5e58SAmara Emerson CCValAssign VA) {
1335a457e08SPetar Avramovic markPhysRegUsed(PhysReg);
134121541fdSMatt Arsenault IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
1355a457e08SPetar Avramovic }
136366857a2SPetar Jovanovic
getStackAddress(uint64_t Size,int64_t Offset,MachinePointerInfo & MPO,ISD::ArgFlagsTy Flags)137121541fdSMatt Arsenault Register MipsIncomingValueHandler::getStackAddress(uint64_t Size,
138121541fdSMatt Arsenault int64_t Offset,
139121541fdSMatt Arsenault MachinePointerInfo &MPO,
140121541fdSMatt Arsenault ISD::ArgFlagsTy Flags) {
141121541fdSMatt Arsenault
1422a64598eSMatt Arsenault MachineFunction &MF = MIRBuilder.getMF();
1432a64598eSMatt Arsenault MachineFrameInfo &MFI = MF.getFrameInfo();
144226e6117SPetar Jovanovic
1456b76d828SMatt Arsenault // FIXME: This should only be immutable for non-byval memory arguments.
146226e6117SPetar Jovanovic int FI = MFI.CreateFixedObject(Size, Offset, true);
147121541fdSMatt Arsenault MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
148226e6117SPetar Jovanovic
1492a1b5af2SJay Foad return MIRBuilder.buildFrameIndex(LLT::pointer(0, 32), FI).getReg(0);
150226e6117SPetar Jovanovic }
151226e6117SPetar Jovanovic
assignValueToAddress(Register ValVReg,Register Addr,LLT MemTy,MachinePointerInfo & MPO,CCValAssign & VA)1520c92bfa4SMatt Arsenault void MipsIncomingValueHandler::assignValueToAddress(Register ValVReg,
153121541fdSMatt Arsenault Register Addr, LLT MemTy,
154121541fdSMatt Arsenault MachinePointerInfo &MPO,
155121541fdSMatt Arsenault CCValAssign &VA) {
156121541fdSMatt Arsenault MachineFunction &MF = MIRBuilder.getMF();
157121541fdSMatt Arsenault auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
158121541fdSMatt Arsenault inferAlignFromPtrInfo(MF, MPO));
159121541fdSMatt Arsenault MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
160226e6117SPetar Jovanovic }
161226e6117SPetar Jovanovic
162121541fdSMatt Arsenault /// Handle cases when f64 is split into 2 32-bit GPRs. This is a custom
163121541fdSMatt Arsenault /// assignment because generic code assumes getNumRegistersForCallingConv is
164121541fdSMatt Arsenault /// accurate. In this case it is not because the type/number are context
165121541fdSMatt Arsenault /// dependent on other arguments.
166121541fdSMatt Arsenault unsigned
assignCustomValue(CallLowering::ArgInfo & Arg,ArrayRef<CCValAssign> VAs,std::function<void ()> * Thunk)167121541fdSMatt Arsenault MipsIncomingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,
1688bde5e58SAmara Emerson ArrayRef<CCValAssign> VAs,
1698bde5e58SAmara Emerson std::function<void()> *Thunk) {
170121541fdSMatt Arsenault const CCValAssign &VALo = VAs[0];
171121541fdSMatt Arsenault const CCValAssign &VAHi = VAs[1];
172121541fdSMatt Arsenault
173121541fdSMatt Arsenault assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
174121541fdSMatt Arsenault VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
175121541fdSMatt Arsenault "unexpected custom value");
176121541fdSMatt Arsenault
177121541fdSMatt Arsenault auto CopyLo = MIRBuilder.buildCopy(LLT::scalar(32), VALo.getLocReg());
178121541fdSMatt Arsenault auto CopyHi = MIRBuilder.buildCopy(LLT::scalar(32), VAHi.getLocReg());
179121541fdSMatt Arsenault if (!STI.isLittle())
180121541fdSMatt Arsenault std::swap(CopyLo, CopyHi);
181121541fdSMatt Arsenault
182121541fdSMatt Arsenault Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
183121541fdSMatt Arsenault Arg.Regs = { CopyLo.getReg(0), CopyHi.getReg(0) };
184121541fdSMatt Arsenault MIRBuilder.buildMerge(Arg.OrigRegs[0], {CopyLo, CopyHi});
185121541fdSMatt Arsenault
186121541fdSMatt Arsenault markPhysRegUsed(VALo.getLocReg());
187121541fdSMatt Arsenault markPhysRegUsed(VAHi.getLocReg());
188121541fdSMatt Arsenault return 2;
189366857a2SPetar Jovanovic }
190366857a2SPetar Jovanovic
191366857a2SPetar Jovanovic namespace {
192121541fdSMatt Arsenault class MipsOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
193121541fdSMatt Arsenault const MipsSubtarget &STI;
194121541fdSMatt Arsenault
195366857a2SPetar Jovanovic public:
MipsOutgoingValueHandler(MachineIRBuilder & MIRBuilder,MachineRegisterInfo & MRI,MachineInstrBuilder & MIB)1960c92bfa4SMatt Arsenault MipsOutgoingValueHandler(MachineIRBuilder &MIRBuilder,
1970c92bfa4SMatt Arsenault MachineRegisterInfo &MRI, MachineInstrBuilder &MIB)
198121541fdSMatt Arsenault : OutgoingValueHandler(MIRBuilder, MRI),
199121541fdSMatt Arsenault STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()), MIB(MIB) {}
200366857a2SPetar Jovanovic
201366857a2SPetar Jovanovic private:
202121541fdSMatt Arsenault void assignValueToReg(Register ValVReg, Register PhysReg,
2038bde5e58SAmara Emerson CCValAssign VA) override;
204226e6117SPetar Jovanovic
205121541fdSMatt Arsenault Register getStackAddress(uint64_t Size, int64_t Offset,
206121541fdSMatt Arsenault MachinePointerInfo &MPO,
207121541fdSMatt Arsenault ISD::ArgFlagsTy Flags) override;
208226e6117SPetar Jovanovic
209121541fdSMatt Arsenault void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
210121541fdSMatt Arsenault MachinePointerInfo &MPO, CCValAssign &VA) override;
211121541fdSMatt Arsenault unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
2128bde5e58SAmara Emerson ArrayRef<CCValAssign> VAs,
2138bde5e58SAmara Emerson std::function<void()> *Thunk) override;
214366857a2SPetar Jovanovic
215366857a2SPetar Jovanovic MachineInstrBuilder &MIB;
216366857a2SPetar Jovanovic };
217366857a2SPetar Jovanovic } // end anonymous namespace
218366857a2SPetar Jovanovic
assignValueToReg(Register ValVReg,Register PhysReg,CCValAssign VA)2190c92bfa4SMatt Arsenault void MipsOutgoingValueHandler::assignValueToReg(Register ValVReg,
220121541fdSMatt Arsenault Register PhysReg,
2218bde5e58SAmara Emerson CCValAssign VA) {
222faeaedf8SMatt Arsenault Register ExtReg = extendRegister(ValVReg, VA);
22365d463bdSPetar Jovanovic MIRBuilder.buildCopy(PhysReg, ExtReg);
224366857a2SPetar Jovanovic MIB.addUse(PhysReg, RegState::Implicit);
225366857a2SPetar Jovanovic }
226366857a2SPetar Jovanovic
getStackAddress(uint64_t Size,int64_t Offset,MachinePointerInfo & MPO,ISD::ArgFlagsTy Flags)227121541fdSMatt Arsenault Register MipsOutgoingValueHandler::getStackAddress(uint64_t Size,
228121541fdSMatt Arsenault int64_t Offset,
229121541fdSMatt Arsenault MachinePointerInfo &MPO,
230121541fdSMatt Arsenault ISD::ArgFlagsTy Flags) {
2312a64598eSMatt Arsenault MachineFunction &MF = MIRBuilder.getMF();
232121541fdSMatt Arsenault MPO = MachinePointerInfo::getStack(MF, Offset);
2332a64598eSMatt Arsenault
234226e6117SPetar Jovanovic LLT p0 = LLT::pointer(0, 32);
235226e6117SPetar Jovanovic LLT s32 = LLT::scalar(32);
2362a1b5af2SJay Foad auto SPReg = MIRBuilder.buildCopy(p0, Register(Mips::SP));
237226e6117SPetar Jovanovic
2382a1b5af2SJay Foad auto OffsetReg = MIRBuilder.buildConstant(s32, Offset);
2392a1b5af2SJay Foad auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
2402a1b5af2SJay Foad return AddrReg.getReg(0);
241226e6117SPetar Jovanovic }
242226e6117SPetar Jovanovic
assignValueToAddress(Register ValVReg,Register Addr,LLT MemTy,MachinePointerInfo & MPO,CCValAssign & VA)2430c92bfa4SMatt Arsenault void MipsOutgoingValueHandler::assignValueToAddress(Register ValVReg,
244121541fdSMatt Arsenault Register Addr, LLT MemTy,
245121541fdSMatt Arsenault MachinePointerInfo &MPO,
246121541fdSMatt Arsenault CCValAssign &VA) {
247121541fdSMatt Arsenault MachineFunction &MF = MIRBuilder.getMF();
248121541fdSMatt Arsenault uint64_t LocMemOffset = VA.getLocMemOffset();
249121541fdSMatt Arsenault
250121541fdSMatt Arsenault auto MMO = MF.getMachineMemOperand(
251121541fdSMatt Arsenault MPO, MachineMemOperand::MOStore, MemTy,
252121541fdSMatt Arsenault commonAlignment(STI.getStackAlignment(), LocMemOffset));
253121541fdSMatt Arsenault
254faeaedf8SMatt Arsenault Register ExtReg = extendRegister(ValVReg, VA);
25565d463bdSPetar Jovanovic MIRBuilder.buildStore(ExtReg, Addr, *MMO);
25665d463bdSPetar Jovanovic }
25765d463bdSPetar Jovanovic
258121541fdSMatt Arsenault unsigned
assignCustomValue(CallLowering::ArgInfo & Arg,ArrayRef<CCValAssign> VAs,std::function<void ()> * Thunk)259121541fdSMatt Arsenault MipsOutgoingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,
2608bde5e58SAmara Emerson ArrayRef<CCValAssign> VAs,
2618bde5e58SAmara Emerson std::function<void()> *Thunk) {
262121541fdSMatt Arsenault const CCValAssign &VALo = VAs[0];
263121541fdSMatt Arsenault const CCValAssign &VAHi = VAs[1];
264226e6117SPetar Jovanovic
265121541fdSMatt Arsenault assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
266121541fdSMatt Arsenault VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
267121541fdSMatt Arsenault "unexpected custom value");
268ff1bc621SPetar Jovanovic
269121541fdSMatt Arsenault auto Unmerge =
270121541fdSMatt Arsenault MIRBuilder.buildUnmerge({LLT::scalar(32), LLT::scalar(32)}, Arg.Regs[0]);
271121541fdSMatt Arsenault Register Lo = Unmerge.getReg(0);
272121541fdSMatt Arsenault Register Hi = Unmerge.getReg(1);
273121541fdSMatt Arsenault
274121541fdSMatt Arsenault Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
275121541fdSMatt Arsenault Arg.Regs = { Lo, Hi };
276121541fdSMatt Arsenault if (!STI.isLittle())
277121541fdSMatt Arsenault std::swap(Lo, Hi);
278121541fdSMatt Arsenault
2798bde5e58SAmara Emerson // If we can return a thunk, just include the register copies. The unmerge can
2808bde5e58SAmara Emerson // be emitted earlier.
2818bde5e58SAmara Emerson if (Thunk) {
2828bde5e58SAmara Emerson *Thunk = [=]() {
2838bde5e58SAmara Emerson MIRBuilder.buildCopy(VALo.getLocReg(), Lo);
2848bde5e58SAmara Emerson MIRBuilder.buildCopy(VAHi.getLocReg(), Hi);
2858bde5e58SAmara Emerson };
2868bde5e58SAmara Emerson return 2;
2878bde5e58SAmara Emerson }
288121541fdSMatt Arsenault MIRBuilder.buildCopy(VALo.getLocReg(), Lo);
289121541fdSMatt Arsenault MIRBuilder.buildCopy(VAHi.getLocReg(), Hi);
290121541fdSMatt Arsenault return 2;
291366857a2SPetar Jovanovic }
292366857a2SPetar Jovanovic
isSupportedArgumentType(Type * T)293ed305191SPetar Avramovic static bool isSupportedArgumentType(Type *T) {
294ff1bc621SPetar Jovanovic if (T->isIntegerTy())
295366857a2SPetar Jovanovic return true;
29658c02100SPetar Jovanovic if (T->isPointerTy())
29758c02100SPetar Jovanovic return true;
2985a457e08SPetar Avramovic if (T->isFloatingPointTy())
2995a457e08SPetar Avramovic return true;
300366857a2SPetar Jovanovic return false;
301366857a2SPetar Jovanovic }
302366857a2SPetar Jovanovic
isSupportedReturnType(Type * T)303ed305191SPetar Avramovic static bool isSupportedReturnType(Type *T) {
304ed305191SPetar Avramovic if (T->isIntegerTy())
305ed305191SPetar Avramovic return true;
306ed305191SPetar Avramovic if (T->isPointerTy())
307ed305191SPetar Avramovic return true;
308ed305191SPetar Avramovic if (T->isFloatingPointTy())
309ed305191SPetar Avramovic return true;
310ed305191SPetar Avramovic if (T->isAggregateType())
311ed305191SPetar Avramovic return true;
312ed305191SPetar Avramovic return false;
313ed305191SPetar Avramovic }
314ed305191SPetar Avramovic
lowerReturn(MachineIRBuilder & MIRBuilder,const Value * Val,ArrayRef<Register> VRegs,FunctionLoweringInfo & FLI) const315fac93e28SPetar Jovanovic bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
316d68458bdSChristudasan Devadasan const Value *Val, ArrayRef<Register> VRegs,
317d68458bdSChristudasan Devadasan FunctionLoweringInfo &FLI) const {
318fac93e28SPetar Jovanovic
319fac93e28SPetar Jovanovic MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
320fac93e28SPetar Jovanovic
321ed305191SPetar Avramovic if (Val != nullptr && !isSupportedReturnType(Val->getType()))
322fac93e28SPetar Jovanovic return false;
323366857a2SPetar Jovanovic
32449168f67SAlexander Ivchenko if (!VRegs.empty()) {
325366857a2SPetar Jovanovic MachineFunction &MF = MIRBuilder.getMF();
326366857a2SPetar Jovanovic const Function &F = MF.getFunction();
327366857a2SPetar Jovanovic const DataLayout &DL = MF.getDataLayout();
328366857a2SPetar Jovanovic const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
329366857a2SPetar Jovanovic
330366857a2SPetar Jovanovic SmallVector<ArgInfo, 8> RetInfos;
331366857a2SPetar Jovanovic
332121541fdSMatt Arsenault ArgInfo ArgRetInfo(VRegs, *Val, 0);
333ed305191SPetar Avramovic setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);
33443f25e61SMatt Arsenault splitToValueTypes(ArgRetInfo, RetInfos, DL, F.getCallingConv());
335366857a2SPetar Jovanovic
336366857a2SPetar Jovanovic SmallVector<CCValAssign, 16> ArgLocs;
337121541fdSMatt Arsenault SmallVector<ISD::OutputArg, 8> Outs;
338121541fdSMatt Arsenault
339366857a2SPetar Jovanovic MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
340366857a2SPetar Jovanovic F.getContext());
341366857a2SPetar Jovanovic
3420c92bfa4SMatt Arsenault MipsOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
343121541fdSMatt Arsenault std::string FuncName = F.getName().str();
344121541fdSMatt Arsenault MipsOutgoingValueAssigner Assigner(TLI.CCAssignFnForReturn(),
345121541fdSMatt Arsenault FuncName.c_str(), /*IsReturn*/ true);
346121541fdSMatt Arsenault
347121541fdSMatt Arsenault if (!determineAssignments(Assigner, RetInfos, CCInfo))
348121541fdSMatt Arsenault return false;
349121541fdSMatt Arsenault
350121541fdSMatt Arsenault if (!handleAssignments(RetHandler, RetInfos, CCInfo, ArgLocs, MIRBuilder))
351366857a2SPetar Jovanovic return false;
352366857a2SPetar Jovanovic }
353121541fdSMatt Arsenault
354fac93e28SPetar Jovanovic MIRBuilder.insertInstr(Ret);
355fac93e28SPetar Jovanovic return true;
356fac93e28SPetar Jovanovic }
357fac93e28SPetar Jovanovic
lowerFormalArguments(MachineIRBuilder & MIRBuilder,const Function & F,ArrayRef<ArrayRef<Register>> VRegs,FunctionLoweringInfo & FLI) const358d68458bdSChristudasan Devadasan bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
359d68458bdSChristudasan Devadasan const Function &F,
360d68458bdSChristudasan Devadasan ArrayRef<ArrayRef<Register>> VRegs,
361d68458bdSChristudasan Devadasan FunctionLoweringInfo &FLI) const {
362fac93e28SPetar Jovanovic
363fac93e28SPetar Jovanovic // Quick exit if there aren't any args.
364fac93e28SPetar Jovanovic if (F.arg_empty())
365fac93e28SPetar Jovanovic return true;
366fac93e28SPetar Jovanovic
367366857a2SPetar Jovanovic for (auto &Arg : F.args()) {
368ed305191SPetar Avramovic if (!isSupportedArgumentType(Arg.getType()))
369366857a2SPetar Jovanovic return false;
370366857a2SPetar Jovanovic }
371366857a2SPetar Jovanovic
372366857a2SPetar Jovanovic MachineFunction &MF = MIRBuilder.getMF();
373366857a2SPetar Jovanovic const DataLayout &DL = MF.getDataLayout();
374366857a2SPetar Jovanovic const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
375366857a2SPetar Jovanovic
376366857a2SPetar Jovanovic SmallVector<ArgInfo, 8> ArgInfos;
377366857a2SPetar Jovanovic unsigned i = 0;
378366857a2SPetar Jovanovic for (auto &Arg : F.args()) {
379121541fdSMatt Arsenault ArgInfo AInfo(VRegs[i], Arg, i);
380366857a2SPetar Jovanovic setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);
381121541fdSMatt Arsenault
382121541fdSMatt Arsenault splitToValueTypes(AInfo, ArgInfos, DL, F.getCallingConv());
383366857a2SPetar Jovanovic ++i;
384366857a2SPetar Jovanovic }
385366857a2SPetar Jovanovic
386366857a2SPetar Jovanovic SmallVector<ISD::InputArg, 8> Ins;
387366857a2SPetar Jovanovic
388366857a2SPetar Jovanovic SmallVector<CCValAssign, 16> ArgLocs;
389366857a2SPetar Jovanovic MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
390366857a2SPetar Jovanovic F.getContext());
391366857a2SPetar Jovanovic
392226e6117SPetar Jovanovic const MipsTargetMachine &TM =
393226e6117SPetar Jovanovic static_cast<const MipsTargetMachine &>(MF.getTarget());
394226e6117SPetar Jovanovic const MipsABIInfo &ABI = TM.getABI();
395226e6117SPetar Jovanovic CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()),
3961778564fSGuillaume Chatelet Align(1));
397121541fdSMatt Arsenault
398121541fdSMatt Arsenault const std::string FuncName = F.getName().str();
399121541fdSMatt Arsenault MipsIncomingValueAssigner Assigner(TLI.CCAssignFnForCall(), FuncName.c_str(),
400121541fdSMatt Arsenault /*IsReturn*/ false);
401121541fdSMatt Arsenault if (!determineAssignments(Assigner, ArgInfos, CCInfo))
402121541fdSMatt Arsenault return false;
403366857a2SPetar Jovanovic
4040c92bfa4SMatt Arsenault MipsIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
405121541fdSMatt Arsenault if (!handleAssignments(Handler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))
406366857a2SPetar Jovanovic return false;
407366857a2SPetar Jovanovic
408c063b0b0SPetar Avramovic if (F.isVarArg()) {
409c063b0b0SPetar Avramovic ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs();
410c063b0b0SPetar Avramovic unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
411c063b0b0SPetar Avramovic
412c063b0b0SPetar Avramovic int VaArgOffset;
413c063b0b0SPetar Avramovic unsigned RegSize = 4;
414c063b0b0SPetar Avramovic if (ArgRegs.size() == Idx)
415c063b0b0SPetar Avramovic VaArgOffset = alignTo(CCInfo.getNextStackOffset(), RegSize);
416c063b0b0SPetar Avramovic else {
417c063b0b0SPetar Avramovic VaArgOffset =
418c063b0b0SPetar Avramovic (int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) -
419c063b0b0SPetar Avramovic (int)(RegSize * (ArgRegs.size() - Idx));
420c063b0b0SPetar Avramovic }
421c063b0b0SPetar Avramovic
422c063b0b0SPetar Avramovic MachineFrameInfo &MFI = MF.getFrameInfo();
423c063b0b0SPetar Avramovic int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
424c063b0b0SPetar Avramovic MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI);
425c063b0b0SPetar Avramovic
426c063b0b0SPetar Avramovic for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) {
427c063b0b0SPetar Avramovic MIRBuilder.getMBB().addLiveIn(ArgRegs[I]);
4289ad1a499SMatt Arsenault LLT RegTy = LLT::scalar(RegSize * 8);
429c063b0b0SPetar Avramovic MachineInstrBuilder Copy =
4309ad1a499SMatt Arsenault MIRBuilder.buildCopy(RegTy, Register(ArgRegs[I]));
431c063b0b0SPetar Avramovic FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
432c063b0b0SPetar Avramovic MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI);
4339ad1a499SMatt Arsenault
4349ad1a499SMatt Arsenault const LLT PtrTy = LLT::pointer(MPO.getAddrSpace(), 32);
4359ad1a499SMatt Arsenault auto FrameIndex = MIRBuilder.buildFrameIndex(PtrTy, FI);
436c9d5c195SGuillaume Chatelet MachineMemOperand *MMO = MF.getMachineMemOperand(
4379ad1a499SMatt Arsenault MPO, MachineMemOperand::MOStore, RegTy, Align(RegSize));
438c063b0b0SPetar Avramovic MIRBuilder.buildStore(Copy, FrameIndex, *MMO);
439c063b0b0SPetar Avramovic }
440c063b0b0SPetar Avramovic }
441c063b0b0SPetar Avramovic
442366857a2SPetar Jovanovic return true;
443366857a2SPetar Jovanovic }
444366857a2SPetar Jovanovic
lowerCall(MachineIRBuilder & MIRBuilder,CallLoweringInfo & Info) const445326ec324SPetar Jovanovic bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
446e1a5f668STim Northover CallLoweringInfo &Info) const {
447326ec324SPetar Jovanovic
448e1a5f668STim Northover if (Info.CallConv != CallingConv::C)
449326ec324SPetar Jovanovic return false;
450326ec324SPetar Jovanovic
451e1a5f668STim Northover for (auto &Arg : Info.OrigArgs) {
452ed305191SPetar Avramovic if (!isSupportedArgumentType(Arg.Ty))
453326ec324SPetar Jovanovic return false;
454d2574d79SPetar Avramovic if (Arg.Flags[0].isByVal())
455d2574d79SPetar Avramovic return false;
456d2574d79SPetar Avramovic if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy())
457326ec324SPetar Jovanovic return false;
458326ec324SPetar Jovanovic }
45969ce1c13SDiana Picus
460ed305191SPetar Avramovic if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(Info.OrigRet.Ty))
461326ec324SPetar Jovanovic return false;
462326ec324SPetar Jovanovic
463326ec324SPetar Jovanovic MachineFunction &MF = MIRBuilder.getMF();
464326ec324SPetar Jovanovic const Function &F = MF.getFunction();
465ed305191SPetar Avramovic const DataLayout &DL = MF.getDataLayout();
466326ec324SPetar Jovanovic const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
467326ec324SPetar Jovanovic const MipsTargetMachine &TM =
468326ec324SPetar Jovanovic static_cast<const MipsTargetMachine &>(MF.getTarget());
469326ec324SPetar Jovanovic const MipsABIInfo &ABI = TM.getABI();
470326ec324SPetar Jovanovic
471326ec324SPetar Jovanovic MachineInstrBuilder CallSeqStart =
472326ec324SPetar Jovanovic MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN);
473326ec324SPetar Jovanovic
474efcd3c00SPetar Avramovic const bool IsCalleeGlobalPIC =
475e1a5f668STim Northover Info.Callee.isGlobal() && TM.isPositionIndependent();
476efcd3c00SPetar Avramovic
477f4a6dd28SPetar Avramovic MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(
478e1a5f668STim Northover Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL);
479326ec324SPetar Jovanovic MIB.addDef(Mips::SP, RegState::Implicit);
480efcd3c00SPetar Avramovic if (IsCalleeGlobalPIC) {
481faeaedf8SMatt Arsenault Register CalleeReg =
482efcd3c00SPetar Avramovic MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32));
483efcd3c00SPetar Avramovic MachineInstr *CalleeGlobalValue =
484e1a5f668STim Northover MIRBuilder.buildGlobalValue(CalleeReg, Info.Callee.getGlobal());
485e1a5f668STim Northover if (!Info.Callee.getGlobal()->hasLocalLinkage())
486efcd3c00SPetar Avramovic CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL);
487efcd3c00SPetar Avramovic MIB.addUse(CalleeReg);
488efcd3c00SPetar Avramovic } else
489e1a5f668STim Northover MIB.add(Info.Callee);
490326ec324SPetar Jovanovic const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
4912f9504aaSMatt Arsenault MIB.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
492326ec324SPetar Jovanovic
493326ec324SPetar Jovanovic TargetLowering::ArgListTy FuncOrigArgs;
494e1a5f668STim Northover FuncOrigArgs.reserve(Info.OrigArgs.size());
495326ec324SPetar Jovanovic
496326ec324SPetar Jovanovic SmallVector<ArgInfo, 8> ArgInfos;
497121541fdSMatt Arsenault for (auto &Arg : Info.OrigArgs)
498121541fdSMatt Arsenault splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv);
499326ec324SPetar Jovanovic
500326ec324SPetar Jovanovic SmallVector<CCValAssign, 8> ArgLocs;
501c063b0b0SPetar Avramovic bool IsCalleeVarArg = false;
502c063b0b0SPetar Avramovic if (Info.Callee.isGlobal()) {
503c063b0b0SPetar Avramovic const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal());
504c063b0b0SPetar Avramovic IsCalleeVarArg = CF->isVarArg();
505c063b0b0SPetar Avramovic }
506121541fdSMatt Arsenault
507121541fdSMatt Arsenault // FIXME: Should use MipsCCState::getSpecialCallingConvForCallee, but it
508121541fdSMatt Arsenault // depends on looking directly at the call target.
5092f9504aaSMatt Arsenault MipsCCState CCInfo(Info.CallConv, IsCalleeVarArg, MF, ArgLocs,
510326ec324SPetar Jovanovic F.getContext());
511326ec324SPetar Jovanovic
5121778564fSGuillaume Chatelet CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv),
5131778564fSGuillaume Chatelet Align(1));
514121541fdSMatt Arsenault
515e1a5f668STim Northover const char *Call =
516e1a5f668STim Northover Info.Callee.isSymbol() ? Info.Callee.getSymbolName() : nullptr;
517326ec324SPetar Jovanovic
518121541fdSMatt Arsenault MipsOutgoingValueAssigner Assigner(TLI.CCAssignFnForCall(), Call,
519121541fdSMatt Arsenault /*IsReturn*/ false);
520121541fdSMatt Arsenault if (!determineAssignments(Assigner, ArgInfos, CCInfo))
521326ec324SPetar Jovanovic return false;
522121541fdSMatt Arsenault
523121541fdSMatt Arsenault MipsOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), MIB);
524121541fdSMatt Arsenault if (!handleAssignments(ArgHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))
525121541fdSMatt Arsenault return false;
526326ec324SPetar Jovanovic
527226e6117SPetar Jovanovic unsigned NextStackOffset = CCInfo.getNextStackOffset();
5283787ee45SNick Desaulniers unsigned StackAlignment = F.getParent()->getOverrideStackAlignment();
5293787ee45SNick Desaulniers if (!StackAlignment) {
530226e6117SPetar Jovanovic const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
5313787ee45SNick Desaulniers StackAlignment = TFL->getStackAlignment();
5323787ee45SNick Desaulniers }
533226e6117SPetar Jovanovic NextStackOffset = alignTo(NextStackOffset, StackAlignment);
534226e6117SPetar Jovanovic CallSeqStart.addImm(NextStackOffset).addImm(0);
535226e6117SPetar Jovanovic
536efcd3c00SPetar Avramovic if (IsCalleeGlobalPIC) {
537efcd3c00SPetar Avramovic MIRBuilder.buildCopy(
538faeaedf8SMatt Arsenault Register(Mips::GP),
539669bb311SMatt Arsenault MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel(MF));
540efcd3c00SPetar Avramovic MIB.addDef(Mips::GP, RegState::Implicit);
541efcd3c00SPetar Avramovic }
542326ec324SPetar Jovanovic MIRBuilder.insertInstr(MIB);
543f4a6dd28SPetar Avramovic if (MIB->getOpcode() == Mips::JALRPseudo) {
544*ad73ce31SZongwei Lan const MipsSubtarget &STI = MIRBuilder.getMF().getSubtarget<MipsSubtarget>();
545f4a6dd28SPetar Avramovic MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(),
546f4a6dd28SPetar Avramovic *STI.getRegBankInfo());
547f4a6dd28SPetar Avramovic }
548326ec324SPetar Jovanovic
549e1a5f668STim Northover if (!Info.OrigRet.Ty->isVoidTy()) {
550326ec324SPetar Jovanovic ArgInfos.clear();
551326ec324SPetar Jovanovic
552121541fdSMatt Arsenault CallLowering::splitToValueTypes(Info.OrigRet, ArgInfos, DL,
553121541fdSMatt Arsenault F.getCallingConv());
554121541fdSMatt Arsenault
555121541fdSMatt Arsenault const std::string FuncName = F.getName().str();
556326ec324SPetar Jovanovic SmallVector<ISD::InputArg, 8> Ins;
557326ec324SPetar Jovanovic SmallVector<CCValAssign, 8> ArgLocs;
558121541fdSMatt Arsenault MipsIncomingValueAssigner Assigner(TLI.CCAssignFnForReturn(),
559121541fdSMatt Arsenault FuncName.c_str(),
560121541fdSMatt Arsenault /*IsReturn*/ true);
561121541fdSMatt Arsenault CallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);
562121541fdSMatt Arsenault
563121541fdSMatt Arsenault MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
564326ec324SPetar Jovanovic F.getContext());
565326ec324SPetar Jovanovic
566121541fdSMatt Arsenault if (!determineAssignments(Assigner, ArgInfos, CCInfo))
567121541fdSMatt Arsenault return false;
568326ec324SPetar Jovanovic
569121541fdSMatt Arsenault if (!handleAssignments(RetHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))
570326ec324SPetar Jovanovic return false;
571326ec324SPetar Jovanovic }
572326ec324SPetar Jovanovic
573226e6117SPetar Jovanovic MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0);
574326ec324SPetar Jovanovic
575326ec324SPetar Jovanovic return true;
576326ec324SPetar Jovanovic }
577