662 lines · cpp
1//===-- RISCVCallLowering.cpp - Call lowering -------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// This file implements the lowering of LLVM calls to machine code calls for11/// GlobalISel.12//13//===----------------------------------------------------------------------===//14 15#include "RISCVCallLowering.h"16#include "RISCVCallingConv.h"17#include "RISCVISelLowering.h"18#include "RISCVMachineFunctionInfo.h"19#include "RISCVSubtarget.h"20#include "llvm/CodeGen/Analysis.h"21#include "llvm/CodeGen/FunctionLoweringInfo.h"22#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"23#include "llvm/CodeGen/MachineFrameInfo.h"24 25using namespace llvm;26 27namespace {28 29struct RISCVOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {30private:31 // The function used internally to assign args - we ignore the AssignFn stored32 // by OutgoingValueAssigner since RISC-V implements its CC using a custom33 // function with a different signature.34 RISCVCCAssignFn *RISCVAssignFn;35 36 // Whether this is assigning args for a return.37 bool IsRet;38 39public:40 RISCVOutgoingValueAssigner(RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)41 : CallLowering::OutgoingValueAssigner(nullptr),42 RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}43 44 bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,45 CCValAssign::LocInfo LocInfo,46 const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,47 CCState &State) override {48 if (RISCVAssignFn(ValNo, ValVT, LocVT, LocInfo, Flags, State, IsRet,49 Info.Ty))50 return true;51 52 StackSize = State.getStackSize();53 return false;54 }55};56 57struct RISCVOutgoingValueHandler : public CallLowering::OutgoingValueHandler {58 RISCVOutgoingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,59 MachineInstrBuilder MIB)60 : OutgoingValueHandler(B, MRI), MIB(MIB),61 Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}62 Register getStackAddress(uint64_t MemSize, int64_t Offset,63 MachinePointerInfo &MPO,64 ISD::ArgFlagsTy Flags) override {65 MachineFunction &MF = MIRBuilder.getMF();66 LLT p0 = LLT::pointer(0, Subtarget.getXLen());67 LLT sXLen = LLT::scalar(Subtarget.getXLen());68 69 if (!SPReg)70 SPReg = MIRBuilder.buildCopy(p0, Register(RISCV::X2)).getReg(0);71 72 auto OffsetReg = MIRBuilder.buildConstant(sXLen, Offset);73 74 auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);75 76 MPO = MachinePointerInfo::getStack(MF, Offset);77 return AddrReg.getReg(0);78 }79 80 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,81 const MachinePointerInfo &MPO,82 const CCValAssign &VA) override {83 MachineFunction &MF = MIRBuilder.getMF();84 uint64_t LocMemOffset = VA.getLocMemOffset();85 86 // TODO: Move StackAlignment to subtarget and share with FrameLowering.87 auto MMO =88 MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy,89 commonAlignment(Align(16), LocMemOffset));90 91 Register ExtReg = extendRegister(ValVReg, VA);92 MIRBuilder.buildStore(ExtReg, Addr, *MMO);93 }94 95 void assignValueToReg(Register ValVReg, Register PhysReg,96 const CCValAssign &VA) override {97 Register ExtReg = extendRegister(ValVReg, VA);98 MIRBuilder.buildCopy(PhysReg, ExtReg);99 MIB.addUse(PhysReg, RegState::Implicit);100 }101 102 unsigned assignCustomValue(CallLowering::ArgInfo &Arg,103 ArrayRef<CCValAssign> VAs,104 std::function<void()> *Thunk) override {105 const CCValAssign &VA = VAs[0];106 if ((VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32) ||107 (VA.getLocVT().isInteger() && VA.getValVT() == MVT::f16)) {108 Register PhysReg = VA.getLocReg();109 110 auto assignFunc = [=]() {111 auto Trunc = MIRBuilder.buildAnyExt(LLT(VA.getLocVT()), Arg.Regs[0]);112 MIRBuilder.buildCopy(PhysReg, Trunc);113 MIB.addUse(PhysReg, RegState::Implicit);114 };115 116 if (Thunk) {117 *Thunk = assignFunc;118 return 1;119 }120 121 assignFunc();122 return 1;123 }124 125 assert(VAs.size() >= 2 && "Expected at least 2 VAs.");126 const CCValAssign &VAHi = VAs[1];127 128 assert(VAHi.needsCustom() && "Value doesn't need custom handling");129 assert(VA.getValNo() == VAHi.getValNo() &&130 "Values belong to different arguments");131 132 assert(VA.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&133 VA.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&134 "unexpected custom value");135 136 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),137 MRI.createGenericVirtualRegister(LLT::scalar(32))};138 MIRBuilder.buildUnmerge(NewRegs, Arg.Regs[0]);139 140 if (VAHi.isMemLoc()) {141 LLT MemTy(VAHi.getLocVT());142 143 MachinePointerInfo MPO;144 Register StackAddr = getStackAddress(145 MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);146 147 assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,148 const_cast<CCValAssign &>(VAHi));149 }150 151 auto assignFunc = [=]() {152 assignValueToReg(NewRegs[0], VA.getLocReg(), VA);153 if (VAHi.isRegLoc())154 assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);155 };156 157 if (Thunk) {158 *Thunk = assignFunc;159 return 2;160 }161 162 assignFunc();163 return 2;164 }165 166private:167 MachineInstrBuilder MIB;168 169 // Cache the SP register vreg if we need it more than once in this call site.170 Register SPReg;171 172 const RISCVSubtarget &Subtarget;173};174 175struct RISCVIncomingValueAssigner : public CallLowering::IncomingValueAssigner {176private:177 // The function used internally to assign args - we ignore the AssignFn stored178 // by IncomingValueAssigner since RISC-V implements its CC using a custom179 // function with a different signature.180 RISCVCCAssignFn *RISCVAssignFn;181 182 // Whether this is assigning args from a return.183 bool IsRet;184 185public:186 RISCVIncomingValueAssigner(RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)187 : CallLowering::IncomingValueAssigner(nullptr),188 RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}189 190 bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,191 CCValAssign::LocInfo LocInfo,192 const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,193 CCState &State) override {194 MachineFunction &MF = State.getMachineFunction();195 196 if (LocVT.isScalableVector())197 MF.getInfo<RISCVMachineFunctionInfo>()->setIsVectorCall();198 199 if (RISCVAssignFn(ValNo, ValVT, LocVT, LocInfo, Flags, State, IsRet,200 Info.Ty))201 return true;202 203 StackSize = State.getStackSize();204 return false;205 }206};207 208struct RISCVIncomingValueHandler : public CallLowering::IncomingValueHandler {209 RISCVIncomingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)210 : IncomingValueHandler(B, MRI),211 Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}212 213 Register getStackAddress(uint64_t MemSize, int64_t Offset,214 MachinePointerInfo &MPO,215 ISD::ArgFlagsTy Flags) override {216 MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo();217 218 int FI = MFI.CreateFixedObject(MemSize, Offset, /*Immutable=*/true);219 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);220 return MIRBuilder.buildFrameIndex(LLT::pointer(0, Subtarget.getXLen()), FI)221 .getReg(0);222 }223 224 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,225 const MachinePointerInfo &MPO,226 const CCValAssign &VA) override {227 MachineFunction &MF = MIRBuilder.getMF();228 auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,229 inferAlignFromPtrInfo(MF, MPO));230 MIRBuilder.buildLoad(ValVReg, Addr, *MMO);231 }232 233 void assignValueToReg(Register ValVReg, Register PhysReg,234 const CCValAssign &VA) override {235 markPhysRegUsed(PhysReg);236 IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);237 }238 239 unsigned assignCustomValue(CallLowering::ArgInfo &Arg,240 ArrayRef<CCValAssign> VAs,241 std::function<void()> *Thunk) override {242 const CCValAssign &VA = VAs[0];243 if ((VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32) ||244 (VA.getLocVT().isInteger() && VA.getValVT() == MVT::f16)) {245 Register PhysReg = VA.getLocReg();246 247 markPhysRegUsed(PhysReg);248 249 LLT LocTy(VA.getLocVT());250 auto Copy = MIRBuilder.buildCopy(LocTy, PhysReg);251 252 MIRBuilder.buildTrunc(Arg.Regs[0], Copy.getReg(0));253 return 1;254 }255 256 assert(VAs.size() >= 2 && "Expected at least 2 VAs.");257 const CCValAssign &VAHi = VAs[1];258 259 assert(VAHi.needsCustom() && "Value doesn't need custom handling");260 assert(VA.getValNo() == VAHi.getValNo() &&261 "Values belong to different arguments");262 263 assert(VA.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&264 VA.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&265 "unexpected custom value");266 267 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),268 MRI.createGenericVirtualRegister(LLT::scalar(32))};269 270 if (VAHi.isMemLoc()) {271 LLT MemTy(VAHi.getLocVT());272 273 MachinePointerInfo MPO;274 Register StackAddr = getStackAddress(275 MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);276 277 assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,278 const_cast<CCValAssign &>(VAHi));279 }280 281 assignValueToReg(NewRegs[0], VA.getLocReg(), VA);282 if (VAHi.isRegLoc())283 assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);284 285 MIRBuilder.buildMergeLikeInstr(Arg.Regs[0], NewRegs);286 287 return 2;288 }289 290 /// How the physical register gets marked varies between formal291 /// parameters (it's a basic-block live-in), and a call instruction292 /// (it's an implicit-def of the BL).293 virtual void markPhysRegUsed(MCRegister PhysReg) = 0;294 295private:296 const RISCVSubtarget &Subtarget;297};298 299struct RISCVFormalArgHandler : public RISCVIncomingValueHandler {300 RISCVFormalArgHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)301 : RISCVIncomingValueHandler(B, MRI) {}302 303 void markPhysRegUsed(MCRegister PhysReg) override {304 MIRBuilder.getMRI()->addLiveIn(PhysReg);305 MIRBuilder.getMBB().addLiveIn(PhysReg);306 }307};308 309struct RISCVCallReturnHandler : public RISCVIncomingValueHandler {310 RISCVCallReturnHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,311 MachineInstrBuilder &MIB)312 : RISCVIncomingValueHandler(B, MRI), MIB(MIB) {}313 314 void markPhysRegUsed(MCRegister PhysReg) override {315 MIB.addDef(PhysReg, RegState::Implicit);316 }317 318 MachineInstrBuilder MIB;319};320 321} // namespace322 323RISCVCallLowering::RISCVCallLowering(const RISCVTargetLowering &TLI)324 : CallLowering(&TLI) {}325 326/// Return true if scalable vector with ScalarTy is legal for lowering.327static bool isLegalElementTypeForRVV(Type *EltTy,328 const RISCVSubtarget &Subtarget) {329 if (EltTy->isPointerTy())330 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() : true;331 if (EltTy->isIntegerTy(1) || EltTy->isIntegerTy(8) ||332 EltTy->isIntegerTy(16) || EltTy->isIntegerTy(32))333 return true;334 if (EltTy->isIntegerTy(64))335 return Subtarget.hasVInstructionsI64();336 if (EltTy->isHalfTy())337 return Subtarget.hasVInstructionsF16Minimal();338 if (EltTy->isBFloatTy())339 return Subtarget.hasVInstructionsBF16Minimal();340 if (EltTy->isFloatTy())341 return Subtarget.hasVInstructionsF32();342 if (EltTy->isDoubleTy())343 return Subtarget.hasVInstructionsF64();344 return false;345}346 347// TODO: Support all argument types.348// TODO: Remove IsLowerArgs argument by adding support for vectors in lowerCall.349static bool isSupportedArgumentType(Type *T, const RISCVSubtarget &Subtarget,350 bool IsLowerArgs = false) {351 if (T->isIntegerTy())352 return true;353 if (T->isHalfTy() || T->isFloatTy() || T->isDoubleTy() || T->isFP128Ty())354 return true;355 if (T->isPointerTy())356 return true;357 if (T->isArrayTy())358 return isSupportedArgumentType(T->getArrayElementType(), Subtarget,359 IsLowerArgs);360 // TODO: Support fixed vector types.361 if (IsLowerArgs && T->isVectorTy() && Subtarget.hasVInstructions() &&362 T->isScalableTy() &&363 isLegalElementTypeForRVV(T->getScalarType(), Subtarget))364 return true;365 return false;366}367 368// TODO: Only integer, pointer and aggregate types are supported now.369// TODO: Remove IsLowerRetVal argument by adding support for vectors in370// lowerCall.371static bool isSupportedReturnType(Type *T, const RISCVSubtarget &Subtarget,372 bool IsLowerRetVal = false) {373 if (T->isIntegerTy() || T->isFloatingPointTy() || T->isPointerTy())374 return true;375 376 if (T->isArrayTy())377 return isSupportedReturnType(T->getArrayElementType(), Subtarget);378 379 if (T->isStructTy()) {380 auto StructT = cast<StructType>(T);381 for (unsigned i = 0, e = StructT->getNumElements(); i != e; ++i)382 if (!isSupportedReturnType(StructT->getElementType(i), Subtarget))383 return false;384 return true;385 }386 387 if (IsLowerRetVal && T->isVectorTy() && Subtarget.hasVInstructions() &&388 T->isScalableTy() &&389 isLegalElementTypeForRVV(T->getScalarType(), Subtarget))390 return true;391 392 return false;393}394 395bool RISCVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,396 const Value *Val, ArrayRef<Register> VRegs,397 FunctionLoweringInfo &FLI) const {398 assert(!Val == VRegs.empty() && "Return value without a vreg");399 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(RISCV::PseudoRET);400 401 if (!FLI.CanLowerReturn) {402 insertSRetStores(MIRBuilder, Val->getType(), VRegs, FLI.DemoteRegister);403 } else if (!VRegs.empty()) {404 const RISCVSubtarget &Subtarget =405 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();406 if (!isSupportedReturnType(Val->getType(), Subtarget,407 /*IsLowerRetVal=*/true))408 return false;409 410 MachineFunction &MF = MIRBuilder.getMF();411 const DataLayout &DL = MF.getDataLayout();412 const Function &F = MF.getFunction();413 CallingConv::ID CC = F.getCallingConv();414 415 ArgInfo OrigRetInfo(VRegs, Val->getType(), 0);416 setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F);417 418 SmallVector<ArgInfo, 4> SplitRetInfos;419 splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC);420 421 RISCVOutgoingValueAssigner Assigner(422 CC == CallingConv::Fast ? CC_RISCV_FastCC : CC_RISCV,423 /*IsRet=*/true);424 RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret);425 if (!determineAndHandleAssignments(Handler, Assigner, SplitRetInfos,426 MIRBuilder, CC, F.isVarArg()))427 return false;428 }429 430 MIRBuilder.insertInstr(Ret);431 return true;432}433 434bool RISCVCallLowering::canLowerReturn(MachineFunction &MF,435 CallingConv::ID CallConv,436 SmallVectorImpl<BaseArgInfo> &Outs,437 bool IsVarArg) const {438 SmallVector<CCValAssign, 16> ArgLocs;439 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs,440 MF.getFunction().getContext());441 442 for (unsigned I = 0, E = Outs.size(); I < E; ++I) {443 MVT VT = MVT::getVT(Outs[I].Ty);444 if (CC_RISCV(I, VT, VT, CCValAssign::Full, Outs[I].Flags[0], CCInfo,445 /*isRet=*/true, nullptr))446 return false;447 }448 return true;449}450 451/// If there are varargs that were passed in a0-a7, the data in those registers452/// must be copied to the varargs save area on the stack.453void RISCVCallLowering::saveVarArgRegisters(454 MachineIRBuilder &MIRBuilder, CallLowering::IncomingValueHandler &Handler,455 IncomingValueAssigner &Assigner, CCState &CCInfo) const {456 MachineFunction &MF = MIRBuilder.getMF();457 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();458 unsigned XLenInBytes = Subtarget.getXLen() / 8;459 ArrayRef<MCPhysReg> ArgRegs = RISCV::getArgGPRs(Subtarget.getTargetABI());460 MachineRegisterInfo &MRI = MF.getRegInfo();461 unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);462 MachineFrameInfo &MFI = MF.getFrameInfo();463 RISCVMachineFunctionInfo *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();464 465 // Size of the vararg save area. For now, the varargs save area is either466 // zero or large enough to hold a0-a7.467 int VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);468 int FI;469 470 // If all registers are allocated, then all varargs must be passed on the471 // stack and we don't need to save any argregs.472 if (VarArgsSaveSize == 0) {473 int VaArgOffset = Assigner.StackSize;474 FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);475 } else {476 int VaArgOffset = -VarArgsSaveSize;477 FI = MFI.CreateFixedObject(VarArgsSaveSize, VaArgOffset, true);478 479 // If saving an odd number of registers then create an extra stack slot to480 // ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures481 // offsets to even-numbered registered remain 2*XLEN-aligned.482 if (Idx % 2) {483 MFI.CreateFixedObject(XLenInBytes,484 VaArgOffset - static_cast<int>(XLenInBytes), true);485 VarArgsSaveSize += XLenInBytes;486 }487 488 const LLT p0 = LLT::pointer(MF.getDataLayout().getAllocaAddrSpace(),489 Subtarget.getXLen());490 const LLT sXLen = LLT::scalar(Subtarget.getXLen());491 492 auto FIN = MIRBuilder.buildFrameIndex(p0, FI);493 auto Offset = MIRBuilder.buildConstant(494 MRI.createGenericVirtualRegister(sXLen), XLenInBytes);495 496 // Copy the integer registers that may have been used for passing varargs497 // to the vararg save area.498 const MVT XLenVT = Subtarget.getXLenVT();499 for (unsigned I = Idx; I < ArgRegs.size(); ++I) {500 const Register VReg = MRI.createGenericVirtualRegister(sXLen);501 Handler.assignValueToReg(502 VReg, ArgRegs[I],503 CCValAssign::getReg(I + MF.getFunction().getNumOperands(), XLenVT,504 ArgRegs[I], XLenVT, CCValAssign::Full));505 auto MPO =506 MachinePointerInfo::getFixedStack(MF, FI, (I - Idx) * XLenInBytes);507 MIRBuilder.buildStore(VReg, FIN, MPO, inferAlignFromPtrInfo(MF, MPO));508 FIN = MIRBuilder.buildPtrAdd(MRI.createGenericVirtualRegister(p0),509 FIN.getReg(0), Offset);510 }511 }512 513 // Record the frame index of the first variable argument which is a value514 // necessary to G_VASTART.515 RVFI->setVarArgsFrameIndex(FI);516 RVFI->setVarArgsSaveSize(VarArgsSaveSize);517}518 519bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,520 const Function &F,521 ArrayRef<ArrayRef<Register>> VRegs,522 FunctionLoweringInfo &FLI) const {523 MachineFunction &MF = MIRBuilder.getMF();524 525 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();526 for (auto &Arg : F.args()) {527 if (!isSupportedArgumentType(Arg.getType(), Subtarget,528 /*IsLowerArgs=*/true))529 return false;530 }531 532 MachineRegisterInfo &MRI = MF.getRegInfo();533 const DataLayout &DL = MF.getDataLayout();534 CallingConv::ID CC = F.getCallingConv();535 536 SmallVector<ArgInfo, 32> SplitArgInfos;537 538 // Insert the hidden sret parameter if the return value won't fit in the539 // return registers.540 if (!FLI.CanLowerReturn)541 insertSRetIncomingArgument(F, SplitArgInfos, FLI.DemoteRegister, MRI, DL);542 543 unsigned Index = 0;544 for (auto &Arg : F.args()) {545 // Construct the ArgInfo object from destination register and argument type.546 ArgInfo AInfo(VRegs[Index], Arg.getType(), Index);547 setArgFlags(AInfo, Index + AttributeList::FirstArgIndex, DL, F);548 549 // Handle any required merging from split value types from physical550 // registers into the desired VReg. ArgInfo objects are constructed551 // correspondingly and appended to SplitArgInfos.552 splitToValueTypes(AInfo, SplitArgInfos, DL, CC);553 554 ++Index;555 }556 557 RISCVIncomingValueAssigner Assigner(CC == CallingConv::Fast ? CC_RISCV_FastCC558 : CC_RISCV,559 /*IsRet=*/false);560 RISCVFormalArgHandler Handler(MIRBuilder, MF.getRegInfo());561 562 SmallVector<CCValAssign, 16> ArgLocs;563 CCState CCInfo(CC, F.isVarArg(), MIRBuilder.getMF(), ArgLocs, F.getContext());564 if (!determineAssignments(Assigner, SplitArgInfos, CCInfo) ||565 !handleAssignments(Handler, SplitArgInfos, CCInfo, ArgLocs, MIRBuilder))566 return false;567 568 if (F.isVarArg())569 saveVarArgRegisters(MIRBuilder, Handler, Assigner, CCInfo);570 571 return true;572}573 574bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,575 CallLoweringInfo &Info) const {576 MachineFunction &MF = MIRBuilder.getMF();577 const DataLayout &DL = MF.getDataLayout();578 CallingConv::ID CC = Info.CallConv;579 580 const RISCVSubtarget &Subtarget =581 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();582 for (auto &AInfo : Info.OrigArgs) {583 if (!isSupportedArgumentType(AInfo.Ty, Subtarget))584 return false;585 if (AInfo.Flags[0].isByVal())586 return false;587 }588 589 if (!Info.OrigRet.Ty->isVoidTy() &&590 !isSupportedReturnType(Info.OrigRet.Ty, Subtarget))591 return false;592 593 MachineInstrBuilder CallSeqStart =594 MIRBuilder.buildInstr(RISCV::ADJCALLSTACKDOWN);595 596 SmallVector<ArgInfo, 32> SplitArgInfos;597 for (auto &AInfo : Info.OrigArgs) {598 // Handle any required unmerging of split value types from a given VReg into599 // physical registers. ArgInfo objects are constructed correspondingly and600 // appended to SplitArgInfos.601 splitToValueTypes(AInfo, SplitArgInfos, DL, CC);602 }603 604 // TODO: Support tail calls.605 Info.IsTailCall = false;606 607 // Select the recommended relocation type R_RISCV_CALL_PLT.608 if (!Info.Callee.isReg())609 Info.Callee.setTargetFlags(RISCVII::MO_CALL);610 611 MachineInstrBuilder Call =612 MIRBuilder613 .buildInstrNoInsert(Info.Callee.isReg() ? RISCV::PseudoCALLIndirect614 : RISCV::PseudoCALL)615 .add(Info.Callee);616 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();617 Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));618 619 RISCVOutgoingValueAssigner ArgAssigner(620 CC == CallingConv::Fast ? CC_RISCV_FastCC : CC_RISCV,621 /*IsRet=*/false);622 RISCVOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), Call);623 if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos,624 MIRBuilder, CC, Info.IsVarArg))625 return false;626 627 MIRBuilder.insertInstr(Call);628 629 CallSeqStart.addImm(ArgAssigner.StackSize).addImm(0);630 MIRBuilder.buildInstr(RISCV::ADJCALLSTACKUP)631 .addImm(ArgAssigner.StackSize)632 .addImm(0);633 634 // If Callee is a reg, since it is used by a target specific635 // instruction, it must have a register class matching the636 // constraint of that instruction.637 if (Call->getOperand(0).isReg())638 constrainOperandRegClass(MF, *TRI, MF.getRegInfo(),639 *Subtarget.getInstrInfo(),640 *Subtarget.getRegBankInfo(), *Call,641 Call->getDesc(), Call->getOperand(0), 0);642 643 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {644 SmallVector<ArgInfo, 4> SplitRetInfos;645 splitToValueTypes(Info.OrigRet, SplitRetInfos, DL, CC);646 647 RISCVIncomingValueAssigner RetAssigner(648 CC == CallingConv::Fast ? CC_RISCV_FastCC : CC_RISCV,649 /*IsRet=*/true);650 RISCVCallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Call);651 if (!determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos,652 MIRBuilder, CC, Info.IsVarArg))653 return false;654 }655 656 if (!Info.CanLowerReturn)657 insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs,658 Info.DemoteRegister, Info.DemoteStackIndex);659 660 return true;661}662