Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
35294 views
//===-- RISCVCallLowering.cpp - Call lowering -------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8/// \file9/// This file implements the lowering of LLVM calls to machine code calls for10/// GlobalISel.11//12//===----------------------------------------------------------------------===//1314#include "RISCVCallLowering.h"15#include "RISCVISelLowering.h"16#include "RISCVMachineFunctionInfo.h"17#include "RISCVSubtarget.h"18#include "llvm/CodeGen/Analysis.h"19#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"20#include "llvm/CodeGen/MachineFrameInfo.h"2122using namespace llvm;2324namespace {2526struct RISCVOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {27private:28// The function used internally to assign args - we ignore the AssignFn stored29// by OutgoingValueAssigner since RISC-V implements its CC using a custom30// function with a different signature.31RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn;3233// Whether this is assigning args for a return.34bool IsRet;3536RVVArgDispatcher &RVVDispatcher;3738public:39RISCVOutgoingValueAssigner(40RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet,41RVVArgDispatcher &RVVDispatcher)42: CallLowering::OutgoingValueAssigner(nullptr),43RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet),44RVVDispatcher(RVVDispatcher) {}4546bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,47CCValAssign::LocInfo LocInfo,48const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,49CCState &State) override {50MachineFunction &MF = State.getMachineFunction();51const DataLayout &DL = MF.getDataLayout();52const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();5354if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,55LocInfo, Flags, State, Info.IsFixed, IsRet, Info.Ty,56*Subtarget.getTargetLowering(), RVVDispatcher))57return true;5859StackSize = State.getStackSize();60return false;61}62};6364struct RISCVOutgoingValueHandler : public CallLowering::OutgoingValueHandler {65RISCVOutgoingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,66MachineInstrBuilder MIB)67: OutgoingValueHandler(B, MRI), MIB(MIB),68Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}69Register getStackAddress(uint64_t MemSize, int64_t Offset,70MachinePointerInfo &MPO,71ISD::ArgFlagsTy Flags) override {72MachineFunction &MF = MIRBuilder.getMF();73LLT p0 = LLT::pointer(0, Subtarget.getXLen());74LLT sXLen = LLT::scalar(Subtarget.getXLen());7576if (!SPReg)77SPReg = MIRBuilder.buildCopy(p0, Register(RISCV::X2)).getReg(0);7879auto OffsetReg = MIRBuilder.buildConstant(sXLen, Offset);8081auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);8283MPO = MachinePointerInfo::getStack(MF, Offset);84return AddrReg.getReg(0);85}8687void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,88const MachinePointerInfo &MPO,89const CCValAssign &VA) override {90MachineFunction &MF = MIRBuilder.getMF();91uint64_t LocMemOffset = VA.getLocMemOffset();9293// TODO: Move StackAlignment to subtarget and share with FrameLowering.94auto MMO =95MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy,96commonAlignment(Align(16), LocMemOffset));9798Register ExtReg = extendRegister(ValVReg, VA);99MIRBuilder.buildStore(ExtReg, Addr, *MMO);100}101102void assignValueToReg(Register ValVReg, Register PhysReg,103const CCValAssign &VA) override {104// If we're passing a smaller fp value into a larger integer register,105// anyextend before copying.106if ((VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32) ||107((VA.getLocVT() == MVT::i32 || VA.getLocVT() == MVT::i64) &&108VA.getValVT() == MVT::f16)) {109LLT DstTy = LLT::scalar(VA.getLocVT().getSizeInBits());110ValVReg = MIRBuilder.buildAnyExt(DstTy, ValVReg).getReg(0);111}112113Register ExtReg = extendRegister(ValVReg, VA);114MIRBuilder.buildCopy(PhysReg, ExtReg);115MIB.addUse(PhysReg, RegState::Implicit);116}117118unsigned assignCustomValue(CallLowering::ArgInfo &Arg,119ArrayRef<CCValAssign> VAs,120std::function<void()> *Thunk) override {121assert(VAs.size() >= 2 && "Expected at least 2 VAs.");122const CCValAssign &VALo = VAs[0];123const CCValAssign &VAHi = VAs[1];124125assert(VAHi.needsCustom() && "Value doesn't need custom handling");126assert(VALo.getValNo() == VAHi.getValNo() &&127"Values belong to different arguments");128129assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&130VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&131"unexpected custom value");132133Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),134MRI.createGenericVirtualRegister(LLT::scalar(32))};135MIRBuilder.buildUnmerge(NewRegs, Arg.Regs[0]);136137if (VAHi.isMemLoc()) {138LLT MemTy(VAHi.getLocVT());139140MachinePointerInfo MPO;141Register StackAddr = getStackAddress(142MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);143144assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,145const_cast<CCValAssign &>(VAHi));146}147148auto assignFunc = [=]() {149assignValueToReg(NewRegs[0], VALo.getLocReg(), VALo);150if (VAHi.isRegLoc())151assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);152};153154if (Thunk) {155*Thunk = assignFunc;156return 2;157}158159assignFunc();160return 2;161}162163private:164MachineInstrBuilder MIB;165166// Cache the SP register vreg if we need it more than once in this call site.167Register SPReg;168169const RISCVSubtarget &Subtarget;170};171172struct RISCVIncomingValueAssigner : public CallLowering::IncomingValueAssigner {173private:174// The function used internally to assign args - we ignore the AssignFn stored175// by IncomingValueAssigner since RISC-V implements its CC using a custom176// function with a different signature.177RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn;178179// Whether this is assigning args from a return.180bool IsRet;181182RVVArgDispatcher &RVVDispatcher;183184public:185RISCVIncomingValueAssigner(186RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet,187RVVArgDispatcher &RVVDispatcher)188: CallLowering::IncomingValueAssigner(nullptr),189RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet),190RVVDispatcher(RVVDispatcher) {}191192bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,193CCValAssign::LocInfo LocInfo,194const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,195CCState &State) override {196MachineFunction &MF = State.getMachineFunction();197const DataLayout &DL = MF.getDataLayout();198const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();199200if (LocVT.isScalableVector())201MF.getInfo<RISCVMachineFunctionInfo>()->setIsVectorCall();202203if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,204LocInfo, Flags, State, /*IsFixed=*/true, IsRet, Info.Ty,205*Subtarget.getTargetLowering(), RVVDispatcher))206return true;207208StackSize = State.getStackSize();209return false;210}211};212213struct RISCVIncomingValueHandler : public CallLowering::IncomingValueHandler {214RISCVIncomingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)215: IncomingValueHandler(B, MRI),216Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}217218Register getStackAddress(uint64_t MemSize, int64_t Offset,219MachinePointerInfo &MPO,220ISD::ArgFlagsTy Flags) override {221MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo();222223int FI = MFI.CreateFixedObject(MemSize, Offset, /*Immutable=*/true);224MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);225return MIRBuilder.buildFrameIndex(LLT::pointer(0, Subtarget.getXLen()), FI)226.getReg(0);227}228229void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,230const MachinePointerInfo &MPO,231const CCValAssign &VA) override {232MachineFunction &MF = MIRBuilder.getMF();233auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,234inferAlignFromPtrInfo(MF, MPO));235MIRBuilder.buildLoad(ValVReg, Addr, *MMO);236}237238void assignValueToReg(Register ValVReg, Register PhysReg,239const CCValAssign &VA) override {240markPhysRegUsed(PhysReg);241IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);242}243244unsigned assignCustomValue(CallLowering::ArgInfo &Arg,245ArrayRef<CCValAssign> VAs,246std::function<void()> *Thunk) override {247assert(VAs.size() >= 2 && "Expected at least 2 VAs.");248const CCValAssign &VALo = VAs[0];249const CCValAssign &VAHi = VAs[1];250251assert(VAHi.needsCustom() && "Value doesn't need custom handling");252assert(VALo.getValNo() == VAHi.getValNo() &&253"Values belong to different arguments");254255assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&256VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&257"unexpected custom value");258259Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),260MRI.createGenericVirtualRegister(LLT::scalar(32))};261262if (VAHi.isMemLoc()) {263LLT MemTy(VAHi.getLocVT());264265MachinePointerInfo MPO;266Register StackAddr = getStackAddress(267MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);268269assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,270const_cast<CCValAssign &>(VAHi));271}272273assignValueToReg(NewRegs[0], VALo.getLocReg(), VALo);274if (VAHi.isRegLoc())275assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);276277MIRBuilder.buildMergeLikeInstr(Arg.Regs[0], NewRegs);278279return 2;280}281282/// How the physical register gets marked varies between formal283/// parameters (it's a basic-block live-in), and a call instruction284/// (it's an implicit-def of the BL).285virtual void markPhysRegUsed(MCRegister PhysReg) = 0;286287private:288const RISCVSubtarget &Subtarget;289};290291struct RISCVFormalArgHandler : public RISCVIncomingValueHandler {292RISCVFormalArgHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)293: RISCVIncomingValueHandler(B, MRI) {}294295void markPhysRegUsed(MCRegister PhysReg) override {296MIRBuilder.getMRI()->addLiveIn(PhysReg);297MIRBuilder.getMBB().addLiveIn(PhysReg);298}299};300301struct RISCVCallReturnHandler : public RISCVIncomingValueHandler {302RISCVCallReturnHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,303MachineInstrBuilder &MIB)304: RISCVIncomingValueHandler(B, MRI), MIB(MIB) {}305306void markPhysRegUsed(MCRegister PhysReg) override {307MIB.addDef(PhysReg, RegState::Implicit);308}309310MachineInstrBuilder MIB;311};312313} // namespace314315RISCVCallLowering::RISCVCallLowering(const RISCVTargetLowering &TLI)316: CallLowering(&TLI) {}317318/// Return true if scalable vector with ScalarTy is legal for lowering.319static bool isLegalElementTypeForRVV(Type *EltTy,320const RISCVSubtarget &Subtarget) {321if (EltTy->isPointerTy())322return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() : true;323if (EltTy->isIntegerTy(1) || EltTy->isIntegerTy(8) ||324EltTy->isIntegerTy(16) || EltTy->isIntegerTy(32))325return true;326if (EltTy->isIntegerTy(64))327return Subtarget.hasVInstructionsI64();328if (EltTy->isHalfTy())329return Subtarget.hasVInstructionsF16();330if (EltTy->isBFloatTy())331return Subtarget.hasVInstructionsBF16();332if (EltTy->isFloatTy())333return Subtarget.hasVInstructionsF32();334if (EltTy->isDoubleTy())335return Subtarget.hasVInstructionsF64();336return false;337}338339// TODO: Support all argument types.340// TODO: Remove IsLowerArgs argument by adding support for vectors in lowerCall.341static bool isSupportedArgumentType(Type *T, const RISCVSubtarget &Subtarget,342bool IsLowerArgs = false) {343if (T->isIntegerTy())344return true;345if (T->isHalfTy() || T->isFloatTy() || T->isDoubleTy())346return true;347if (T->isPointerTy())348return true;349// TODO: Support fixed vector types.350if (IsLowerArgs && T->isVectorTy() && Subtarget.hasVInstructions() &&351T->isScalableTy() &&352isLegalElementTypeForRVV(T->getScalarType(), Subtarget))353return true;354return false;355}356357// TODO: Only integer, pointer and aggregate types are supported now.358// TODO: Remove IsLowerRetVal argument by adding support for vectors in359// lowerCall.360static bool isSupportedReturnType(Type *T, const RISCVSubtarget &Subtarget,361bool IsLowerRetVal = false) {362// TODO: Integers larger than 2*XLen are passed indirectly which is not363// supported yet.364if (T->isIntegerTy())365return T->getIntegerBitWidth() <= Subtarget.getXLen() * 2;366if (T->isHalfTy() || T->isFloatTy() || T->isDoubleTy())367return true;368if (T->isPointerTy())369return true;370371if (T->isArrayTy())372return isSupportedReturnType(T->getArrayElementType(), Subtarget);373374if (T->isStructTy()) {375auto StructT = cast<StructType>(T);376for (unsigned i = 0, e = StructT->getNumElements(); i != e; ++i)377if (!isSupportedReturnType(StructT->getElementType(i), Subtarget))378return false;379return true;380}381382if (IsLowerRetVal && T->isVectorTy() && Subtarget.hasVInstructions() &&383T->isScalableTy() &&384isLegalElementTypeForRVV(T->getScalarType(), Subtarget))385return true;386387return false;388}389390bool RISCVCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,391const Value *Val,392ArrayRef<Register> VRegs,393MachineInstrBuilder &Ret) const {394if (!Val)395return true;396397const RISCVSubtarget &Subtarget =398MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();399if (!isSupportedReturnType(Val->getType(), Subtarget, /*IsLowerRetVal=*/true))400return false;401402MachineFunction &MF = MIRBuilder.getMF();403const DataLayout &DL = MF.getDataLayout();404const Function &F = MF.getFunction();405CallingConv::ID CC = F.getCallingConv();406407ArgInfo OrigRetInfo(VRegs, Val->getType(), 0);408setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F);409410SmallVector<ArgInfo, 4> SplitRetInfos;411splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC);412413RVVArgDispatcher Dispatcher{&MF, getTLI<RISCVTargetLowering>(),414ArrayRef(F.getReturnType())};415RISCVOutgoingValueAssigner Assigner(416CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,417/*IsRet=*/true, Dispatcher);418RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret);419return determineAndHandleAssignments(Handler, Assigner, SplitRetInfos,420MIRBuilder, CC, F.isVarArg());421}422423bool RISCVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,424const Value *Val, ArrayRef<Register> VRegs,425FunctionLoweringInfo &FLI) const {426assert(!Val == VRegs.empty() && "Return value without a vreg");427MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(RISCV::PseudoRET);428429if (!lowerReturnVal(MIRBuilder, Val, VRegs, Ret))430return false;431432MIRBuilder.insertInstr(Ret);433return true;434}435436/// If there are varargs that were passed in a0-a7, the data in those registers437/// must be copied to the varargs save area on the stack.438void RISCVCallLowering::saveVarArgRegisters(439MachineIRBuilder &MIRBuilder, CallLowering::IncomingValueHandler &Handler,440IncomingValueAssigner &Assigner, CCState &CCInfo) const {441MachineFunction &MF = MIRBuilder.getMF();442const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();443unsigned XLenInBytes = Subtarget.getXLen() / 8;444ArrayRef<MCPhysReg> ArgRegs = RISCV::getArgGPRs(Subtarget.getTargetABI());445MachineRegisterInfo &MRI = MF.getRegInfo();446unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);447MachineFrameInfo &MFI = MF.getFrameInfo();448RISCVMachineFunctionInfo *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();449450// Size of the vararg save area. For now, the varargs save area is either451// zero or large enough to hold a0-a7.452int VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);453int FI;454455// If all registers are allocated, then all varargs must be passed on the456// stack and we don't need to save any argregs.457if (VarArgsSaveSize == 0) {458int VaArgOffset = Assigner.StackSize;459FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);460} else {461int VaArgOffset = -VarArgsSaveSize;462FI = MFI.CreateFixedObject(VarArgsSaveSize, VaArgOffset, true);463464// If saving an odd number of registers then create an extra stack slot to465// ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures466// offsets to even-numbered registered remain 2*XLEN-aligned.467if (Idx % 2) {468MFI.CreateFixedObject(XLenInBytes,469VaArgOffset - static_cast<int>(XLenInBytes), true);470VarArgsSaveSize += XLenInBytes;471}472473const LLT p0 = LLT::pointer(MF.getDataLayout().getAllocaAddrSpace(),474Subtarget.getXLen());475const LLT sXLen = LLT::scalar(Subtarget.getXLen());476477auto FIN = MIRBuilder.buildFrameIndex(p0, FI);478auto Offset = MIRBuilder.buildConstant(479MRI.createGenericVirtualRegister(sXLen), XLenInBytes);480481// Copy the integer registers that may have been used for passing varargs482// to the vararg save area.483const MVT XLenVT = Subtarget.getXLenVT();484for (unsigned I = Idx; I < ArgRegs.size(); ++I) {485const Register VReg = MRI.createGenericVirtualRegister(sXLen);486Handler.assignValueToReg(487VReg, ArgRegs[I],488CCValAssign::getReg(I + MF.getFunction().getNumOperands(), XLenVT,489ArgRegs[I], XLenVT, CCValAssign::Full));490auto MPO =491MachinePointerInfo::getFixedStack(MF, FI, (I - Idx) * XLenInBytes);492MIRBuilder.buildStore(VReg, FIN, MPO, inferAlignFromPtrInfo(MF, MPO));493FIN = MIRBuilder.buildPtrAdd(MRI.createGenericVirtualRegister(p0),494FIN.getReg(0), Offset);495}496}497498// Record the frame index of the first variable argument which is a value499// necessary to G_VASTART.500RVFI->setVarArgsFrameIndex(FI);501RVFI->setVarArgsSaveSize(VarArgsSaveSize);502}503504bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,505const Function &F,506ArrayRef<ArrayRef<Register>> VRegs,507FunctionLoweringInfo &FLI) const {508// Early exit if there are no arguments. varargs are not part of F.args() but509// must be lowered.510if (F.arg_empty() && !F.isVarArg())511return true;512513const RISCVSubtarget &Subtarget =514MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();515for (auto &Arg : F.args()) {516if (!isSupportedArgumentType(Arg.getType(), Subtarget,517/*IsLowerArgs=*/true))518return false;519}520521MachineFunction &MF = MIRBuilder.getMF();522const DataLayout &DL = MF.getDataLayout();523CallingConv::ID CC = F.getCallingConv();524525SmallVector<ArgInfo, 32> SplitArgInfos;526SmallVector<Type *, 4> TypeList;527unsigned Index = 0;528for (auto &Arg : F.args()) {529// Construct the ArgInfo object from destination register and argument type.530ArgInfo AInfo(VRegs[Index], Arg.getType(), Index);531setArgFlags(AInfo, Index + AttributeList::FirstArgIndex, DL, F);532533// Handle any required merging from split value types from physical534// registers into the desired VReg. ArgInfo objects are constructed535// correspondingly and appended to SplitArgInfos.536splitToValueTypes(AInfo, SplitArgInfos, DL, CC);537538TypeList.push_back(Arg.getType());539540++Index;541}542543RVVArgDispatcher Dispatcher{&MF, getTLI<RISCVTargetLowering>(),544ArrayRef(TypeList)};545RISCVIncomingValueAssigner Assigner(546CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,547/*IsRet=*/false, Dispatcher);548RISCVFormalArgHandler Handler(MIRBuilder, MF.getRegInfo());549550SmallVector<CCValAssign, 16> ArgLocs;551CCState CCInfo(CC, F.isVarArg(), MIRBuilder.getMF(), ArgLocs, F.getContext());552if (!determineAssignments(Assigner, SplitArgInfos, CCInfo) ||553!handleAssignments(Handler, SplitArgInfos, CCInfo, ArgLocs, MIRBuilder))554return false;555556if (F.isVarArg())557saveVarArgRegisters(MIRBuilder, Handler, Assigner, CCInfo);558559return true;560}561562bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,563CallLoweringInfo &Info) const {564MachineFunction &MF = MIRBuilder.getMF();565const DataLayout &DL = MF.getDataLayout();566const Function &F = MF.getFunction();567CallingConv::ID CC = F.getCallingConv();568569const RISCVSubtarget &Subtarget =570MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();571for (auto &AInfo : Info.OrigArgs) {572if (!isSupportedArgumentType(AInfo.Ty, Subtarget))573return false;574}575576if (!Info.OrigRet.Ty->isVoidTy() &&577!isSupportedReturnType(Info.OrigRet.Ty, Subtarget))578return false;579580MachineInstrBuilder CallSeqStart =581MIRBuilder.buildInstr(RISCV::ADJCALLSTACKDOWN);582583SmallVector<ArgInfo, 32> SplitArgInfos;584SmallVector<ISD::OutputArg, 8> Outs;585SmallVector<Type *, 4> TypeList;586for (auto &AInfo : Info.OrigArgs) {587// Handle any required unmerging of split value types from a given VReg into588// physical registers. ArgInfo objects are constructed correspondingly and589// appended to SplitArgInfos.590splitToValueTypes(AInfo, SplitArgInfos, DL, CC);591TypeList.push_back(AInfo.Ty);592}593594// TODO: Support tail calls.595Info.IsTailCall = false;596597// Select the recommended relocation type R_RISCV_CALL_PLT.598if (!Info.Callee.isReg())599Info.Callee.setTargetFlags(RISCVII::MO_CALL);600601MachineInstrBuilder Call =602MIRBuilder603.buildInstrNoInsert(Info.Callee.isReg() ? RISCV::PseudoCALLIndirect604: RISCV::PseudoCALL)605.add(Info.Callee);606const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();607Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));608609RVVArgDispatcher ArgDispatcher{&MF, getTLI<RISCVTargetLowering>(),610ArrayRef(TypeList)};611RISCVOutgoingValueAssigner ArgAssigner(612CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,613/*IsRet=*/false, ArgDispatcher);614RISCVOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), Call);615if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos,616MIRBuilder, CC, Info.IsVarArg))617return false;618619MIRBuilder.insertInstr(Call);620621CallSeqStart.addImm(ArgAssigner.StackSize).addImm(0);622MIRBuilder.buildInstr(RISCV::ADJCALLSTACKUP)623.addImm(ArgAssigner.StackSize)624.addImm(0);625626// If Callee is a reg, since it is used by a target specific627// instruction, it must have a register class matching the628// constraint of that instruction.629if (Call->getOperand(0).isReg())630constrainOperandRegClass(MF, *TRI, MF.getRegInfo(),631*Subtarget.getInstrInfo(),632*Subtarget.getRegBankInfo(), *Call,633Call->getDesc(), Call->getOperand(0), 0);634635if (Info.OrigRet.Ty->isVoidTy())636return true;637638SmallVector<ArgInfo, 4> SplitRetInfos;639splitToValueTypes(Info.OrigRet, SplitRetInfos, DL, CC);640641RVVArgDispatcher RetDispatcher{&MF, getTLI<RISCVTargetLowering>(),642ArrayRef(F.getReturnType())};643RISCVIncomingValueAssigner RetAssigner(644CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,645/*IsRet=*/true, RetDispatcher);646RISCVCallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Call);647if (!determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos,648MIRBuilder, CC, Info.IsVarArg))649return false;650651return true;652}653654655