brintos

brintos / llvm-project-archived public Read only

0
0
Text · 34.4 KiB · 78f4779 Raw
811 lines · cpp
1//===-- RISCVCallingConv.cpp - RISC-V Custom CC Routines ------------------===//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// This file contains the custom routines for the RISC-V Calling Convention.10//11//===----------------------------------------------------------------------===//12 13#include "RISCVCallingConv.h"14#include "RISCVSubtarget.h"15#include "llvm/IR/DataLayout.h"16#include "llvm/IR/Module.h"17#include "llvm/MC/MCRegister.h"18 19using namespace llvm;20 21// Calling Convention Implementation.22// The expectations for frontend ABI lowering vary from target to target.23// Ideally, an LLVM frontend would be able to avoid worrying about many ABI24// details, but this is a longer term goal. For now, we simply try to keep the25// role of the frontend as simple and well-defined as possible. The rules can26// be summarised as:27// * Never split up large scalar arguments. We handle them here.28// * If a hardfloat calling convention is being used, and the struct may be29// passed in a pair of registers (fp+fp, int+fp), and both registers are30// available, then pass as two separate arguments. If either the GPRs or FPRs31// are exhausted, then pass according to the rule below.32// * If a struct could never be passed in registers or directly in a stack33// slot (as it is larger than 2*XLEN and the floating point rules don't34// apply), then pass it using a pointer with the byval attribute.35// * If a struct is less than 2*XLEN, then coerce to either a two-element36// word-sized array or a 2*XLEN scalar (depending on alignment).37// * The frontend can determine whether a struct is returned by reference or38// not based on its size and fields. If it will be returned by reference, the39// frontend must modify the prototype so a pointer with the sret annotation is40// passed as the first argument. This is not necessary for large scalar41// returns.42// * Struct return values and varargs should be coerced to structs containing43// register-size fields in the same situations they would be for fixed44// arguments.45 46static const MCPhysReg ArgFPR16s[] = {RISCV::F10_H, RISCV::F11_H, RISCV::F12_H,47                                      RISCV::F13_H, RISCV::F14_H, RISCV::F15_H,48                                      RISCV::F16_H, RISCV::F17_H};49static const MCPhysReg ArgFPR32s[] = {RISCV::F10_F, RISCV::F11_F, RISCV::F12_F,50                                      RISCV::F13_F, RISCV::F14_F, RISCV::F15_F,51                                      RISCV::F16_F, RISCV::F17_F};52static const MCPhysReg ArgFPR64s[] = {RISCV::F10_D, RISCV::F11_D, RISCV::F12_D,53                                      RISCV::F13_D, RISCV::F14_D, RISCV::F15_D,54                                      RISCV::F16_D, RISCV::F17_D};55// This is an interim calling convention and it may be changed in the future.56static const MCPhysReg ArgVRs[] = {57    RISCV::V8,  RISCV::V9,  RISCV::V10, RISCV::V11, RISCV::V12, RISCV::V13,58    RISCV::V14, RISCV::V15, RISCV::V16, RISCV::V17, RISCV::V18, RISCV::V19,59    RISCV::V20, RISCV::V21, RISCV::V22, RISCV::V23};60static const MCPhysReg ArgVRM2s[] = {RISCV::V8M2,  RISCV::V10M2, RISCV::V12M2,61                                     RISCV::V14M2, RISCV::V16M2, RISCV::V18M2,62                                     RISCV::V20M2, RISCV::V22M2};63static const MCPhysReg ArgVRM4s[] = {RISCV::V8M4, RISCV::V12M4, RISCV::V16M4,64                                     RISCV::V20M4};65static const MCPhysReg ArgVRM8s[] = {RISCV::V8M8, RISCV::V16M8};66static const MCPhysReg ArgVRN2M1s[] = {67    RISCV::V8_V9,   RISCV::V9_V10,  RISCV::V10_V11, RISCV::V11_V12,68    RISCV::V12_V13, RISCV::V13_V14, RISCV::V14_V15, RISCV::V15_V16,69    RISCV::V16_V17, RISCV::V17_V18, RISCV::V18_V19, RISCV::V19_V20,70    RISCV::V20_V21, RISCV::V21_V22, RISCV::V22_V23};71static const MCPhysReg ArgVRN3M1s[] = {72    RISCV::V8_V9_V10,   RISCV::V9_V10_V11,  RISCV::V10_V11_V12,73    RISCV::V11_V12_V13, RISCV::V12_V13_V14, RISCV::V13_V14_V15,74    RISCV::V14_V15_V16, RISCV::V15_V16_V17, RISCV::V16_V17_V18,75    RISCV::V17_V18_V19, RISCV::V18_V19_V20, RISCV::V19_V20_V21,76    RISCV::V20_V21_V22, RISCV::V21_V22_V23};77static const MCPhysReg ArgVRN4M1s[] = {78    RISCV::V8_V9_V10_V11,   RISCV::V9_V10_V11_V12,  RISCV::V10_V11_V12_V13,79    RISCV::V11_V12_V13_V14, RISCV::V12_V13_V14_V15, RISCV::V13_V14_V15_V16,80    RISCV::V14_V15_V16_V17, RISCV::V15_V16_V17_V18, RISCV::V16_V17_V18_V19,81    RISCV::V17_V18_V19_V20, RISCV::V18_V19_V20_V21, RISCV::V19_V20_V21_V22,82    RISCV::V20_V21_V22_V23};83static const MCPhysReg ArgVRN5M1s[] = {84    RISCV::V8_V9_V10_V11_V12,   RISCV::V9_V10_V11_V12_V13,85    RISCV::V10_V11_V12_V13_V14, RISCV::V11_V12_V13_V14_V15,86    RISCV::V12_V13_V14_V15_V16, RISCV::V13_V14_V15_V16_V17,87    RISCV::V14_V15_V16_V17_V18, RISCV::V15_V16_V17_V18_V19,88    RISCV::V16_V17_V18_V19_V20, RISCV::V17_V18_V19_V20_V21,89    RISCV::V18_V19_V20_V21_V22, RISCV::V19_V20_V21_V22_V23};90static const MCPhysReg ArgVRN6M1s[] = {91    RISCV::V8_V9_V10_V11_V12_V13,   RISCV::V9_V10_V11_V12_V13_V14,92    RISCV::V10_V11_V12_V13_V14_V15, RISCV::V11_V12_V13_V14_V15_V16,93    RISCV::V12_V13_V14_V15_V16_V17, RISCV::V13_V14_V15_V16_V17_V18,94    RISCV::V14_V15_V16_V17_V18_V19, RISCV::V15_V16_V17_V18_V19_V20,95    RISCV::V16_V17_V18_V19_V20_V21, RISCV::V17_V18_V19_V20_V21_V22,96    RISCV::V18_V19_V20_V21_V22_V23};97static const MCPhysReg ArgVRN7M1s[] = {98    RISCV::V8_V9_V10_V11_V12_V13_V14,   RISCV::V9_V10_V11_V12_V13_V14_V15,99    RISCV::V10_V11_V12_V13_V14_V15_V16, RISCV::V11_V12_V13_V14_V15_V16_V17,100    RISCV::V12_V13_V14_V15_V16_V17_V18, RISCV::V13_V14_V15_V16_V17_V18_V19,101    RISCV::V14_V15_V16_V17_V18_V19_V20, RISCV::V15_V16_V17_V18_V19_V20_V21,102    RISCV::V16_V17_V18_V19_V20_V21_V22, RISCV::V17_V18_V19_V20_V21_V22_V23};103static const MCPhysReg ArgVRN8M1s[] = {RISCV::V8_V9_V10_V11_V12_V13_V14_V15,104                                       RISCV::V9_V10_V11_V12_V13_V14_V15_V16,105                                       RISCV::V10_V11_V12_V13_V14_V15_V16_V17,106                                       RISCV::V11_V12_V13_V14_V15_V16_V17_V18,107                                       RISCV::V12_V13_V14_V15_V16_V17_V18_V19,108                                       RISCV::V13_V14_V15_V16_V17_V18_V19_V20,109                                       RISCV::V14_V15_V16_V17_V18_V19_V20_V21,110                                       RISCV::V15_V16_V17_V18_V19_V20_V21_V22,111                                       RISCV::V16_V17_V18_V19_V20_V21_V22_V23};112static const MCPhysReg ArgVRN2M2s[] = {RISCV::V8M2_V10M2,  RISCV::V10M2_V12M2,113                                       RISCV::V12M2_V14M2, RISCV::V14M2_V16M2,114                                       RISCV::V16M2_V18M2, RISCV::V18M2_V20M2,115                                       RISCV::V20M2_V22M2};116static const MCPhysReg ArgVRN3M2s[] = {117    RISCV::V8M2_V10M2_V12M2,  RISCV::V10M2_V12M2_V14M2,118    RISCV::V12M2_V14M2_V16M2, RISCV::V14M2_V16M2_V18M2,119    RISCV::V16M2_V18M2_V20M2, RISCV::V18M2_V20M2_V22M2};120static const MCPhysReg ArgVRN4M2s[] = {121    RISCV::V8M2_V10M2_V12M2_V14M2, RISCV::V10M2_V12M2_V14M2_V16M2,122    RISCV::V12M2_V14M2_V16M2_V18M2, RISCV::V14M2_V16M2_V18M2_V20M2,123    RISCV::V16M2_V18M2_V20M2_V22M2};124static const MCPhysReg ArgVRN2M4s[] = {RISCV::V8M4_V12M4, RISCV::V12M4_V16M4,125                                       RISCV::V16M4_V20M4};126 127ArrayRef<MCPhysReg> RISCV::getArgGPRs(const RISCVABI::ABI ABI) {128  // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except129  // the ILP32E ABI.130  static const MCPhysReg ArgIGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,131                                       RISCV::X13, RISCV::X14, RISCV::X15,132                                       RISCV::X16, RISCV::X17};133  // The GPRs used for passing arguments in the ILP32E/LP64E ABI.134  static const MCPhysReg ArgEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,135                                       RISCV::X13, RISCV::X14, RISCV::X15};136 137  if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)138    return ArrayRef(ArgEGPRs);139 140  return ArrayRef(ArgIGPRs);141}142 143static ArrayRef<MCPhysReg> getArgGPR16s(const RISCVABI::ABI ABI) {144  // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except145  // the ILP32E ABI.146  static const MCPhysReg ArgIGPRs[] = {RISCV::X10_H, RISCV::X11_H, RISCV::X12_H,147                                       RISCV::X13_H, RISCV::X14_H, RISCV::X15_H,148                                       RISCV::X16_H, RISCV::X17_H};149  // The GPRs used for passing arguments in the ILP32E/LP64E ABI.150  static const MCPhysReg ArgEGPRs[] = {RISCV::X10_H, RISCV::X11_H,151                                       RISCV::X12_H, RISCV::X13_H,152                                       RISCV::X14_H, RISCV::X15_H};153 154  if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)155    return ArrayRef(ArgEGPRs);156 157  return ArrayRef(ArgIGPRs);158}159 160static ArrayRef<MCPhysReg> getArgGPR32s(const RISCVABI::ABI ABI) {161  // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except162  // the ILP32E ABI.163  static const MCPhysReg ArgIGPRs[] = {RISCV::X10_W, RISCV::X11_W, RISCV::X12_W,164                                       RISCV::X13_W, RISCV::X14_W, RISCV::X15_W,165                                       RISCV::X16_W, RISCV::X17_W};166  // The GPRs used for passing arguments in the ILP32E/LP64E ABI.167  static const MCPhysReg ArgEGPRs[] = {RISCV::X10_W, RISCV::X11_W,168                                       RISCV::X12_W, RISCV::X13_W,169                                       RISCV::X14_W, RISCV::X15_W};170 171  if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)172    return ArrayRef(ArgEGPRs);173 174  return ArrayRef(ArgIGPRs);175}176 177static ArrayRef<MCPhysReg> getFastCCArgGPRs(const RISCVABI::ABI ABI) {178  // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used179  // for save-restore libcall, so we don't use them.180  // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.181  static const MCPhysReg FastCCIGPRs[] = {182      RISCV::X10, RISCV::X11, RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15,183      RISCV::X16, RISCV::X17, RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31};184 185  // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.186  static const MCPhysReg FastCCEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,187                                          RISCV::X13, RISCV::X14, RISCV::X15};188 189  if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)190    return ArrayRef(FastCCEGPRs);191 192  return ArrayRef(FastCCIGPRs);193}194 195static ArrayRef<MCPhysReg> getFastCCArgGPRF16s(const RISCVABI::ABI ABI) {196  // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used197  // for save-restore libcall, so we don't use them.198  // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.199  static const MCPhysReg FastCCIGPRs[] = {200      RISCV::X10_H, RISCV::X11_H, RISCV::X12_H, RISCV::X13_H,201      RISCV::X14_H, RISCV::X15_H, RISCV::X16_H, RISCV::X17_H,202      RISCV::X28_H, RISCV::X29_H, RISCV::X30_H, RISCV::X31_H};203 204  // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.205  static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_H, RISCV::X11_H,206                                          RISCV::X12_H, RISCV::X13_H,207                                          RISCV::X14_H, RISCV::X15_H};208 209  if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)210    return ArrayRef(FastCCEGPRs);211 212  return ArrayRef(FastCCIGPRs);213}214 215static ArrayRef<MCPhysReg> getFastCCArgGPRF32s(const RISCVABI::ABI ABI) {216  // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used217  // for save-restore libcall, so we don't use them.218  // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.219  static const MCPhysReg FastCCIGPRs[] = {220      RISCV::X10_W, RISCV::X11_W, RISCV::X12_W, RISCV::X13_W,221      RISCV::X14_W, RISCV::X15_W, RISCV::X16_W, RISCV::X17_W,222      RISCV::X28_W, RISCV::X29_W, RISCV::X30_W, RISCV::X31_W};223 224  // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.225  static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_W, RISCV::X11_W,226                                          RISCV::X12_W, RISCV::X13_W,227                                          RISCV::X14_W, RISCV::X15_W};228 229  if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)230    return ArrayRef(FastCCEGPRs);231 232  return ArrayRef(FastCCIGPRs);233}234 235// Pass a 2*XLEN argument that has been split into two XLEN values through236// registers or the stack as necessary.237static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1,238                                ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2,239                                MVT ValVT2, MVT LocVT2,240                                ISD::ArgFlagsTy ArgFlags2, bool EABI) {241  unsigned XLenInBytes = XLen / 8;242  const RISCVSubtarget &STI =243      State.getMachineFunction().getSubtarget<RISCVSubtarget>();244  ArrayRef<MCPhysReg> ArgGPRs = RISCV::getArgGPRs(STI.getTargetABI());245 246  if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {247    // At least one half can be passed via register.248    State.addLoc(CCValAssign::getReg(VA1.getValNo(), VA1.getValVT(), Reg,249                                     VA1.getLocVT(), CCValAssign::Full));250  } else {251    // Both halves must be passed on the stack, with proper alignment.252    // TODO: To be compatible with GCC's behaviors, we force them to have 4-byte253    // alignment. This behavior may be changed when RV32E/ILP32E is ratified.254    Align StackAlign(XLenInBytes);255    if (!EABI || XLen != 32)256      StackAlign = std::max(StackAlign, ArgFlags1.getNonZeroOrigAlign());257    State.addLoc(258        CCValAssign::getMem(VA1.getValNo(), VA1.getValVT(),259                            State.AllocateStack(XLenInBytes, StackAlign),260                            VA1.getLocVT(), CCValAssign::Full));261    State.addLoc(CCValAssign::getMem(262        ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)),263        LocVT2, CCValAssign::Full));264    return false;265  }266 267  if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {268    // The second half can also be passed via register.269    State.addLoc(270        CCValAssign::getReg(ValNo2, ValVT2, Reg, LocVT2, CCValAssign::Full));271  } else {272    // The second half is passed via the stack, without additional alignment.273    State.addLoc(CCValAssign::getMem(274        ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)),275        LocVT2, CCValAssign::Full));276  }277 278  return false;279}280 281static MCRegister allocateRVVReg(MVT ValVT, unsigned ValNo, CCState &State,282                                 const RISCVTargetLowering &TLI) {283  const TargetRegisterClass *RC = TLI.getRegClassFor(ValVT);284  if (RC == &RISCV::VRRegClass) {285    // Assign the first mask argument to V0.286    // This is an interim calling convention and it may be changed in the287    // future.288    if (ValVT.getVectorElementType() == MVT::i1)289      if (MCRegister Reg = State.AllocateReg(RISCV::V0))290        return Reg;291    return State.AllocateReg(ArgVRs);292  }293  if (RC == &RISCV::VRM2RegClass)294    return State.AllocateReg(ArgVRM2s);295  if (RC == &RISCV::VRM4RegClass)296    return State.AllocateReg(ArgVRM4s);297  if (RC == &RISCV::VRM8RegClass)298    return State.AllocateReg(ArgVRM8s);299  if (RC == &RISCV::VRN2M1RegClass)300    return State.AllocateReg(ArgVRN2M1s);301  if (RC == &RISCV::VRN3M1RegClass)302    return State.AllocateReg(ArgVRN3M1s);303  if (RC == &RISCV::VRN4M1RegClass)304    return State.AllocateReg(ArgVRN4M1s);305  if (RC == &RISCV::VRN5M1RegClass)306    return State.AllocateReg(ArgVRN5M1s);307  if (RC == &RISCV::VRN6M1RegClass)308    return State.AllocateReg(ArgVRN6M1s);309  if (RC == &RISCV::VRN7M1RegClass)310    return State.AllocateReg(ArgVRN7M1s);311  if (RC == &RISCV::VRN8M1RegClass)312    return State.AllocateReg(ArgVRN8M1s);313  if (RC == &RISCV::VRN2M2RegClass)314    return State.AllocateReg(ArgVRN2M2s);315  if (RC == &RISCV::VRN3M2RegClass)316    return State.AllocateReg(ArgVRN3M2s);317  if (RC == &RISCV::VRN4M2RegClass)318    return State.AllocateReg(ArgVRN4M2s);319  if (RC == &RISCV::VRN2M4RegClass)320    return State.AllocateReg(ArgVRN2M4s);321  llvm_unreachable("Unhandled register class for ValueType");322}323 324// Implements the RISC-V calling convention. Returns true upon failure.325bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,326                    CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,327                    CCState &State, bool IsRet, Type *OrigTy) {328  const MachineFunction &MF = State.getMachineFunction();329  const DataLayout &DL = MF.getDataLayout();330  const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();331  const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering();332 333  unsigned XLen = Subtarget.getXLen();334  MVT XLenVT = Subtarget.getXLenVT();335 336  if (ArgFlags.isNest()) {337    // Static chain parameter must not be passed in normal argument registers,338    // so we assign t2/t3 for it as done in GCC's339    // __builtin_call_with_static_chain340    bool HasCFBranch =341        Subtarget.hasStdExtZicfilp() &&342        MF.getFunction().getParent()->getModuleFlag("cf-protection-branch");343 344    // Normal: t2, Branch control flow protection: t3345    const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7;346 347    RISCVABI::ABI ABI = Subtarget.getTargetABI();348    if (HasCFBranch &&349        (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E))350      reportFatalUsageError(351          "Nested functions with control flow protection are not "352          "usable with ILP32E or LP64E ABI.");353    if (MCRegister Reg = State.AllocateReg(StaticChainReg)) {354      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));355      return false;356    }357  }358 359  // Any return value split in to more than two values can't be returned360  // directly. Vectors are returned via the available vector registers.361  if (!LocVT.isVector() && IsRet && ValNo > 1)362    return true;363 364  // UseGPRForF16_F32 if targeting one of the soft-float ABIs, if passing a365  // variadic argument, or if no F16/F32 argument registers are available.366  bool UseGPRForF16_F32 = true;367  // UseGPRForF64 if targeting soft-float ABIs or an FLEN=32 ABI, if passing a368  // variadic argument, or if no F64 argument registers are available.369  bool UseGPRForF64 = true;370 371  RISCVABI::ABI ABI = Subtarget.getTargetABI();372  switch (ABI) {373  default:374    llvm_unreachable("Unexpected ABI");375  case RISCVABI::ABI_ILP32:376  case RISCVABI::ABI_ILP32E:377  case RISCVABI::ABI_LP64:378  case RISCVABI::ABI_LP64E:379    break;380  case RISCVABI::ABI_ILP32F:381  case RISCVABI::ABI_LP64F:382    UseGPRForF16_F32 = ArgFlags.isVarArg();383    break;384  case RISCVABI::ABI_ILP32D:385  case RISCVABI::ABI_LP64D:386    UseGPRForF16_F32 = ArgFlags.isVarArg();387    UseGPRForF64 = ArgFlags.isVarArg();388    break;389  }390 391  if ((LocVT == MVT::f16 || LocVT == MVT::bf16) && !UseGPRForF16_F32) {392    if (MCRegister Reg = State.AllocateReg(ArgFPR16s)) {393      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));394      return false;395    }396  }397 398  if (LocVT == MVT::f32 && !UseGPRForF16_F32) {399    if (MCRegister Reg = State.AllocateReg(ArgFPR32s)) {400      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));401      return false;402    }403  }404 405  if (LocVT == MVT::f64 && !UseGPRForF64) {406    if (MCRegister Reg = State.AllocateReg(ArgFPR64s)) {407      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));408      return false;409    }410  }411 412  if ((ValVT == MVT::f16 && Subtarget.hasStdExtZhinxmin())) {413    if (MCRegister Reg = State.AllocateReg(getArgGPR16s(ABI))) {414      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));415      return false;416    }417  }418 419  if (ValVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {420    if (MCRegister Reg = State.AllocateReg(getArgGPR32s(ABI))) {421      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));422      return false;423    }424  }425 426  ArrayRef<MCPhysReg> ArgGPRs = RISCV::getArgGPRs(ABI);427 428  // Zdinx use GPR without a bitcast when possible.429  if (LocVT == MVT::f64 && XLen == 64 && Subtarget.hasStdExtZdinx()) {430    if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {431      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));432      return false;433    }434  }435 436  // FP smaller than XLen, uses custom GPR.437  if (LocVT == MVT::f16 || LocVT == MVT::bf16 ||438      (LocVT == MVT::f32 && XLen == 64)) {439    if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {440      LocVT = XLenVT;441      State.addLoc(442          CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));443      return false;444    }445  }446 447  // Bitcast FP to GPR if we can use a GPR register.448  if ((XLen == 32 && LocVT == MVT::f32) || (XLen == 64 && LocVT == MVT::f64)) {449    if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {450      LocVT = XLenVT;451      LocInfo = CCValAssign::BCvt;452      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));453      return false;454    }455  }456 457  // If this is a variadic argument, the RISC-V calling convention requires458  // that it is assigned an 'even' or 'aligned' register if it has 8-byte459  // alignment (RV32) or 16-byte alignment (RV64). An aligned register should460  // be used regardless of whether the original argument was split during461  // legalisation or not. The argument will not be passed by registers if the462  // original type is larger than 2*XLEN, so the register alignment rule does463  // not apply.464  // TODO: To be compatible with GCC's behaviors, we don't align registers465  // currently if we are using ILP32E calling convention. This behavior may be466  // changed when RV32E/ILP32E is ratified.467  unsigned TwoXLenInBytes = (2 * XLen) / 8;468  if (ArgFlags.isVarArg() && ArgFlags.getNonZeroOrigAlign() == TwoXLenInBytes &&469      DL.getTypeAllocSize(OrigTy) == TwoXLenInBytes &&470      ABI != RISCVABI::ABI_ILP32E) {471    unsigned RegIdx = State.getFirstUnallocated(ArgGPRs);472    // Skip 'odd' register if necessary.473    if (RegIdx != std::size(ArgGPRs) && RegIdx % 2 == 1)474      State.AllocateReg(ArgGPRs);475  }476 477  SmallVectorImpl<CCValAssign> &PendingLocs = State.getPendingLocs();478  SmallVectorImpl<ISD::ArgFlagsTy> &PendingArgFlags =479      State.getPendingArgFlags();480 481  assert(PendingLocs.size() == PendingArgFlags.size() &&482         "PendingLocs and PendingArgFlags out of sync");483 484  // Handle passing f64 on RV32D with a soft float ABI or when floating point485  // registers are exhausted.486  if (XLen == 32 && LocVT == MVT::f64) {487    assert(PendingLocs.empty() && "Can't lower f64 if it is split");488    // Depending on available argument GPRS, f64 may be passed in a pair of489    // GPRs, split between a GPR and the stack, or passed completely on the490    // stack. LowerCall/LowerFormalArguments/LowerReturn must recognise these491    // cases.492    MCRegister Reg = State.AllocateReg(ArgGPRs);493    if (!Reg) {494      int64_t StackOffset = State.AllocateStack(8, Align(8));495      State.addLoc(496          CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));497      return false;498    }499    LocVT = MVT::i32;500    State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));501    MCRegister HiReg = State.AllocateReg(ArgGPRs);502    if (HiReg) {503      State.addLoc(504          CCValAssign::getCustomReg(ValNo, ValVT, HiReg, LocVT, LocInfo));505    } else {506      int64_t StackOffset = State.AllocateStack(4, Align(4));507      State.addLoc(508          CCValAssign::getCustomMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));509    }510    return false;511  }512 513  // Split arguments might be passed indirectly, so keep track of the pending514  // values. Split vectors are passed via a mix of registers and indirectly, so515  // treat them as we would any other argument.516  if (ValVT.isScalarInteger() && (ArgFlags.isSplit() || !PendingLocs.empty())) {517    LocVT = XLenVT;518    LocInfo = CCValAssign::Indirect;519    PendingLocs.push_back(520        CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo));521    PendingArgFlags.push_back(ArgFlags);522    if (!ArgFlags.isSplitEnd()) {523      return false;524    }525  }526 527  // If the split argument only had two elements, it should be passed directly528  // in registers or on the stack.529  if (ValVT.isScalarInteger() && ArgFlags.isSplitEnd() &&530      PendingLocs.size() <= 2) {531    assert(PendingLocs.size() == 2 && "Unexpected PendingLocs.size()");532    // Apply the normal calling convention rules to the first half of the533    // split argument.534    CCValAssign VA = PendingLocs[0];535    ISD::ArgFlagsTy AF = PendingArgFlags[0];536    PendingLocs.clear();537    PendingArgFlags.clear();538    return CC_RISCVAssign2XLen(539        XLen, State, VA, AF, ValNo, ValVT, LocVT, ArgFlags,540        ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E);541  }542 543  // Allocate to a register if possible, or else a stack slot.544  MCRegister Reg;545  unsigned StoreSizeBytes = XLen / 8;546  Align StackAlign = Align(XLen / 8);547 548  if (ValVT.isVector() || ValVT.isRISCVVectorTuple()) {549    Reg = allocateRVVReg(ValVT, ValNo, State, TLI);550    if (Reg) {551      // Fixed-length vectors are located in the corresponding scalable-vector552      // container types.553      if (ValVT.isFixedLengthVector()) {554        LocVT = TLI.getContainerForFixedLengthVector(LocVT);555        State.addLoc(556            CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));557        return false;558      }559    } else {560      // For return values, the vector must be passed fully via registers or561      // via the stack.562      // FIXME: The proposed vector ABI only mandates v8-v15 for return values,563      // but we're using all of them.564      if (IsRet)565        return true;566      // Try using a GPR to pass the address567      if ((Reg = State.AllocateReg(ArgGPRs))) {568        LocVT = XLenVT;569        LocInfo = CCValAssign::Indirect;570      } else if (ValVT.isScalableVector()) {571        LocVT = XLenVT;572        LocInfo = CCValAssign::Indirect;573      } else {574        StoreSizeBytes = ValVT.getStoreSize();575        // Align vectors to their element sizes, being careful for vXi1576        // vectors.577        StackAlign = MaybeAlign(ValVT.getScalarSizeInBits() / 8).valueOrOne();578      }579    }580  } else {581    Reg = State.AllocateReg(ArgGPRs);582  }583 584  int64_t StackOffset =585      Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);586 587  // If we reach this point and PendingLocs is non-empty, we must be at the588  // end of a split argument that must be passed indirectly.589  if (!PendingLocs.empty()) {590    assert(ArgFlags.isSplitEnd() && "Expected ArgFlags.isSplitEnd()");591    assert(PendingLocs.size() > 2 && "Unexpected PendingLocs.size()");592 593    for (auto &It : PendingLocs) {594      if (Reg)595        It.convertToReg(Reg);596      else597        It.convertToMem(StackOffset);598      State.addLoc(It);599    }600    PendingLocs.clear();601    PendingArgFlags.clear();602    return false;603  }604 605  assert(((ValVT.isFloatingPoint() && !ValVT.isVector()) || LocVT == XLenVT ||606          (TLI.getSubtarget().hasVInstructions() &&607           (ValVT.isVector() || ValVT.isRISCVVectorTuple()))) &&608         "Expected an XLenVT or vector types at this stage");609 610  if (Reg) {611    State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));612    return false;613  }614 615  State.addLoc(CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));616  return false;617}618 619// FastCC has less than 1% performance improvement for some particular620// benchmark. But theoretically, it may have benefit for some cases.621bool llvm::CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT,622                           CCValAssign::LocInfo LocInfo,623                           ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet,624                           Type *OrigTy) {625  const MachineFunction &MF = State.getMachineFunction();626  const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();627  const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering();628  RISCVABI::ABI ABI = Subtarget.getTargetABI();629 630  if ((LocVT == MVT::f16 && Subtarget.hasStdExtZfhmin()) ||631      (LocVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin())) {632    static const MCPhysReg FPR16List[] = {633        RISCV::F10_H, RISCV::F11_H, RISCV::F12_H, RISCV::F13_H, RISCV::F14_H,634        RISCV::F15_H, RISCV::F16_H, RISCV::F17_H, RISCV::F0_H,  RISCV::F1_H,635        RISCV::F2_H,  RISCV::F3_H,  RISCV::F4_H,  RISCV::F5_H,  RISCV::F6_H,636        RISCV::F7_H,  RISCV::F28_H, RISCV::F29_H, RISCV::F30_H, RISCV::F31_H};637    if (MCRegister Reg = State.AllocateReg(FPR16List)) {638      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));639      return false;640    }641  }642 643  if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {644    static const MCPhysReg FPR32List[] = {645        RISCV::F10_F, RISCV::F11_F, RISCV::F12_F, RISCV::F13_F, RISCV::F14_F,646        RISCV::F15_F, RISCV::F16_F, RISCV::F17_F, RISCV::F0_F,  RISCV::F1_F,647        RISCV::F2_F,  RISCV::F3_F,  RISCV::F4_F,  RISCV::F5_F,  RISCV::F6_F,648        RISCV::F7_F,  RISCV::F28_F, RISCV::F29_F, RISCV::F30_F, RISCV::F31_F};649    if (MCRegister Reg = State.AllocateReg(FPR32List)) {650      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));651      return false;652    }653  }654 655  if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {656    static const MCPhysReg FPR64List[] = {657        RISCV::F10_D, RISCV::F11_D, RISCV::F12_D, RISCV::F13_D, RISCV::F14_D,658        RISCV::F15_D, RISCV::F16_D, RISCV::F17_D, RISCV::F0_D,  RISCV::F1_D,659        RISCV::F2_D,  RISCV::F3_D,  RISCV::F4_D,  RISCV::F5_D,  RISCV::F6_D,660        RISCV::F7_D,  RISCV::F28_D, RISCV::F29_D, RISCV::F30_D, RISCV::F31_D};661    if (MCRegister Reg = State.AllocateReg(FPR64List)) {662      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));663      return false;664    }665  }666 667  MVT XLenVT = Subtarget.getXLenVT();668 669  // Check if there is an available GPRF16 before hitting the stack.670  if ((LocVT == MVT::f16 && Subtarget.hasStdExtZhinxmin())) {671    if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF16s(ABI))) {672      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));673      return false;674    }675  }676 677  // Check if there is an available GPRF32 before hitting the stack.678  if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {679    if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF32s(ABI))) {680      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));681      return false;682    }683  }684 685  // Check if there is an available GPR before hitting the stack.686  if (LocVT == MVT::f64 && Subtarget.is64Bit() && Subtarget.hasStdExtZdinx()) {687    if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) {688      if (LocVT.getSizeInBits() != Subtarget.getXLen()) {689        LocVT = XLenVT;690        State.addLoc(691            CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));692        return false;693      }694      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));695      return false;696    }697  }698 699  ArrayRef<MCPhysReg> ArgGPRs = getFastCCArgGPRs(ABI);700 701  if (LocVT.isVector()) {702    if (MCRegister Reg = allocateRVVReg(ValVT, ValNo, State, TLI)) {703      // Fixed-length vectors are located in the corresponding scalable-vector704      // container types.705      if (LocVT.isFixedLengthVector()) {706        LocVT = TLI.getContainerForFixedLengthVector(LocVT);707        State.addLoc(708            CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));709        return false;710      }711      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));712      return false;713    }714 715    // Pass scalable vectors indirectly. Pass fixed vectors indirectly if we716    // have a free GPR.717    if (LocVT.isScalableVector() ||718        State.getFirstUnallocated(ArgGPRs) != ArgGPRs.size()) {719      LocInfo = CCValAssign::Indirect;720      LocVT = XLenVT;721    }722  }723 724  if (LocVT == XLenVT) {725    if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) {726      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));727      return false;728    }729  }730 731  if (LocVT == XLenVT || LocVT == MVT::f16 || LocVT == MVT::bf16 ||732      LocVT == MVT::f32 || LocVT == MVT::f64 || LocVT.isFixedLengthVector()) {733    Align StackAlign = MaybeAlign(ValVT.getScalarSizeInBits() / 8).valueOrOne();734    int64_t Offset = State.AllocateStack(LocVT.getStoreSize(), StackAlign);735    State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));736    return false;737  }738 739  return true; // CC didn't match.740}741 742bool llvm::CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,743                        CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,744                        Type *OrigTy, CCState &State) {745  if (ArgFlags.isNest()) {746    report_fatal_error(747        "Attribute 'nest' is not supported in GHC calling convention");748  }749 750  static const MCPhysReg GPRList[] = {751      RISCV::X9,  RISCV::X18, RISCV::X19, RISCV::X20, RISCV::X21, RISCV::X22,752      RISCV::X23, RISCV::X24, RISCV::X25, RISCV::X26, RISCV::X27};753 754  if (LocVT == MVT::i32 || LocVT == MVT::i64) {755    // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, R7, SpLim756    //                        s1    s2  s3  s4  s5  s6  s7  s8  s9  s10 s11757    if (MCRegister Reg = State.AllocateReg(GPRList)) {758      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));759      return false;760    }761  }762 763  const RISCVSubtarget &Subtarget =764      State.getMachineFunction().getSubtarget<RISCVSubtarget>();765 766  if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {767    // Pass in STG registers: F1, ..., F6768    //                        fs0 ... fs5769    static const MCPhysReg FPR32List[] = {RISCV::F8_F,  RISCV::F9_F,770                                          RISCV::F18_F, RISCV::F19_F,771                                          RISCV::F20_F, RISCV::F21_F};772    if (MCRegister Reg = State.AllocateReg(FPR32List)) {773      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));774      return false;775    }776  }777 778  if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {779    // Pass in STG registers: D1, ..., D6780    //                        fs6 ... fs11781    static const MCPhysReg FPR64List[] = {RISCV::F22_D, RISCV::F23_D,782                                          RISCV::F24_D, RISCV::F25_D,783                                          RISCV::F26_D, RISCV::F27_D};784    if (MCRegister Reg = State.AllocateReg(FPR64List)) {785      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));786      return false;787    }788  }789 790  if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {791    static const MCPhysReg GPR32List[] = {792        RISCV::X9_W,  RISCV::X18_W, RISCV::X19_W, RISCV::X20_W,793        RISCV::X21_W, RISCV::X22_W, RISCV::X23_W, RISCV::X24_W,794        RISCV::X25_W, RISCV::X26_W, RISCV::X27_W};795    if (MCRegister Reg = State.AllocateReg(GPR32List)) {796      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));797      return false;798    }799  }800 801  if (LocVT == MVT::f64 && Subtarget.hasStdExtZdinx() && Subtarget.is64Bit()) {802    if (MCRegister Reg = State.AllocateReg(GPRList)) {803      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));804      return false;805    }806  }807 808  report_fatal_error("No registers left in GHC calling convention");809  return true;810}811