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" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace llvm; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) 250b57cec5SDimitry Andric : CallLowering(&TLI) {} 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric bool MipsCallLowering::MipsHandler::assign(Register VReg, const CCValAssign &VA, 280b57cec5SDimitry Andric const EVT &VT) { 290b57cec5SDimitry Andric if (VA.isRegLoc()) { 300b57cec5SDimitry Andric assignValueToReg(VReg, VA, VT); 310b57cec5SDimitry Andric } else if (VA.isMemLoc()) { 320b57cec5SDimitry Andric assignValueToAddress(VReg, VA); 330b57cec5SDimitry Andric } else { 340b57cec5SDimitry Andric return false; 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric return true; 370b57cec5SDimitry Andric } 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef<Register> VRegs, 400b57cec5SDimitry Andric ArrayRef<CCValAssign> ArgLocs, 410b57cec5SDimitry Andric unsigned ArgLocsStartIndex, 420b57cec5SDimitry Andric const EVT &VT) { 430b57cec5SDimitry Andric for (unsigned i = 0; i < VRegs.size(); ++i) 440b57cec5SDimitry Andric if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i], VT)) 450b57cec5SDimitry Andric return false; 460b57cec5SDimitry Andric return true; 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric void MipsCallLowering::MipsHandler::setLeastSignificantFirst( 500b57cec5SDimitry Andric SmallVectorImpl<Register> &VRegs) { 510b57cec5SDimitry Andric if (!MIRBuilder.getMF().getDataLayout().isLittleEndian()) 520b57cec5SDimitry Andric std::reverse(VRegs.begin(), VRegs.end()); 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric bool MipsCallLowering::MipsHandler::handle( 560b57cec5SDimitry Andric ArrayRef<CCValAssign> ArgLocs, ArrayRef<CallLowering::ArgInfo> Args) { 570b57cec5SDimitry Andric SmallVector<Register, 4> VRegs; 580b57cec5SDimitry Andric unsigned SplitLength; 590b57cec5SDimitry Andric const Function &F = MIRBuilder.getMF().getFunction(); 600b57cec5SDimitry Andric const DataLayout &DL = F.getParent()->getDataLayout(); 610b57cec5SDimitry Andric const MipsTargetLowering &TLI = *static_cast<const MipsTargetLowering *>( 620b57cec5SDimitry Andric MIRBuilder.getMF().getSubtarget().getTargetLowering()); 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric for (unsigned ArgsIndex = 0, ArgLocsIndex = 0; ArgsIndex < Args.size(); 650b57cec5SDimitry Andric ++ArgsIndex, ArgLocsIndex += SplitLength) { 660b57cec5SDimitry Andric EVT VT = TLI.getValueType(DL, Args[ArgsIndex].Ty); 670b57cec5SDimitry Andric SplitLength = TLI.getNumRegistersForCallingConv(F.getContext(), 680b57cec5SDimitry Andric F.getCallingConv(), VT); 690b57cec5SDimitry Andric assert(Args[ArgsIndex].Regs.size() == 1 && "Can't handle multple regs yet"); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric if (SplitLength > 1) { 720b57cec5SDimitry Andric VRegs.clear(); 730b57cec5SDimitry Andric MVT RegisterVT = TLI.getRegisterTypeForCallingConv( 740b57cec5SDimitry Andric F.getContext(), F.getCallingConv(), VT); 750b57cec5SDimitry Andric for (unsigned i = 0; i < SplitLength; ++i) 760b57cec5SDimitry Andric VRegs.push_back(MRI.createGenericVirtualRegister(LLT{RegisterVT})); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Regs[0], 790b57cec5SDimitry Andric VT)) 800b57cec5SDimitry Andric return false; 810b57cec5SDimitry Andric } else { 820b57cec5SDimitry Andric if (!assign(Args[ArgsIndex].Regs[0], ArgLocs[ArgLocsIndex], VT)) 830b57cec5SDimitry Andric return false; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric return true; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric namespace { 900b57cec5SDimitry Andric class IncomingValueHandler : public MipsCallLowering::MipsHandler { 910b57cec5SDimitry Andric public: 920b57cec5SDimitry Andric IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) 930b57cec5SDimitry Andric : MipsHandler(MIRBuilder, MRI) {} 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric private: 960b57cec5SDimitry Andric void assignValueToReg(Register ValVReg, const CCValAssign &VA, 970b57cec5SDimitry Andric const EVT &VT) override; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric Register getStackAddress(const CCValAssign &VA, 1000b57cec5SDimitry Andric MachineMemOperand *&MMO) override; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric bool handleSplit(SmallVectorImpl<Register> &VRegs, 1050b57cec5SDimitry Andric ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, 1060b57cec5SDimitry Andric Register ArgsReg, const EVT &VT) override; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric virtual void markPhysRegUsed(unsigned PhysReg) { 109*8bcb0991SDimitry Andric MIRBuilder.getMRI()->addLiveIn(PhysReg); 1100b57cec5SDimitry Andric MIRBuilder.getMBB().addLiveIn(PhysReg); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric void buildLoad(Register Val, const CCValAssign &VA) { 1140b57cec5SDimitry Andric MachineMemOperand *MMO; 1150b57cec5SDimitry Andric Register Addr = getStackAddress(VA, MMO); 1160b57cec5SDimitry Andric MIRBuilder.buildLoad(Val, Addr, *MMO); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric }; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric class CallReturnHandler : public IncomingValueHandler { 1210b57cec5SDimitry Andric public: 1220b57cec5SDimitry Andric CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 1230b57cec5SDimitry Andric MachineInstrBuilder &MIB) 1240b57cec5SDimitry Andric : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric private: 1270b57cec5SDimitry Andric void markPhysRegUsed(unsigned PhysReg) override { 1280b57cec5SDimitry Andric MIB.addDef(PhysReg, RegState::Implicit); 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric MachineInstrBuilder &MIB; 1320b57cec5SDimitry Andric }; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric } // end anonymous namespace 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric void IncomingValueHandler::assignValueToReg(Register ValVReg, 1370b57cec5SDimitry Andric const CCValAssign &VA, 1380b57cec5SDimitry Andric const EVT &VT) { 1390b57cec5SDimitry Andric const MipsSubtarget &STI = 1400b57cec5SDimitry Andric static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); 1410b57cec5SDimitry Andric Register PhysReg = VA.getLocReg(); 1420b57cec5SDimitry Andric if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { 1430b57cec5SDimitry Andric const MipsSubtarget &STI = 1440b57cec5SDimitry Andric static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric MIRBuilder 1470b57cec5SDimitry Andric .buildInstr(STI.isFP64bit() ? Mips::BuildPairF64_64 1480b57cec5SDimitry Andric : Mips::BuildPairF64) 1490b57cec5SDimitry Andric .addDef(ValVReg) 1500b57cec5SDimitry Andric .addUse(PhysReg + (STI.isLittle() ? 0 : 1)) 1510b57cec5SDimitry Andric .addUse(PhysReg + (STI.isLittle() ? 1 : 0)) 1520b57cec5SDimitry Andric .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), 1530b57cec5SDimitry Andric *STI.getRegBankInfo()); 1540b57cec5SDimitry Andric markPhysRegUsed(PhysReg); 1550b57cec5SDimitry Andric markPhysRegUsed(PhysReg + 1); 1560b57cec5SDimitry Andric } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { 1570b57cec5SDimitry Andric MIRBuilder.buildInstr(Mips::MTC1) 1580b57cec5SDimitry Andric .addDef(ValVReg) 1590b57cec5SDimitry Andric .addUse(PhysReg) 1600b57cec5SDimitry Andric .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), 1610b57cec5SDimitry Andric *STI.getRegBankInfo()); 1620b57cec5SDimitry Andric markPhysRegUsed(PhysReg); 1630b57cec5SDimitry Andric } else { 1640b57cec5SDimitry Andric switch (VA.getLocInfo()) { 1650b57cec5SDimitry Andric case CCValAssign::LocInfo::SExt: 1660b57cec5SDimitry Andric case CCValAssign::LocInfo::ZExt: 1670b57cec5SDimitry Andric case CCValAssign::LocInfo::AExt: { 1680b57cec5SDimitry Andric auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); 1690b57cec5SDimitry Andric MIRBuilder.buildTrunc(ValVReg, Copy); 1700b57cec5SDimitry Andric break; 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric default: 1730b57cec5SDimitry Andric MIRBuilder.buildCopy(ValVReg, PhysReg); 1740b57cec5SDimitry Andric break; 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric markPhysRegUsed(PhysReg); 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric Register IncomingValueHandler::getStackAddress(const CCValAssign &VA, 1810b57cec5SDimitry Andric MachineMemOperand *&MMO) { 1820b57cec5SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 1830b57cec5SDimitry Andric unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; 1840b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset(); 1850b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric int FI = MFI.CreateFixedObject(Size, Offset, true); 1880b57cec5SDimitry Andric MachinePointerInfo MPO = 1890b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); 1920b57cec5SDimitry Andric unsigned Align = MinAlign(TFL->getStackAlignment(), Offset); 1930b57cec5SDimitry Andric MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, Size, Align); 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric Register AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); 1960b57cec5SDimitry Andric MIRBuilder.buildFrameIndex(AddrReg, FI); 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric return AddrReg; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric void IncomingValueHandler::assignValueToAddress(Register ValVReg, 2020b57cec5SDimitry Andric const CCValAssign &VA) { 2030b57cec5SDimitry Andric if (VA.getLocInfo() == CCValAssign::SExt || 2040b57cec5SDimitry Andric VA.getLocInfo() == CCValAssign::ZExt || 2050b57cec5SDimitry Andric VA.getLocInfo() == CCValAssign::AExt) { 2060b57cec5SDimitry Andric Register LoadReg = MRI.createGenericVirtualRegister(LLT::scalar(32)); 2070b57cec5SDimitry Andric buildLoad(LoadReg, VA); 2080b57cec5SDimitry Andric MIRBuilder.buildTrunc(ValVReg, LoadReg); 2090b57cec5SDimitry Andric } else 2100b57cec5SDimitry Andric buildLoad(ValVReg, VA); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric bool IncomingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs, 2140b57cec5SDimitry Andric ArrayRef<CCValAssign> ArgLocs, 2150b57cec5SDimitry Andric unsigned ArgLocsStartIndex, 2160b57cec5SDimitry Andric Register ArgsReg, const EVT &VT) { 2170b57cec5SDimitry Andric if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) 2180b57cec5SDimitry Andric return false; 2190b57cec5SDimitry Andric setLeastSignificantFirst(VRegs); 2200b57cec5SDimitry Andric MIRBuilder.buildMerge(ArgsReg, VRegs); 2210b57cec5SDimitry Andric return true; 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric namespace { 2250b57cec5SDimitry Andric class OutgoingValueHandler : public MipsCallLowering::MipsHandler { 2260b57cec5SDimitry Andric public: 2270b57cec5SDimitry Andric OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 2280b57cec5SDimitry Andric MachineInstrBuilder &MIB) 2290b57cec5SDimitry Andric : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric private: 2320b57cec5SDimitry Andric void assignValueToReg(Register ValVReg, const CCValAssign &VA, 2330b57cec5SDimitry Andric const EVT &VT) override; 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric Register getStackAddress(const CCValAssign &VA, 2360b57cec5SDimitry Andric MachineMemOperand *&MMO) override; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric bool handleSplit(SmallVectorImpl<Register> &VRegs, 2410b57cec5SDimitry Andric ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, 2420b57cec5SDimitry Andric Register ArgsReg, const EVT &VT) override; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric Register extendRegister(Register ValReg, const CCValAssign &VA); 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric MachineInstrBuilder &MIB; 2470b57cec5SDimitry Andric }; 2480b57cec5SDimitry Andric } // end anonymous namespace 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric void OutgoingValueHandler::assignValueToReg(Register ValVReg, 2510b57cec5SDimitry Andric const CCValAssign &VA, 2520b57cec5SDimitry Andric const EVT &VT) { 2530b57cec5SDimitry Andric Register PhysReg = VA.getLocReg(); 2540b57cec5SDimitry Andric const MipsSubtarget &STI = 2550b57cec5SDimitry Andric static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { 2580b57cec5SDimitry Andric MIRBuilder 2590b57cec5SDimitry Andric .buildInstr(STI.isFP64bit() ? Mips::ExtractElementF64_64 2600b57cec5SDimitry Andric : Mips::ExtractElementF64) 2610b57cec5SDimitry Andric .addDef(PhysReg + (STI.isLittle() ? 1 : 0)) 2620b57cec5SDimitry Andric .addUse(ValVReg) 2630b57cec5SDimitry Andric .addImm(1) 2640b57cec5SDimitry Andric .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), 2650b57cec5SDimitry Andric *STI.getRegBankInfo()); 2660b57cec5SDimitry Andric MIRBuilder 2670b57cec5SDimitry Andric .buildInstr(STI.isFP64bit() ? Mips::ExtractElementF64_64 2680b57cec5SDimitry Andric : Mips::ExtractElementF64) 2690b57cec5SDimitry Andric .addDef(PhysReg + (STI.isLittle() ? 0 : 1)) 2700b57cec5SDimitry Andric .addUse(ValVReg) 2710b57cec5SDimitry Andric .addImm(0) 2720b57cec5SDimitry Andric .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), 2730b57cec5SDimitry Andric *STI.getRegBankInfo()); 2740b57cec5SDimitry Andric } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { 2750b57cec5SDimitry Andric MIRBuilder.buildInstr(Mips::MFC1) 2760b57cec5SDimitry Andric .addDef(PhysReg) 2770b57cec5SDimitry Andric .addUse(ValVReg) 2780b57cec5SDimitry Andric .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), 2790b57cec5SDimitry Andric *STI.getRegBankInfo()); 2800b57cec5SDimitry Andric } else { 2810b57cec5SDimitry Andric Register ExtReg = extendRegister(ValVReg, VA); 2820b57cec5SDimitry Andric MIRBuilder.buildCopy(PhysReg, ExtReg); 2830b57cec5SDimitry Andric MIB.addUse(PhysReg, RegState::Implicit); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric Register OutgoingValueHandler::getStackAddress(const CCValAssign &VA, 2880b57cec5SDimitry Andric MachineMemOperand *&MMO) { 2890b57cec5SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 2900b57cec5SDimitry Andric const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric LLT p0 = LLT::pointer(0, 32); 2930b57cec5SDimitry Andric LLT s32 = LLT::scalar(32); 2940b57cec5SDimitry Andric Register SPReg = MRI.createGenericVirtualRegister(p0); 2950b57cec5SDimitry Andric MIRBuilder.buildCopy(SPReg, Register(Mips::SP)); 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric Register OffsetReg = MRI.createGenericVirtualRegister(s32); 2980b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset(); 2990b57cec5SDimitry Andric MIRBuilder.buildConstant(OffsetReg, Offset); 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric Register AddrReg = MRI.createGenericVirtualRegister(p0); 3020b57cec5SDimitry Andric MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric MachinePointerInfo MPO = 3050b57cec5SDimitry Andric MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); 3060b57cec5SDimitry Andric unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; 3070b57cec5SDimitry Andric unsigned Align = MinAlign(TFL->getStackAlignment(), Offset); 3080b57cec5SDimitry Andric MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, Size, Align); 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric return AddrReg; 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric void OutgoingValueHandler::assignValueToAddress(Register ValVReg, 3140b57cec5SDimitry Andric const CCValAssign &VA) { 3150b57cec5SDimitry Andric MachineMemOperand *MMO; 3160b57cec5SDimitry Andric Register Addr = getStackAddress(VA, MMO); 3170b57cec5SDimitry Andric Register ExtReg = extendRegister(ValVReg, VA); 3180b57cec5SDimitry Andric MIRBuilder.buildStore(ExtReg, Addr, *MMO); 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric Register OutgoingValueHandler::extendRegister(Register ValReg, 3220b57cec5SDimitry Andric const CCValAssign &VA) { 3230b57cec5SDimitry Andric LLT LocTy{VA.getLocVT()}; 3240b57cec5SDimitry Andric switch (VA.getLocInfo()) { 3250b57cec5SDimitry Andric case CCValAssign::SExt: { 3260b57cec5SDimitry Andric Register ExtReg = MRI.createGenericVirtualRegister(LocTy); 3270b57cec5SDimitry Andric MIRBuilder.buildSExt(ExtReg, ValReg); 3280b57cec5SDimitry Andric return ExtReg; 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric case CCValAssign::ZExt: { 3310b57cec5SDimitry Andric Register ExtReg = MRI.createGenericVirtualRegister(LocTy); 3320b57cec5SDimitry Andric MIRBuilder.buildZExt(ExtReg, ValReg); 3330b57cec5SDimitry Andric return ExtReg; 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric case CCValAssign::AExt: { 3360b57cec5SDimitry Andric Register ExtReg = MRI.createGenericVirtualRegister(LocTy); 3370b57cec5SDimitry Andric MIRBuilder.buildAnyExt(ExtReg, ValReg); 3380b57cec5SDimitry Andric return ExtReg; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric // TODO : handle upper extends 3410b57cec5SDimitry Andric case CCValAssign::Full: 3420b57cec5SDimitry Andric return ValReg; 3430b57cec5SDimitry Andric default: 3440b57cec5SDimitry Andric break; 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric llvm_unreachable("unable to extend register"); 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric bool OutgoingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs, 3500b57cec5SDimitry Andric ArrayRef<CCValAssign> ArgLocs, 3510b57cec5SDimitry Andric unsigned ArgLocsStartIndex, 3520b57cec5SDimitry Andric Register ArgsReg, const EVT &VT) { 3530b57cec5SDimitry Andric MIRBuilder.buildUnmerge(VRegs, ArgsReg); 3540b57cec5SDimitry Andric setLeastSignificantFirst(VRegs); 3550b57cec5SDimitry Andric if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) 3560b57cec5SDimitry Andric return false; 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric return true; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 361*8bcb0991SDimitry Andric static bool isSupportedArgumentType(Type *T) { 3620b57cec5SDimitry Andric if (T->isIntegerTy()) 3630b57cec5SDimitry Andric return true; 3640b57cec5SDimitry Andric if (T->isPointerTy()) 3650b57cec5SDimitry Andric return true; 3660b57cec5SDimitry Andric if (T->isFloatingPointTy()) 3670b57cec5SDimitry Andric return true; 3680b57cec5SDimitry Andric return false; 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 371*8bcb0991SDimitry Andric static bool isSupportedReturnType(Type *T) { 372*8bcb0991SDimitry Andric if (T->isIntegerTy()) 373*8bcb0991SDimitry Andric return true; 374*8bcb0991SDimitry Andric if (T->isPointerTy()) 375*8bcb0991SDimitry Andric return true; 376*8bcb0991SDimitry Andric if (T->isFloatingPointTy()) 377*8bcb0991SDimitry Andric return true; 378*8bcb0991SDimitry Andric if (T->isAggregateType()) 379*8bcb0991SDimitry Andric return true; 380*8bcb0991SDimitry Andric return false; 381*8bcb0991SDimitry Andric } 382*8bcb0991SDimitry Andric 3830b57cec5SDimitry Andric static CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT, 3840b57cec5SDimitry Andric const ISD::ArgFlagsTy &Flags) { 3850b57cec5SDimitry Andric // > does not mean loss of information as type RegisterVT can't hold type VT, 3860b57cec5SDimitry Andric // it means that type VT is split into multiple registers of type RegisterVT 3870b57cec5SDimitry Andric if (VT.getSizeInBits() >= RegisterVT.getSizeInBits()) 3880b57cec5SDimitry Andric return CCValAssign::LocInfo::Full; 3890b57cec5SDimitry Andric if (Flags.isSExt()) 3900b57cec5SDimitry Andric return CCValAssign::LocInfo::SExt; 3910b57cec5SDimitry Andric if (Flags.isZExt()) 3920b57cec5SDimitry Andric return CCValAssign::LocInfo::ZExt; 3930b57cec5SDimitry Andric return CCValAssign::LocInfo::AExt; 3940b57cec5SDimitry Andric } 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric template <typename T> 3970b57cec5SDimitry Andric static void setLocInfo(SmallVectorImpl<CCValAssign> &ArgLocs, 3980b57cec5SDimitry Andric const SmallVectorImpl<T> &Arguments) { 3990b57cec5SDimitry Andric for (unsigned i = 0; i < ArgLocs.size(); ++i) { 4000b57cec5SDimitry Andric const CCValAssign &VA = ArgLocs[i]; 4010b57cec5SDimitry Andric CCValAssign::LocInfo LocInfo = determineLocInfo( 4020b57cec5SDimitry Andric Arguments[i].VT, Arguments[i].ArgVT, Arguments[i].Flags); 4030b57cec5SDimitry Andric if (VA.isMemLoc()) 4040b57cec5SDimitry Andric ArgLocs[i] = 4050b57cec5SDimitry Andric CCValAssign::getMem(VA.getValNo(), VA.getValVT(), 4060b57cec5SDimitry Andric VA.getLocMemOffset(), VA.getLocVT(), LocInfo); 4070b57cec5SDimitry Andric else 4080b57cec5SDimitry Andric ArgLocs[i] = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), 4090b57cec5SDimitry Andric VA.getLocReg(), VA.getLocVT(), LocInfo); 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 4140b57cec5SDimitry Andric const Value *Val, 4150b57cec5SDimitry Andric ArrayRef<Register> VRegs) const { 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); 4180b57cec5SDimitry Andric 419*8bcb0991SDimitry Andric if (Val != nullptr && !isSupportedReturnType(Val->getType())) 4200b57cec5SDimitry Andric return false; 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric if (!VRegs.empty()) { 4230b57cec5SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 4240b57cec5SDimitry Andric const Function &F = MF.getFunction(); 4250b57cec5SDimitry Andric const DataLayout &DL = MF.getDataLayout(); 4260b57cec5SDimitry Andric const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric SmallVector<ArgInfo, 8> RetInfos; 4290b57cec5SDimitry Andric SmallVector<unsigned, 8> OrigArgIndices; 4300b57cec5SDimitry Andric 431*8bcb0991SDimitry Andric ArgInfo ArgRetInfo(VRegs, Val->getType()); 432*8bcb0991SDimitry Andric setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F); 433*8bcb0991SDimitry Andric splitToValueTypes(DL, ArgRetInfo, 0, RetInfos, OrigArgIndices); 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric SmallVector<ISD::OutputArg, 8> Outs; 4360b57cec5SDimitry Andric subTargetRegTypeForCallingConv(F, RetInfos, OrigArgIndices, Outs); 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 4390b57cec5SDimitry Andric MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 4400b57cec5SDimitry Andric F.getContext()); 4410b57cec5SDimitry Andric CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); 4420b57cec5SDimitry Andric setLocInfo(ArgLocs, Outs); 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); 4450b57cec5SDimitry Andric if (!RetHandler.handle(ArgLocs, RetInfos)) { 4460b57cec5SDimitry Andric return false; 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric MIRBuilder.insertInstr(Ret); 4500b57cec5SDimitry Andric return true; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric bool MipsCallLowering::lowerFormalArguments( 4540b57cec5SDimitry Andric MachineIRBuilder &MIRBuilder, const Function &F, 4550b57cec5SDimitry Andric ArrayRef<ArrayRef<Register>> VRegs) const { 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric // Quick exit if there aren't any args. 4580b57cec5SDimitry Andric if (F.arg_empty()) 4590b57cec5SDimitry Andric return true; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric for (auto &Arg : F.args()) { 462*8bcb0991SDimitry Andric if (!isSupportedArgumentType(Arg.getType())) 4630b57cec5SDimitry Andric return false; 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 4670b57cec5SDimitry Andric const DataLayout &DL = MF.getDataLayout(); 4680b57cec5SDimitry Andric const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric SmallVector<ArgInfo, 8> ArgInfos; 4710b57cec5SDimitry Andric SmallVector<unsigned, 8> OrigArgIndices; 4720b57cec5SDimitry Andric unsigned i = 0; 4730b57cec5SDimitry Andric for (auto &Arg : F.args()) { 4740b57cec5SDimitry Andric ArgInfo AInfo(VRegs[i], Arg.getType()); 4750b57cec5SDimitry Andric setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F); 476*8bcb0991SDimitry Andric ArgInfos.push_back(AInfo); 477*8bcb0991SDimitry Andric OrigArgIndices.push_back(i); 4780b57cec5SDimitry Andric ++i; 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric SmallVector<ISD::InputArg, 8> Ins; 4820b57cec5SDimitry Andric subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Ins); 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 4850b57cec5SDimitry Andric MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 4860b57cec5SDimitry Andric F.getContext()); 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric const MipsTargetMachine &TM = 4890b57cec5SDimitry Andric static_cast<const MipsTargetMachine &>(MF.getTarget()); 4900b57cec5SDimitry Andric const MipsABIInfo &ABI = TM.getABI(); 4910b57cec5SDimitry Andric CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), 4920b57cec5SDimitry Andric 1); 4930b57cec5SDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); 4940b57cec5SDimitry Andric setLocInfo(ArgLocs, Ins); 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); 4970b57cec5SDimitry Andric if (!Handler.handle(ArgLocs, ArgInfos)) 4980b57cec5SDimitry Andric return false; 4990b57cec5SDimitry Andric 500*8bcb0991SDimitry Andric if (F.isVarArg()) { 501*8bcb0991SDimitry Andric ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs(); 502*8bcb0991SDimitry Andric unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs); 503*8bcb0991SDimitry Andric 504*8bcb0991SDimitry Andric int VaArgOffset; 505*8bcb0991SDimitry Andric unsigned RegSize = 4; 506*8bcb0991SDimitry Andric if (ArgRegs.size() == Idx) 507*8bcb0991SDimitry Andric VaArgOffset = alignTo(CCInfo.getNextStackOffset(), RegSize); 508*8bcb0991SDimitry Andric else { 509*8bcb0991SDimitry Andric VaArgOffset = 510*8bcb0991SDimitry Andric (int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) - 511*8bcb0991SDimitry Andric (int)(RegSize * (ArgRegs.size() - Idx)); 512*8bcb0991SDimitry Andric } 513*8bcb0991SDimitry Andric 514*8bcb0991SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 515*8bcb0991SDimitry Andric int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true); 516*8bcb0991SDimitry Andric MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI); 517*8bcb0991SDimitry Andric 518*8bcb0991SDimitry Andric for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) { 519*8bcb0991SDimitry Andric MIRBuilder.getMBB().addLiveIn(ArgRegs[I]); 520*8bcb0991SDimitry Andric 521*8bcb0991SDimitry Andric MachineInstrBuilder Copy = 522*8bcb0991SDimitry Andric MIRBuilder.buildCopy(LLT::scalar(RegSize * 8), Register(ArgRegs[I])); 523*8bcb0991SDimitry Andric FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true); 524*8bcb0991SDimitry Andric MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI); 525*8bcb0991SDimitry Andric MachineInstrBuilder FrameIndex = 526*8bcb0991SDimitry Andric MIRBuilder.buildFrameIndex(LLT::pointer(MPO.getAddrSpace(), 32), FI); 527*8bcb0991SDimitry Andric MachineMemOperand *MMO = 528*8bcb0991SDimitry Andric MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, RegSize, 529*8bcb0991SDimitry Andric /* Alignment */ RegSize); 530*8bcb0991SDimitry Andric MIRBuilder.buildStore(Copy, FrameIndex, *MMO); 531*8bcb0991SDimitry Andric } 532*8bcb0991SDimitry Andric } 533*8bcb0991SDimitry Andric 5340b57cec5SDimitry Andric return true; 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 538*8bcb0991SDimitry Andric CallLoweringInfo &Info) const { 5390b57cec5SDimitry Andric 540*8bcb0991SDimitry Andric if (Info.CallConv != CallingConv::C) 5410b57cec5SDimitry Andric return false; 5420b57cec5SDimitry Andric 543*8bcb0991SDimitry Andric for (auto &Arg : Info.OrigArgs) { 544*8bcb0991SDimitry Andric if (!isSupportedArgumentType(Arg.Ty)) 5450b57cec5SDimitry Andric return false; 546*8bcb0991SDimitry Andric if (Arg.Flags[0].isByVal()) 547*8bcb0991SDimitry Andric return false; 548*8bcb0991SDimitry Andric if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy()) 5490b57cec5SDimitry Andric return false; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric 552*8bcb0991SDimitry Andric if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(Info.OrigRet.Ty)) 5530b57cec5SDimitry Andric return false; 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 5560b57cec5SDimitry Andric const Function &F = MF.getFunction(); 557*8bcb0991SDimitry Andric const DataLayout &DL = MF.getDataLayout(); 5580b57cec5SDimitry Andric const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 5590b57cec5SDimitry Andric const MipsTargetMachine &TM = 5600b57cec5SDimitry Andric static_cast<const MipsTargetMachine &>(MF.getTarget()); 5610b57cec5SDimitry Andric const MipsABIInfo &ABI = TM.getABI(); 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric MachineInstrBuilder CallSeqStart = 5640b57cec5SDimitry Andric MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric const bool IsCalleeGlobalPIC = 567*8bcb0991SDimitry Andric Info.Callee.isGlobal() && TM.isPositionIndependent(); 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert( 570*8bcb0991SDimitry Andric Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL); 5710b57cec5SDimitry Andric MIB.addDef(Mips::SP, RegState::Implicit); 5720b57cec5SDimitry Andric if (IsCalleeGlobalPIC) { 5730b57cec5SDimitry Andric Register CalleeReg = 5740b57cec5SDimitry Andric MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32)); 5750b57cec5SDimitry Andric MachineInstr *CalleeGlobalValue = 576*8bcb0991SDimitry Andric MIRBuilder.buildGlobalValue(CalleeReg, Info.Callee.getGlobal()); 577*8bcb0991SDimitry Andric if (!Info.Callee.getGlobal()->hasLocalLinkage()) 5780b57cec5SDimitry Andric CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL); 5790b57cec5SDimitry Andric MIB.addUse(CalleeReg); 5800b57cec5SDimitry Andric } else 581*8bcb0991SDimitry Andric MIB.add(Info.Callee); 5820b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 5830b57cec5SDimitry Andric MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv())); 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric TargetLowering::ArgListTy FuncOrigArgs; 586*8bcb0991SDimitry Andric FuncOrigArgs.reserve(Info.OrigArgs.size()); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric SmallVector<ArgInfo, 8> ArgInfos; 5890b57cec5SDimitry Andric SmallVector<unsigned, 8> OrigArgIndices; 5900b57cec5SDimitry Andric unsigned i = 0; 591*8bcb0991SDimitry Andric for (auto &Arg : Info.OrigArgs) { 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric TargetLowering::ArgListEntry Entry; 5940b57cec5SDimitry Andric Entry.Ty = Arg.Ty; 5950b57cec5SDimitry Andric FuncOrigArgs.push_back(Entry); 5960b57cec5SDimitry Andric 597*8bcb0991SDimitry Andric ArgInfos.push_back(Arg); 598*8bcb0991SDimitry Andric OrigArgIndices.push_back(i); 5990b57cec5SDimitry Andric ++i; 6000b57cec5SDimitry Andric } 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric SmallVector<ISD::OutputArg, 8> Outs; 6030b57cec5SDimitry Andric subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs); 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric SmallVector<CCValAssign, 8> ArgLocs; 606*8bcb0991SDimitry Andric bool IsCalleeVarArg = false; 607*8bcb0991SDimitry Andric if (Info.Callee.isGlobal()) { 608*8bcb0991SDimitry Andric const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal()); 609*8bcb0991SDimitry Andric IsCalleeVarArg = CF->isVarArg(); 610*8bcb0991SDimitry Andric } 611*8bcb0991SDimitry Andric MipsCCState CCInfo(F.getCallingConv(), IsCalleeVarArg, MF, ArgLocs, 6120b57cec5SDimitry Andric F.getContext()); 6130b57cec5SDimitry Andric 614*8bcb0991SDimitry Andric CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv), 1); 615*8bcb0991SDimitry Andric const char *Call = 616*8bcb0991SDimitry Andric Info.Callee.isSymbol() ? Info.Callee.getSymbolName() : nullptr; 6170b57cec5SDimitry Andric CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); 6180b57cec5SDimitry Andric setLocInfo(ArgLocs, Outs); 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); 6210b57cec5SDimitry Andric if (!RetHandler.handle(ArgLocs, ArgInfos)) { 6220b57cec5SDimitry Andric return false; 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric unsigned NextStackOffset = CCInfo.getNextStackOffset(); 6260b57cec5SDimitry Andric const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); 6270b57cec5SDimitry Andric unsigned StackAlignment = TFL->getStackAlignment(); 6280b57cec5SDimitry Andric NextStackOffset = alignTo(NextStackOffset, StackAlignment); 6290b57cec5SDimitry Andric CallSeqStart.addImm(NextStackOffset).addImm(0); 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric if (IsCalleeGlobalPIC) { 6320b57cec5SDimitry Andric MIRBuilder.buildCopy( 6330b57cec5SDimitry Andric Register(Mips::GP), 6340b57cec5SDimitry Andric MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel()); 6350b57cec5SDimitry Andric MIB.addDef(Mips::GP, RegState::Implicit); 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric MIRBuilder.insertInstr(MIB); 6380b57cec5SDimitry Andric if (MIB->getOpcode() == Mips::JALRPseudo) { 6390b57cec5SDimitry Andric const MipsSubtarget &STI = 6400b57cec5SDimitry Andric static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); 6410b57cec5SDimitry Andric MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), 6420b57cec5SDimitry Andric *STI.getRegBankInfo()); 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 645*8bcb0991SDimitry Andric if (!Info.OrigRet.Ty->isVoidTy()) { 6460b57cec5SDimitry Andric ArgInfos.clear(); 6470b57cec5SDimitry Andric SmallVector<unsigned, 8> OrigRetIndices; 6480b57cec5SDimitry Andric 649*8bcb0991SDimitry Andric splitToValueTypes(DL, Info.OrigRet, 0, ArgInfos, OrigRetIndices); 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric SmallVector<ISD::InputArg, 8> Ins; 6520b57cec5SDimitry Andric subTargetRegTypeForCallingConv(F, ArgInfos, OrigRetIndices, Ins); 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric SmallVector<CCValAssign, 8> ArgLocs; 6550b57cec5SDimitry Andric MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 6560b57cec5SDimitry Andric F.getContext()); 6570b57cec5SDimitry Andric 658*8bcb0991SDimitry Andric CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), Info.OrigRet.Ty, Call); 6590b57cec5SDimitry Andric setLocInfo(ArgLocs, Ins); 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); 6620b57cec5SDimitry Andric if (!Handler.handle(ArgLocs, ArgInfos)) 6630b57cec5SDimitry Andric return false; 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0); 6670b57cec5SDimitry Andric 6680b57cec5SDimitry Andric return true; 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric template <typename T> 6720b57cec5SDimitry Andric void MipsCallLowering::subTargetRegTypeForCallingConv( 6730b57cec5SDimitry Andric const Function &F, ArrayRef<ArgInfo> Args, 6740b57cec5SDimitry Andric ArrayRef<unsigned> OrigArgIndices, SmallVectorImpl<T> &ISDArgs) const { 6750b57cec5SDimitry Andric const DataLayout &DL = F.getParent()->getDataLayout(); 6760b57cec5SDimitry Andric const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric unsigned ArgNo = 0; 6790b57cec5SDimitry Andric for (auto &Arg : Args) { 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric EVT VT = TLI.getValueType(DL, Arg.Ty); 6820b57cec5SDimitry Andric MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), 6830b57cec5SDimitry Andric F.getCallingConv(), VT); 6840b57cec5SDimitry Andric unsigned NumRegs = TLI.getNumRegistersForCallingConv( 6850b57cec5SDimitry Andric F.getContext(), F.getCallingConv(), VT); 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric for (unsigned i = 0; i < NumRegs; ++i) { 688*8bcb0991SDimitry Andric ISD::ArgFlagsTy Flags = Arg.Flags[0]; 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric if (i == 0) 6910b57cec5SDimitry Andric Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); 6920b57cec5SDimitry Andric else 693*8bcb0991SDimitry Andric Flags.setOrigAlign(Align::None()); 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric ISDArgs.emplace_back(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 6960b57cec5SDimitry Andric 0); 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric ++ArgNo; 6990b57cec5SDimitry Andric } 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric void MipsCallLowering::splitToValueTypes( 703*8bcb0991SDimitry Andric const DataLayout &DL, const ArgInfo &OrigArg, unsigned OriginalIndex, 7040b57cec5SDimitry Andric SmallVectorImpl<ArgInfo> &SplitArgs, 7050b57cec5SDimitry Andric SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const { 7060b57cec5SDimitry Andric 707*8bcb0991SDimitry Andric SmallVector<EVT, 4> SplitEVTs; 708*8bcb0991SDimitry Andric SmallVector<Register, 4> SplitVRegs; 709*8bcb0991SDimitry Andric const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 710*8bcb0991SDimitry Andric LLVMContext &Ctx = OrigArg.Ty->getContext(); 711*8bcb0991SDimitry Andric 712*8bcb0991SDimitry Andric ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitEVTs); 713*8bcb0991SDimitry Andric 714*8bcb0991SDimitry Andric for (unsigned i = 0; i < SplitEVTs.size(); ++i) { 715*8bcb0991SDimitry Andric ArgInfo Info = ArgInfo{OrigArg.Regs[i], SplitEVTs[i].getTypeForEVT(Ctx)}; 716*8bcb0991SDimitry Andric Info.Flags = OrigArg.Flags; 717*8bcb0991SDimitry Andric SplitArgs.push_back(Info); 7180b57cec5SDimitry Andric SplitArgsOrigIndices.push_back(OriginalIndex); 7190b57cec5SDimitry Andric } 720*8bcb0991SDimitry Andric } 721