Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
213799 views
//===-- RISCVCallingConv.cpp - RISC-V Custom CC Routines ------------------===//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// This file contains the custom routines for the RISC-V Calling Convention.9//10//===----------------------------------------------------------------------===//1112#include "RISCVCallingConv.h"13#include "RISCVSubtarget.h"14#include "llvm/IR/DataLayout.h"15#include "llvm/IR/Module.h"16#include "llvm/MC/MCRegister.h"1718using namespace llvm;1920// Calling Convention Implementation.21// The expectations for frontend ABI lowering vary from target to target.22// Ideally, an LLVM frontend would be able to avoid worrying about many ABI23// details, but this is a longer term goal. For now, we simply try to keep the24// role of the frontend as simple and well-defined as possible. The rules can25// be summarised as:26// * Never split up large scalar arguments. We handle them here.27// * If a hardfloat calling convention is being used, and the struct may be28// passed in a pair of registers (fp+fp, int+fp), and both registers are29// available, then pass as two separate arguments. If either the GPRs or FPRs30// are exhausted, then pass according to the rule below.31// * If a struct could never be passed in registers or directly in a stack32// slot (as it is larger than 2*XLEN and the floating point rules don't33// apply), then pass it using a pointer with the byval attribute.34// * If a struct is less than 2*XLEN, then coerce to either a two-element35// word-sized array or a 2*XLEN scalar (depending on alignment).36// * The frontend can determine whether a struct is returned by reference or37// not based on its size and fields. If it will be returned by reference, the38// frontend must modify the prototype so a pointer with the sret annotation is39// passed as the first argument. This is not necessary for large scalar40// returns.41// * Struct return values and varargs should be coerced to structs containing42// register-size fields in the same situations they would be for fixed43// arguments.4445static const MCPhysReg ArgFPR16s[] = {RISCV::F10_H, RISCV::F11_H, RISCV::F12_H,46RISCV::F13_H, RISCV::F14_H, RISCV::F15_H,47RISCV::F16_H, RISCV::F17_H};48static const MCPhysReg ArgFPR32s[] = {RISCV::F10_F, RISCV::F11_F, RISCV::F12_F,49RISCV::F13_F, RISCV::F14_F, RISCV::F15_F,50RISCV::F16_F, RISCV::F17_F};51static const MCPhysReg ArgFPR64s[] = {RISCV::F10_D, RISCV::F11_D, RISCV::F12_D,52RISCV::F13_D, RISCV::F14_D, RISCV::F15_D,53RISCV::F16_D, RISCV::F17_D};54// This is an interim calling convention and it may be changed in the future.55static const MCPhysReg ArgVRs[] = {56RISCV::V8, RISCV::V9, RISCV::V10, RISCV::V11, RISCV::V12, RISCV::V13,57RISCV::V14, RISCV::V15, RISCV::V16, RISCV::V17, RISCV::V18, RISCV::V19,58RISCV::V20, RISCV::V21, RISCV::V22, RISCV::V23};59static const MCPhysReg ArgVRM2s[] = {RISCV::V8M2, RISCV::V10M2, RISCV::V12M2,60RISCV::V14M2, RISCV::V16M2, RISCV::V18M2,61RISCV::V20M2, RISCV::V22M2};62static const MCPhysReg ArgVRM4s[] = {RISCV::V8M4, RISCV::V12M4, RISCV::V16M4,63RISCV::V20M4};64static const MCPhysReg ArgVRM8s[] = {RISCV::V8M8, RISCV::V16M8};65static const MCPhysReg ArgVRN2M1s[] = {66RISCV::V8_V9, RISCV::V9_V10, RISCV::V10_V11, RISCV::V11_V12,67RISCV::V12_V13, RISCV::V13_V14, RISCV::V14_V15, RISCV::V15_V16,68RISCV::V16_V17, RISCV::V17_V18, RISCV::V18_V19, RISCV::V19_V20,69RISCV::V20_V21, RISCV::V21_V22, RISCV::V22_V23};70static const MCPhysReg ArgVRN3M1s[] = {71RISCV::V8_V9_V10, RISCV::V9_V10_V11, RISCV::V10_V11_V12,72RISCV::V11_V12_V13, RISCV::V12_V13_V14, RISCV::V13_V14_V15,73RISCV::V14_V15_V16, RISCV::V15_V16_V17, RISCV::V16_V17_V18,74RISCV::V17_V18_V19, RISCV::V18_V19_V20, RISCV::V19_V20_V21,75RISCV::V20_V21_V22, RISCV::V21_V22_V23};76static const MCPhysReg ArgVRN4M1s[] = {77RISCV::V8_V9_V10_V11, RISCV::V9_V10_V11_V12, RISCV::V10_V11_V12_V13,78RISCV::V11_V12_V13_V14, RISCV::V12_V13_V14_V15, RISCV::V13_V14_V15_V16,79RISCV::V14_V15_V16_V17, RISCV::V15_V16_V17_V18, RISCV::V16_V17_V18_V19,80RISCV::V17_V18_V19_V20, RISCV::V18_V19_V20_V21, RISCV::V19_V20_V21_V22,81RISCV::V20_V21_V22_V23};82static const MCPhysReg ArgVRN5M1s[] = {83RISCV::V8_V9_V10_V11_V12, RISCV::V9_V10_V11_V12_V13,84RISCV::V10_V11_V12_V13_V14, RISCV::V11_V12_V13_V14_V15,85RISCV::V12_V13_V14_V15_V16, RISCV::V13_V14_V15_V16_V17,86RISCV::V14_V15_V16_V17_V18, RISCV::V15_V16_V17_V18_V19,87RISCV::V16_V17_V18_V19_V20, RISCV::V17_V18_V19_V20_V21,88RISCV::V18_V19_V20_V21_V22, RISCV::V19_V20_V21_V22_V23};89static const MCPhysReg ArgVRN6M1s[] = {90RISCV::V8_V9_V10_V11_V12_V13, RISCV::V9_V10_V11_V12_V13_V14,91RISCV::V10_V11_V12_V13_V14_V15, RISCV::V11_V12_V13_V14_V15_V16,92RISCV::V12_V13_V14_V15_V16_V17, RISCV::V13_V14_V15_V16_V17_V18,93RISCV::V14_V15_V16_V17_V18_V19, RISCV::V15_V16_V17_V18_V19_V20,94RISCV::V16_V17_V18_V19_V20_V21, RISCV::V17_V18_V19_V20_V21_V22,95RISCV::V18_V19_V20_V21_V22_V23};96static const MCPhysReg ArgVRN7M1s[] = {97RISCV::V8_V9_V10_V11_V12_V13_V14, RISCV::V9_V10_V11_V12_V13_V14_V15,98RISCV::V10_V11_V12_V13_V14_V15_V16, RISCV::V11_V12_V13_V14_V15_V16_V17,99RISCV::V12_V13_V14_V15_V16_V17_V18, RISCV::V13_V14_V15_V16_V17_V18_V19,100RISCV::V14_V15_V16_V17_V18_V19_V20, RISCV::V15_V16_V17_V18_V19_V20_V21,101RISCV::V16_V17_V18_V19_V20_V21_V22, RISCV::V17_V18_V19_V20_V21_V22_V23};102static const MCPhysReg ArgVRN8M1s[] = {RISCV::V8_V9_V10_V11_V12_V13_V14_V15,103RISCV::V9_V10_V11_V12_V13_V14_V15_V16,104RISCV::V10_V11_V12_V13_V14_V15_V16_V17,105RISCV::V11_V12_V13_V14_V15_V16_V17_V18,106RISCV::V12_V13_V14_V15_V16_V17_V18_V19,107RISCV::V13_V14_V15_V16_V17_V18_V19_V20,108RISCV::V14_V15_V16_V17_V18_V19_V20_V21,109RISCV::V15_V16_V17_V18_V19_V20_V21_V22,110RISCV::V16_V17_V18_V19_V20_V21_V22_V23};111static const MCPhysReg ArgVRN2M2s[] = {RISCV::V8M2_V10M2, RISCV::V10M2_V12M2,112RISCV::V12M2_V14M2, RISCV::V14M2_V16M2,113RISCV::V16M2_V18M2, RISCV::V18M2_V20M2,114RISCV::V20M2_V22M2};115static const MCPhysReg ArgVRN3M2s[] = {116RISCV::V8M2_V10M2_V12M2, RISCV::V10M2_V12M2_V14M2,117RISCV::V12M2_V14M2_V16M2, RISCV::V14M2_V16M2_V18M2,118RISCV::V16M2_V18M2_V20M2, RISCV::V18M2_V20M2_V22M2};119static const MCPhysReg ArgVRN4M2s[] = {120RISCV::V8M2_V10M2_V12M2_V14M2, RISCV::V10M2_V12M2_V14M2_V16M2,121RISCV::V12M2_V14M2_V16M2_V18M2, RISCV::V14M2_V16M2_V18M2_V20M2,122RISCV::V16M2_V18M2_V20M2_V22M2};123static const MCPhysReg ArgVRN2M4s[] = {RISCV::V8M4_V12M4, RISCV::V12M4_V16M4,124RISCV::V16M4_V20M4};125126ArrayRef<MCPhysReg> RISCV::getArgGPRs(const RISCVABI::ABI ABI) {127// The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except128// the ILP32E ABI.129static const MCPhysReg ArgIGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,130RISCV::X13, RISCV::X14, RISCV::X15,131RISCV::X16, RISCV::X17};132// The GPRs used for passing arguments in the ILP32E/LP64E ABI.133static const MCPhysReg ArgEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,134RISCV::X13, RISCV::X14, RISCV::X15};135136if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)137return ArrayRef(ArgEGPRs);138139return ArrayRef(ArgIGPRs);140}141142static ArrayRef<MCPhysReg> getArgGPR16s(const RISCVABI::ABI ABI) {143// The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except144// the ILP32E ABI.145static const MCPhysReg ArgIGPRs[] = {RISCV::X10_H, RISCV::X11_H, RISCV::X12_H,146RISCV::X13_H, RISCV::X14_H, RISCV::X15_H,147RISCV::X16_H, RISCV::X17_H};148// The GPRs used for passing arguments in the ILP32E/LP64E ABI.149static const MCPhysReg ArgEGPRs[] = {RISCV::X10_H, RISCV::X11_H,150RISCV::X12_H, RISCV::X13_H,151RISCV::X14_H, RISCV::X15_H};152153if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)154return ArrayRef(ArgEGPRs);155156return ArrayRef(ArgIGPRs);157}158159static ArrayRef<MCPhysReg> getArgGPR32s(const RISCVABI::ABI ABI) {160// The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except161// the ILP32E ABI.162static const MCPhysReg ArgIGPRs[] = {RISCV::X10_W, RISCV::X11_W, RISCV::X12_W,163RISCV::X13_W, RISCV::X14_W, RISCV::X15_W,164RISCV::X16_W, RISCV::X17_W};165// The GPRs used for passing arguments in the ILP32E/LP64E ABI.166static const MCPhysReg ArgEGPRs[] = {RISCV::X10_W, RISCV::X11_W,167RISCV::X12_W, RISCV::X13_W,168RISCV::X14_W, RISCV::X15_W};169170if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)171return ArrayRef(ArgEGPRs);172173return ArrayRef(ArgIGPRs);174}175176static ArrayRef<MCPhysReg> getFastCCArgGPRs(const RISCVABI::ABI ABI) {177// The GPRs used for passing arguments in the FastCC, X5 and X6 might be used178// for save-restore libcall, so we don't use them.179// Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.180static const MCPhysReg FastCCIGPRs[] = {181RISCV::X10, RISCV::X11, RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15,182RISCV::X16, RISCV::X17, RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31};183184// The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.185static const MCPhysReg FastCCEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,186RISCV::X13, RISCV::X14, RISCV::X15};187188if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)189return ArrayRef(FastCCEGPRs);190191return ArrayRef(FastCCIGPRs);192}193194static ArrayRef<MCPhysReg> getFastCCArgGPRF16s(const RISCVABI::ABI ABI) {195// The GPRs used for passing arguments in the FastCC, X5 and X6 might be used196// for save-restore libcall, so we don't use them.197// Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.198static const MCPhysReg FastCCIGPRs[] = {199RISCV::X10_H, RISCV::X11_H, RISCV::X12_H, RISCV::X13_H,200RISCV::X14_H, RISCV::X15_H, RISCV::X16_H, RISCV::X17_H,201RISCV::X28_H, RISCV::X29_H, RISCV::X30_H, RISCV::X31_H};202203// The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.204static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_H, RISCV::X11_H,205RISCV::X12_H, RISCV::X13_H,206RISCV::X14_H, RISCV::X15_H};207208if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)209return ArrayRef(FastCCEGPRs);210211return ArrayRef(FastCCIGPRs);212}213214static ArrayRef<MCPhysReg> getFastCCArgGPRF32s(const RISCVABI::ABI ABI) {215// The GPRs used for passing arguments in the FastCC, X5 and X6 might be used216// for save-restore libcall, so we don't use them.217// Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.218static const MCPhysReg FastCCIGPRs[] = {219RISCV::X10_W, RISCV::X11_W, RISCV::X12_W, RISCV::X13_W,220RISCV::X14_W, RISCV::X15_W, RISCV::X16_W, RISCV::X17_W,221RISCV::X28_W, RISCV::X29_W, RISCV::X30_W, RISCV::X31_W};222223// The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.224static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_W, RISCV::X11_W,225RISCV::X12_W, RISCV::X13_W,226RISCV::X14_W, RISCV::X15_W};227228if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)229return ArrayRef(FastCCEGPRs);230231return ArrayRef(FastCCIGPRs);232}233234// Pass a 2*XLEN argument that has been split into two XLEN values through235// registers or the stack as necessary.236static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1,237ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2,238MVT ValVT2, MVT LocVT2,239ISD::ArgFlagsTy ArgFlags2, bool EABI) {240unsigned XLenInBytes = XLen / 8;241const RISCVSubtarget &STI =242State.getMachineFunction().getSubtarget<RISCVSubtarget>();243ArrayRef<MCPhysReg> ArgGPRs = RISCV::getArgGPRs(STI.getTargetABI());244245if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {246// At least one half can be passed via register.247State.addLoc(CCValAssign::getReg(VA1.getValNo(), VA1.getValVT(), Reg,248VA1.getLocVT(), CCValAssign::Full));249} else {250// Both halves must be passed on the stack, with proper alignment.251// TODO: To be compatible with GCC's behaviors, we force them to have 4-byte252// alignment. This behavior may be changed when RV32E/ILP32E is ratified.253Align StackAlign(XLenInBytes);254if (!EABI || XLen != 32)255StackAlign = std::max(StackAlign, ArgFlags1.getNonZeroOrigAlign());256State.addLoc(257CCValAssign::getMem(VA1.getValNo(), VA1.getValVT(),258State.AllocateStack(XLenInBytes, StackAlign),259VA1.getLocVT(), CCValAssign::Full));260State.addLoc(CCValAssign::getMem(261ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)),262LocVT2, CCValAssign::Full));263return false;264}265266if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {267// The second half can also be passed via register.268State.addLoc(269CCValAssign::getReg(ValNo2, ValVT2, Reg, LocVT2, CCValAssign::Full));270} else {271// The second half is passed via the stack, without additional alignment.272State.addLoc(CCValAssign::getMem(273ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)),274LocVT2, CCValAssign::Full));275}276277return false;278}279280static MCRegister allocateRVVReg(MVT ValVT, unsigned ValNo, CCState &State,281const RISCVTargetLowering &TLI) {282const TargetRegisterClass *RC = TLI.getRegClassFor(ValVT);283if (RC == &RISCV::VRRegClass) {284// Assign the first mask argument to V0.285// This is an interim calling convention and it may be changed in the286// future.287if (ValVT.getVectorElementType() == MVT::i1)288if (MCRegister Reg = State.AllocateReg(RISCV::V0))289return Reg;290return State.AllocateReg(ArgVRs);291}292if (RC == &RISCV::VRM2RegClass)293return State.AllocateReg(ArgVRM2s);294if (RC == &RISCV::VRM4RegClass)295return State.AllocateReg(ArgVRM4s);296if (RC == &RISCV::VRM8RegClass)297return State.AllocateReg(ArgVRM8s);298if (RC == &RISCV::VRN2M1RegClass)299return State.AllocateReg(ArgVRN2M1s);300if (RC == &RISCV::VRN3M1RegClass)301return State.AllocateReg(ArgVRN3M1s);302if (RC == &RISCV::VRN4M1RegClass)303return State.AllocateReg(ArgVRN4M1s);304if (RC == &RISCV::VRN5M1RegClass)305return State.AllocateReg(ArgVRN5M1s);306if (RC == &RISCV::VRN6M1RegClass)307return State.AllocateReg(ArgVRN6M1s);308if (RC == &RISCV::VRN7M1RegClass)309return State.AllocateReg(ArgVRN7M1s);310if (RC == &RISCV::VRN8M1RegClass)311return State.AllocateReg(ArgVRN8M1s);312if (RC == &RISCV::VRN2M2RegClass)313return State.AllocateReg(ArgVRN2M2s);314if (RC == &RISCV::VRN3M2RegClass)315return State.AllocateReg(ArgVRN3M2s);316if (RC == &RISCV::VRN4M2RegClass)317return State.AllocateReg(ArgVRN4M2s);318if (RC == &RISCV::VRN2M4RegClass)319return State.AllocateReg(ArgVRN2M4s);320llvm_unreachable("Unhandled register class for ValueType");321}322323// Implements the RISC-V calling convention. Returns true upon failure.324bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,325CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,326CCState &State, bool IsFixed, bool IsRet, Type *OrigTy) {327const MachineFunction &MF = State.getMachineFunction();328const DataLayout &DL = MF.getDataLayout();329const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();330const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering();331332unsigned XLen = Subtarget.getXLen();333MVT XLenVT = Subtarget.getXLenVT();334335if (ArgFlags.isNest()) {336// Static chain parameter must not be passed in normal argument registers,337// so we assign t2/t3 for it as done in GCC's338// __builtin_call_with_static_chain339bool HasCFBranch =340Subtarget.hasStdExtZicfilp() &&341MF.getFunction().getParent()->getModuleFlag("cf-protection-branch");342343// Normal: t2, Branch control flow protection: t3344const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7;345346RISCVABI::ABI ABI = Subtarget.getTargetABI();347if (HasCFBranch &&348(ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E))349reportFatalUsageError(350"Nested functions with control flow protection are not "351"usable with ILP32E or LP64E ABI.");352if (MCRegister Reg = State.AllocateReg(StaticChainReg)) {353State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));354return false;355}356}357358// Any return value split in to more than two values can't be returned359// directly. Vectors are returned via the available vector registers.360if (!LocVT.isVector() && IsRet && ValNo > 1)361return true;362363// UseGPRForF16_F32 if targeting one of the soft-float ABIs, if passing a364// variadic argument, or if no F16/F32 argument registers are available.365bool UseGPRForF16_F32 = true;366// UseGPRForF64 if targeting soft-float ABIs or an FLEN=32 ABI, if passing a367// variadic argument, or if no F64 argument registers are available.368bool UseGPRForF64 = true;369370RISCVABI::ABI ABI = Subtarget.getTargetABI();371switch (ABI) {372default:373llvm_unreachable("Unexpected ABI");374case RISCVABI::ABI_ILP32:375case RISCVABI::ABI_ILP32E:376case RISCVABI::ABI_LP64:377case RISCVABI::ABI_LP64E:378break;379case RISCVABI::ABI_ILP32F:380case RISCVABI::ABI_LP64F:381UseGPRForF16_F32 = !IsFixed;382break;383case RISCVABI::ABI_ILP32D:384case RISCVABI::ABI_LP64D:385UseGPRForF16_F32 = !IsFixed;386UseGPRForF64 = !IsFixed;387break;388}389390if ((LocVT == MVT::f16 || LocVT == MVT::bf16) && !UseGPRForF16_F32) {391if (MCRegister Reg = State.AllocateReg(ArgFPR16s)) {392State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));393return false;394}395}396397if (LocVT == MVT::f32 && !UseGPRForF16_F32) {398if (MCRegister Reg = State.AllocateReg(ArgFPR32s)) {399State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));400return false;401}402}403404if (LocVT == MVT::f64 && !UseGPRForF64) {405if (MCRegister Reg = State.AllocateReg(ArgFPR64s)) {406State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));407return false;408}409}410411if ((ValVT == MVT::f16 && Subtarget.hasStdExtZhinxmin())) {412if (MCRegister Reg = State.AllocateReg(getArgGPR16s(ABI))) {413State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));414return false;415}416}417418if (ValVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {419if (MCRegister Reg = State.AllocateReg(getArgGPR32s(ABI))) {420State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));421return false;422}423}424425ArrayRef<MCPhysReg> ArgGPRs = RISCV::getArgGPRs(ABI);426427// Zdinx use GPR without a bitcast when possible.428if (LocVT == MVT::f64 && XLen == 64 && Subtarget.hasStdExtZdinx()) {429if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {430State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));431return false;432}433}434435// FP smaller than XLen, uses custom GPR.436if (LocVT == MVT::f16 || LocVT == MVT::bf16 ||437(LocVT == MVT::f32 && XLen == 64)) {438if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {439LocVT = XLenVT;440State.addLoc(441CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));442return false;443}444}445446// Bitcast FP to GPR if we can use a GPR register.447if ((XLen == 32 && LocVT == MVT::f32) || (XLen == 64 && LocVT == MVT::f64)) {448if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {449LocVT = XLenVT;450LocInfo = CCValAssign::BCvt;451State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));452return false;453}454}455456// If this is a variadic argument, the RISC-V calling convention requires457// that it is assigned an 'even' or 'aligned' register if it has 8-byte458// alignment (RV32) or 16-byte alignment (RV64). An aligned register should459// be used regardless of whether the original argument was split during460// legalisation or not. The argument will not be passed by registers if the461// original type is larger than 2*XLEN, so the register alignment rule does462// not apply.463// TODO: To be compatible with GCC's behaviors, we don't align registers464// currently if we are using ILP32E calling convention. This behavior may be465// changed when RV32E/ILP32E is ratified.466unsigned TwoXLenInBytes = (2 * XLen) / 8;467if (!IsFixed && ArgFlags.getNonZeroOrigAlign() == TwoXLenInBytes &&468DL.getTypeAllocSize(OrigTy) == TwoXLenInBytes &&469ABI != RISCVABI::ABI_ILP32E) {470unsigned RegIdx = State.getFirstUnallocated(ArgGPRs);471// Skip 'odd' register if necessary.472if (RegIdx != std::size(ArgGPRs) && RegIdx % 2 == 1)473State.AllocateReg(ArgGPRs);474}475476SmallVectorImpl<CCValAssign> &PendingLocs = State.getPendingLocs();477SmallVectorImpl<ISD::ArgFlagsTy> &PendingArgFlags =478State.getPendingArgFlags();479480assert(PendingLocs.size() == PendingArgFlags.size() &&481"PendingLocs and PendingArgFlags out of sync");482483// Handle passing f64 on RV32D with a soft float ABI or when floating point484// registers are exhausted.485if (XLen == 32 && LocVT == MVT::f64) {486assert(PendingLocs.empty() && "Can't lower f64 if it is split");487// Depending on available argument GPRS, f64 may be passed in a pair of488// GPRs, split between a GPR and the stack, or passed completely on the489// stack. LowerCall/LowerFormalArguments/LowerReturn must recognise these490// cases.491MCRegister Reg = State.AllocateReg(ArgGPRs);492if (!Reg) {493int64_t StackOffset = State.AllocateStack(8, Align(8));494State.addLoc(495CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));496return false;497}498LocVT = MVT::i32;499State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));500MCRegister HiReg = State.AllocateReg(ArgGPRs);501if (HiReg) {502State.addLoc(503CCValAssign::getCustomReg(ValNo, ValVT, HiReg, LocVT, LocInfo));504} else {505int64_t StackOffset = State.AllocateStack(4, Align(4));506State.addLoc(507CCValAssign::getCustomMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));508}509return false;510}511512// Split arguments might be passed indirectly, so keep track of the pending513// values. Split vectors are passed via a mix of registers and indirectly, so514// treat them as we would any other argument.515if (ValVT.isScalarInteger() && (ArgFlags.isSplit() || !PendingLocs.empty())) {516LocVT = XLenVT;517LocInfo = CCValAssign::Indirect;518PendingLocs.push_back(519CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo));520PendingArgFlags.push_back(ArgFlags);521if (!ArgFlags.isSplitEnd()) {522return false;523}524}525526// If the split argument only had two elements, it should be passed directly527// in registers or on the stack.528if (ValVT.isScalarInteger() && ArgFlags.isSplitEnd() &&529PendingLocs.size() <= 2) {530assert(PendingLocs.size() == 2 && "Unexpected PendingLocs.size()");531// Apply the normal calling convention rules to the first half of the532// split argument.533CCValAssign VA = PendingLocs[0];534ISD::ArgFlagsTy AF = PendingArgFlags[0];535PendingLocs.clear();536PendingArgFlags.clear();537return CC_RISCVAssign2XLen(538XLen, State, VA, AF, ValNo, ValVT, LocVT, ArgFlags,539ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E);540}541542// Allocate to a register if possible, or else a stack slot.543MCRegister Reg;544unsigned StoreSizeBytes = XLen / 8;545Align StackAlign = Align(XLen / 8);546547if (ValVT.isVector() || ValVT.isRISCVVectorTuple()) {548Reg = allocateRVVReg(ValVT, ValNo, State, TLI);549if (Reg) {550// Fixed-length vectors are located in the corresponding scalable-vector551// container types.552if (ValVT.isFixedLengthVector()) {553LocVT = TLI.getContainerForFixedLengthVector(LocVT);554State.addLoc(555CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));556return false;557}558} else {559// For return values, the vector must be passed fully via registers or560// via the stack.561// FIXME: The proposed vector ABI only mandates v8-v15 for return values,562// but we're using all of them.563if (IsRet)564return true;565// Try using a GPR to pass the address566if ((Reg = State.AllocateReg(ArgGPRs))) {567LocVT = XLenVT;568LocInfo = CCValAssign::Indirect;569} else if (ValVT.isScalableVector()) {570LocVT = XLenVT;571LocInfo = CCValAssign::Indirect;572} else {573StoreSizeBytes = ValVT.getStoreSize();574// Align vectors to their element sizes, being careful for vXi1575// vectors.576StackAlign = MaybeAlign(ValVT.getScalarSizeInBits() / 8).valueOrOne();577}578}579} else {580Reg = State.AllocateReg(ArgGPRs);581}582583int64_t StackOffset =584Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);585586// If we reach this point and PendingLocs is non-empty, we must be at the587// end of a split argument that must be passed indirectly.588if (!PendingLocs.empty()) {589assert(ArgFlags.isSplitEnd() && "Expected ArgFlags.isSplitEnd()");590assert(PendingLocs.size() > 2 && "Unexpected PendingLocs.size()");591592for (auto &It : PendingLocs) {593if (Reg)594It.convertToReg(Reg);595else596It.convertToMem(StackOffset);597State.addLoc(It);598}599PendingLocs.clear();600PendingArgFlags.clear();601return false;602}603604assert(((ValVT.isFloatingPoint() && !ValVT.isVector()) || LocVT == XLenVT ||605(TLI.getSubtarget().hasVInstructions() &&606(ValVT.isVector() || ValVT.isRISCVVectorTuple()))) &&607"Expected an XLenVT or vector types at this stage");608609if (Reg) {610State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));611return false;612}613614State.addLoc(CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));615return false;616}617618// FastCC has less than 1% performance improvement for some particular619// benchmark. But theoretically, it may have benefit for some cases.620bool llvm::CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT,621CCValAssign::LocInfo LocInfo,622ISD::ArgFlagsTy ArgFlags, CCState &State,623bool IsFixed, bool IsRet, Type *OrigTy) {624const MachineFunction &MF = State.getMachineFunction();625const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();626const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering();627RISCVABI::ABI ABI = Subtarget.getTargetABI();628629if ((LocVT == MVT::f16 && Subtarget.hasStdExtZfhmin()) ||630(LocVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin())) {631static const MCPhysReg FPR16List[] = {632RISCV::F10_H, RISCV::F11_H, RISCV::F12_H, RISCV::F13_H, RISCV::F14_H,633RISCV::F15_H, RISCV::F16_H, RISCV::F17_H, RISCV::F0_H, RISCV::F1_H,634RISCV::F2_H, RISCV::F3_H, RISCV::F4_H, RISCV::F5_H, RISCV::F6_H,635RISCV::F7_H, RISCV::F28_H, RISCV::F29_H, RISCV::F30_H, RISCV::F31_H};636if (MCRegister Reg = State.AllocateReg(FPR16List)) {637State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));638return false;639}640}641642if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {643static const MCPhysReg FPR32List[] = {644RISCV::F10_F, RISCV::F11_F, RISCV::F12_F, RISCV::F13_F, RISCV::F14_F,645RISCV::F15_F, RISCV::F16_F, RISCV::F17_F, RISCV::F0_F, RISCV::F1_F,646RISCV::F2_F, RISCV::F3_F, RISCV::F4_F, RISCV::F5_F, RISCV::F6_F,647RISCV::F7_F, RISCV::F28_F, RISCV::F29_F, RISCV::F30_F, RISCV::F31_F};648if (MCRegister Reg = State.AllocateReg(FPR32List)) {649State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));650return false;651}652}653654if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {655static const MCPhysReg FPR64List[] = {656RISCV::F10_D, RISCV::F11_D, RISCV::F12_D, RISCV::F13_D, RISCV::F14_D,657RISCV::F15_D, RISCV::F16_D, RISCV::F17_D, RISCV::F0_D, RISCV::F1_D,658RISCV::F2_D, RISCV::F3_D, RISCV::F4_D, RISCV::F5_D, RISCV::F6_D,659RISCV::F7_D, RISCV::F28_D, RISCV::F29_D, RISCV::F30_D, RISCV::F31_D};660if (MCRegister Reg = State.AllocateReg(FPR64List)) {661State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));662return false;663}664}665666MVT XLenVT = Subtarget.getXLenVT();667668// Check if there is an available GPRF16 before hitting the stack.669if ((LocVT == MVT::f16 && Subtarget.hasStdExtZhinxmin())) {670if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF16s(ABI))) {671State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));672return false;673}674}675676// Check if there is an available GPRF32 before hitting the stack.677if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {678if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF32s(ABI))) {679State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));680return false;681}682}683684// Check if there is an available GPR before hitting the stack.685if (LocVT == MVT::f64 && Subtarget.is64Bit() && Subtarget.hasStdExtZdinx()) {686if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) {687if (LocVT.getSizeInBits() != Subtarget.getXLen()) {688LocVT = XLenVT;689State.addLoc(690CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));691return false;692}693State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));694return false;695}696}697698ArrayRef<MCPhysReg> ArgGPRs = getFastCCArgGPRs(ABI);699700if (LocVT.isVector()) {701if (MCRegister Reg = allocateRVVReg(ValVT, ValNo, State, TLI)) {702// Fixed-length vectors are located in the corresponding scalable-vector703// container types.704if (LocVT.isFixedLengthVector()) {705LocVT = TLI.getContainerForFixedLengthVector(LocVT);706State.addLoc(707CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));708return false;709}710State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));711return false;712}713714// Pass scalable vectors indirectly. Pass fixed vectors indirectly if we715// have a free GPR.716if (LocVT.isScalableVector() ||717State.getFirstUnallocated(ArgGPRs) != ArgGPRs.size()) {718LocInfo = CCValAssign::Indirect;719LocVT = XLenVT;720}721}722723if (LocVT == XLenVT) {724if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) {725State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));726return false;727}728}729730if (LocVT == XLenVT || LocVT == MVT::f16 || LocVT == MVT::bf16 ||731LocVT == MVT::f32 || LocVT == MVT::f64 || LocVT.isFixedLengthVector()) {732Align StackAlign = MaybeAlign(ValVT.getScalarSizeInBits() / 8).valueOrOne();733int64_t Offset = State.AllocateStack(LocVT.getStoreSize(), StackAlign);734State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));735return false;736}737738return true; // CC didn't match.739}740741bool llvm::CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,742CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,743CCState &State) {744if (ArgFlags.isNest()) {745report_fatal_error(746"Attribute 'nest' is not supported in GHC calling convention");747}748749static const MCPhysReg GPRList[] = {750RISCV::X9, RISCV::X18, RISCV::X19, RISCV::X20, RISCV::X21, RISCV::X22,751RISCV::X23, RISCV::X24, RISCV::X25, RISCV::X26, RISCV::X27};752753if (LocVT == MVT::i32 || LocVT == MVT::i64) {754// Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, R7, SpLim755// s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11756if (MCRegister Reg = State.AllocateReg(GPRList)) {757State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));758return false;759}760}761762const RISCVSubtarget &Subtarget =763State.getMachineFunction().getSubtarget<RISCVSubtarget>();764765if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {766// Pass in STG registers: F1, ..., F6767// fs0 ... fs5768static const MCPhysReg FPR32List[] = {RISCV::F8_F, RISCV::F9_F,769RISCV::F18_F, RISCV::F19_F,770RISCV::F20_F, RISCV::F21_F};771if (MCRegister Reg = State.AllocateReg(FPR32List)) {772State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));773return false;774}775}776777if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {778// Pass in STG registers: D1, ..., D6779// fs6 ... fs11780static const MCPhysReg FPR64List[] = {RISCV::F22_D, RISCV::F23_D,781RISCV::F24_D, RISCV::F25_D,782RISCV::F26_D, RISCV::F27_D};783if (MCRegister Reg = State.AllocateReg(FPR64List)) {784State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));785return false;786}787}788789if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {790static const MCPhysReg GPR32List[] = {791RISCV::X9_W, RISCV::X18_W, RISCV::X19_W, RISCV::X20_W,792RISCV::X21_W, RISCV::X22_W, RISCV::X23_W, RISCV::X24_W,793RISCV::X25_W, RISCV::X26_W, RISCV::X27_W};794if (MCRegister Reg = State.AllocateReg(GPR32List)) {795State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));796return false;797}798}799800if (LocVT == MVT::f64 && Subtarget.hasStdExtZdinx() && Subtarget.is64Bit()) {801if (MCRegister Reg = State.AllocateReg(GPRList)) {802State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));803return false;804}805}806807report_fatal_error("No registers left in GHC calling convention");808return true;809}810811812