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