1093b8bfeSCraig Topper //===-- RISCVCallingConv.cpp - RISC-V Custom CC Routines ------------------===// 2093b8bfeSCraig Topper // 3093b8bfeSCraig Topper // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4093b8bfeSCraig Topper // See https://llvm.org/LICENSE.txt for license information. 5093b8bfeSCraig Topper // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6093b8bfeSCraig Topper // 7093b8bfeSCraig Topper //===----------------------------------------------------------------------===// 8093b8bfeSCraig Topper // 9093b8bfeSCraig Topper // This file contains the custom routines for the RISC-V Calling Convention. 10093b8bfeSCraig Topper // 11093b8bfeSCraig Topper //===----------------------------------------------------------------------===// 12093b8bfeSCraig Topper 13093b8bfeSCraig Topper #include "RISCVCallingConv.h" 14093b8bfeSCraig Topper #include "RISCVSubtarget.h" 15093b8bfeSCraig Topper #include "llvm/IR/DataLayout.h" 16093b8bfeSCraig Topper #include "llvm/MC/MCRegister.h" 17093b8bfeSCraig Topper 18093b8bfeSCraig Topper using namespace llvm; 19093b8bfeSCraig Topper 20093b8bfeSCraig Topper // Calling Convention Implementation. 21093b8bfeSCraig Topper // The expectations for frontend ABI lowering vary from target to target. 22093b8bfeSCraig Topper // Ideally, an LLVM frontend would be able to avoid worrying about many ABI 23093b8bfeSCraig Topper // details, but this is a longer term goal. For now, we simply try to keep the 24093b8bfeSCraig Topper // role of the frontend as simple and well-defined as possible. The rules can 25093b8bfeSCraig Topper // be summarised as: 26093b8bfeSCraig Topper // * Never split up large scalar arguments. We handle them here. 27093b8bfeSCraig Topper // * If a hardfloat calling convention is being used, and the struct may be 28093b8bfeSCraig Topper // passed in a pair of registers (fp+fp, int+fp), and both registers are 29093b8bfeSCraig Topper // available, then pass as two separate arguments. If either the GPRs or FPRs 30093b8bfeSCraig Topper // are exhausted, then pass according to the rule below. 31093b8bfeSCraig Topper // * If a struct could never be passed in registers or directly in a stack 32093b8bfeSCraig Topper // slot (as it is larger than 2*XLEN and the floating point rules don't 33093b8bfeSCraig Topper // apply), then pass it using a pointer with the byval attribute. 34093b8bfeSCraig Topper // * If a struct is less than 2*XLEN, then coerce to either a two-element 35093b8bfeSCraig Topper // word-sized array or a 2*XLEN scalar (depending on alignment). 36093b8bfeSCraig Topper // * The frontend can determine whether a struct is returned by reference or 37093b8bfeSCraig Topper // not based on its size and fields. If it will be returned by reference, the 38093b8bfeSCraig Topper // frontend must modify the prototype so a pointer with the sret annotation is 39093b8bfeSCraig Topper // passed as the first argument. This is not necessary for large scalar 40093b8bfeSCraig Topper // returns. 41093b8bfeSCraig Topper // * Struct return values and varargs should be coerced to structs containing 42093b8bfeSCraig Topper // register-size fields in the same situations they would be for fixed 43093b8bfeSCraig Topper // arguments. 44093b8bfeSCraig Topper 45093b8bfeSCraig Topper static const MCPhysReg ArgFPR16s[] = {RISCV::F10_H, RISCV::F11_H, RISCV::F12_H, 46093b8bfeSCraig Topper RISCV::F13_H, RISCV::F14_H, RISCV::F15_H, 47093b8bfeSCraig Topper RISCV::F16_H, RISCV::F17_H}; 48093b8bfeSCraig Topper static const MCPhysReg ArgFPR32s[] = {RISCV::F10_F, RISCV::F11_F, RISCV::F12_F, 49093b8bfeSCraig Topper RISCV::F13_F, RISCV::F14_F, RISCV::F15_F, 50093b8bfeSCraig Topper RISCV::F16_F, RISCV::F17_F}; 51093b8bfeSCraig Topper static const MCPhysReg ArgFPR64s[] = {RISCV::F10_D, RISCV::F11_D, RISCV::F12_D, 52093b8bfeSCraig Topper RISCV::F13_D, RISCV::F14_D, RISCV::F15_D, 53093b8bfeSCraig Topper RISCV::F16_D, RISCV::F17_D}; 54093b8bfeSCraig Topper // This is an interim calling convention and it may be changed in the future. 55093b8bfeSCraig Topper static const MCPhysReg ArgVRs[] = { 56093b8bfeSCraig Topper RISCV::V8, RISCV::V9, RISCV::V10, RISCV::V11, RISCV::V12, RISCV::V13, 57093b8bfeSCraig Topper RISCV::V14, RISCV::V15, RISCV::V16, RISCV::V17, RISCV::V18, RISCV::V19, 58093b8bfeSCraig Topper RISCV::V20, RISCV::V21, RISCV::V22, RISCV::V23}; 59093b8bfeSCraig Topper static const MCPhysReg ArgVRM2s[] = {RISCV::V8M2, RISCV::V10M2, RISCV::V12M2, 60093b8bfeSCraig Topper RISCV::V14M2, RISCV::V16M2, RISCV::V18M2, 61093b8bfeSCraig Topper RISCV::V20M2, RISCV::V22M2}; 62093b8bfeSCraig Topper static const MCPhysReg ArgVRM4s[] = {RISCV::V8M4, RISCV::V12M4, RISCV::V16M4, 63093b8bfeSCraig Topper RISCV::V20M4}; 64093b8bfeSCraig Topper static const MCPhysReg ArgVRM8s[] = {RISCV::V8M8, RISCV::V16M8}; 65093b8bfeSCraig Topper static const MCPhysReg ArgVRN2M1s[] = { 66093b8bfeSCraig Topper RISCV::V8_V9, RISCV::V9_V10, RISCV::V10_V11, RISCV::V11_V12, 67093b8bfeSCraig Topper RISCV::V12_V13, RISCV::V13_V14, RISCV::V14_V15, RISCV::V15_V16, 68093b8bfeSCraig Topper RISCV::V16_V17, RISCV::V17_V18, RISCV::V18_V19, RISCV::V19_V20, 69093b8bfeSCraig Topper RISCV::V20_V21, RISCV::V21_V22, RISCV::V22_V23}; 70093b8bfeSCraig Topper static const MCPhysReg ArgVRN3M1s[] = { 71093b8bfeSCraig Topper RISCV::V8_V9_V10, RISCV::V9_V10_V11, RISCV::V10_V11_V12, 72093b8bfeSCraig Topper RISCV::V11_V12_V13, RISCV::V12_V13_V14, RISCV::V13_V14_V15, 73093b8bfeSCraig Topper RISCV::V14_V15_V16, RISCV::V15_V16_V17, RISCV::V16_V17_V18, 74093b8bfeSCraig Topper RISCV::V17_V18_V19, RISCV::V18_V19_V20, RISCV::V19_V20_V21, 75093b8bfeSCraig Topper RISCV::V20_V21_V22, RISCV::V21_V22_V23}; 76093b8bfeSCraig Topper static const MCPhysReg ArgVRN4M1s[] = { 77093b8bfeSCraig Topper RISCV::V8_V9_V10_V11, RISCV::V9_V10_V11_V12, RISCV::V10_V11_V12_V13, 78093b8bfeSCraig Topper RISCV::V11_V12_V13_V14, RISCV::V12_V13_V14_V15, RISCV::V13_V14_V15_V16, 79093b8bfeSCraig Topper RISCV::V14_V15_V16_V17, RISCV::V15_V16_V17_V18, RISCV::V16_V17_V18_V19, 80093b8bfeSCraig Topper RISCV::V17_V18_V19_V20, RISCV::V18_V19_V20_V21, RISCV::V19_V20_V21_V22, 81093b8bfeSCraig Topper RISCV::V20_V21_V22_V23}; 82093b8bfeSCraig Topper static const MCPhysReg ArgVRN5M1s[] = { 83093b8bfeSCraig Topper RISCV::V8_V9_V10_V11_V12, RISCV::V9_V10_V11_V12_V13, 84093b8bfeSCraig Topper RISCV::V10_V11_V12_V13_V14, RISCV::V11_V12_V13_V14_V15, 85093b8bfeSCraig Topper RISCV::V12_V13_V14_V15_V16, RISCV::V13_V14_V15_V16_V17, 86093b8bfeSCraig Topper RISCV::V14_V15_V16_V17_V18, RISCV::V15_V16_V17_V18_V19, 87093b8bfeSCraig Topper RISCV::V16_V17_V18_V19_V20, RISCV::V17_V18_V19_V20_V21, 88093b8bfeSCraig Topper RISCV::V18_V19_V20_V21_V22, RISCV::V19_V20_V21_V22_V23}; 89093b8bfeSCraig Topper static const MCPhysReg ArgVRN6M1s[] = { 90093b8bfeSCraig Topper RISCV::V8_V9_V10_V11_V12_V13, RISCV::V9_V10_V11_V12_V13_V14, 91093b8bfeSCraig Topper RISCV::V10_V11_V12_V13_V14_V15, RISCV::V11_V12_V13_V14_V15_V16, 92093b8bfeSCraig Topper RISCV::V12_V13_V14_V15_V16_V17, RISCV::V13_V14_V15_V16_V17_V18, 93093b8bfeSCraig Topper RISCV::V14_V15_V16_V17_V18_V19, RISCV::V15_V16_V17_V18_V19_V20, 94093b8bfeSCraig Topper RISCV::V16_V17_V18_V19_V20_V21, RISCV::V17_V18_V19_V20_V21_V22, 95093b8bfeSCraig Topper RISCV::V18_V19_V20_V21_V22_V23}; 96093b8bfeSCraig Topper static const MCPhysReg ArgVRN7M1s[] = { 97093b8bfeSCraig Topper RISCV::V8_V9_V10_V11_V12_V13_V14, RISCV::V9_V10_V11_V12_V13_V14_V15, 98093b8bfeSCraig Topper RISCV::V10_V11_V12_V13_V14_V15_V16, RISCV::V11_V12_V13_V14_V15_V16_V17, 99093b8bfeSCraig Topper RISCV::V12_V13_V14_V15_V16_V17_V18, RISCV::V13_V14_V15_V16_V17_V18_V19, 100093b8bfeSCraig Topper RISCV::V14_V15_V16_V17_V18_V19_V20, RISCV::V15_V16_V17_V18_V19_V20_V21, 101093b8bfeSCraig Topper RISCV::V16_V17_V18_V19_V20_V21_V22, RISCV::V17_V18_V19_V20_V21_V22_V23}; 102093b8bfeSCraig Topper static const MCPhysReg ArgVRN8M1s[] = {RISCV::V8_V9_V10_V11_V12_V13_V14_V15, 103093b8bfeSCraig Topper RISCV::V9_V10_V11_V12_V13_V14_V15_V16, 104093b8bfeSCraig Topper RISCV::V10_V11_V12_V13_V14_V15_V16_V17, 105093b8bfeSCraig Topper RISCV::V11_V12_V13_V14_V15_V16_V17_V18, 106093b8bfeSCraig Topper RISCV::V12_V13_V14_V15_V16_V17_V18_V19, 107093b8bfeSCraig Topper RISCV::V13_V14_V15_V16_V17_V18_V19_V20, 108093b8bfeSCraig Topper RISCV::V14_V15_V16_V17_V18_V19_V20_V21, 109093b8bfeSCraig Topper RISCV::V15_V16_V17_V18_V19_V20_V21_V22, 110093b8bfeSCraig Topper RISCV::V16_V17_V18_V19_V20_V21_V22_V23}; 111093b8bfeSCraig Topper static const MCPhysReg ArgVRN2M2s[] = {RISCV::V8M2_V10M2, RISCV::V10M2_V12M2, 112093b8bfeSCraig Topper RISCV::V12M2_V14M2, RISCV::V14M2_V16M2, 113093b8bfeSCraig Topper RISCV::V16M2_V18M2, RISCV::V18M2_V20M2, 114093b8bfeSCraig Topper RISCV::V20M2_V22M2}; 115093b8bfeSCraig Topper static const MCPhysReg ArgVRN3M2s[] = { 116093b8bfeSCraig Topper RISCV::V8M2_V10M2_V12M2, RISCV::V10M2_V12M2_V14M2, 117093b8bfeSCraig Topper RISCV::V12M2_V14M2_V16M2, RISCV::V14M2_V16M2_V18M2, 118093b8bfeSCraig Topper RISCV::V16M2_V18M2_V20M2, RISCV::V18M2_V20M2_V22M2}; 119093b8bfeSCraig Topper static const MCPhysReg ArgVRN4M2s[] = { 120093b8bfeSCraig Topper RISCV::V8M2_V10M2_V12M2_V14M2, RISCV::V10M2_V12M2_V14M2_V16M2, 121093b8bfeSCraig Topper RISCV::V12M2_V14M2_V16M2_V18M2, RISCV::V14M2_V16M2_V18M2_V20M2, 122093b8bfeSCraig Topper RISCV::V16M2_V18M2_V20M2_V22M2}; 123093b8bfeSCraig Topper static const MCPhysReg ArgVRN2M4s[] = {RISCV::V8M4_V12M4, RISCV::V12M4_V16M4, 124093b8bfeSCraig Topper RISCV::V16M4_V20M4}; 125093b8bfeSCraig Topper 126093b8bfeSCraig Topper ArrayRef<MCPhysReg> RISCV::getArgGPRs(const RISCVABI::ABI ABI) { 127093b8bfeSCraig Topper // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except 128093b8bfeSCraig Topper // the ILP32E ABI. 129093b8bfeSCraig Topper static const MCPhysReg ArgIGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12, 130093b8bfeSCraig Topper RISCV::X13, RISCV::X14, RISCV::X15, 131093b8bfeSCraig Topper RISCV::X16, RISCV::X17}; 132a43a2981SAlex Bradbury // The GPRs used for passing arguments in the ILP32E/LP64E ABI. 133093b8bfeSCraig Topper static const MCPhysReg ArgEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12, 134093b8bfeSCraig Topper RISCV::X13, RISCV::X14, RISCV::X15}; 135093b8bfeSCraig Topper 136093b8bfeSCraig Topper if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E) 137093b8bfeSCraig Topper return ArrayRef(ArgEGPRs); 138093b8bfeSCraig Topper 139093b8bfeSCraig Topper return ArrayRef(ArgIGPRs); 140093b8bfeSCraig Topper } 141093b8bfeSCraig Topper 1428a7843caSCraig Topper static ArrayRef<MCPhysReg> getArgGPR16s(const RISCVABI::ABI ABI) { 1438a7843caSCraig Topper // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except 1448a7843caSCraig Topper // the ILP32E ABI. 1458a7843caSCraig Topper static const MCPhysReg ArgIGPRs[] = {RISCV::X10_H, RISCV::X11_H, RISCV::X12_H, 1468a7843caSCraig Topper RISCV::X13_H, RISCV::X14_H, RISCV::X15_H, 1478a7843caSCraig Topper RISCV::X16_H, RISCV::X17_H}; 1488a7843caSCraig Topper // The GPRs used for passing arguments in the ILP32E/LP64E ABI. 1498a7843caSCraig Topper static const MCPhysReg ArgEGPRs[] = {RISCV::X10_H, RISCV::X11_H, 1508a7843caSCraig Topper RISCV::X12_H, RISCV::X13_H, 1518a7843caSCraig Topper RISCV::X14_H, RISCV::X15_H}; 1528a7843caSCraig Topper 1538a7843caSCraig Topper if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E) 1548a7843caSCraig Topper return ArrayRef(ArgEGPRs); 1558a7843caSCraig Topper 1568a7843caSCraig Topper return ArrayRef(ArgIGPRs); 1578a7843caSCraig Topper } 1588a7843caSCraig Topper 159*bc91f3cdSCraig Topper static ArrayRef<MCPhysReg> getArgGPR32s(const RISCVABI::ABI ABI) { 160*bc91f3cdSCraig Topper // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except 161*bc91f3cdSCraig Topper // the ILP32E ABI. 162*bc91f3cdSCraig Topper static const MCPhysReg ArgIGPRs[] = {RISCV::X10_W, RISCV::X11_W, RISCV::X12_W, 163*bc91f3cdSCraig Topper RISCV::X13_W, RISCV::X14_W, RISCV::X15_W, 164*bc91f3cdSCraig Topper RISCV::X16_W, RISCV::X17_W}; 165*bc91f3cdSCraig Topper // The GPRs used for passing arguments in the ILP32E/LP64E ABI. 166*bc91f3cdSCraig Topper static const MCPhysReg ArgEGPRs[] = {RISCV::X10_W, RISCV::X11_W, 167*bc91f3cdSCraig Topper RISCV::X12_W, RISCV::X13_W, 168*bc91f3cdSCraig Topper RISCV::X14_W, RISCV::X15_W}; 169*bc91f3cdSCraig Topper 170*bc91f3cdSCraig Topper if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E) 171*bc91f3cdSCraig Topper return ArrayRef(ArgEGPRs); 172*bc91f3cdSCraig Topper 173*bc91f3cdSCraig Topper return ArrayRef(ArgIGPRs); 174*bc91f3cdSCraig Topper } 175*bc91f3cdSCraig Topper 176093b8bfeSCraig Topper static ArrayRef<MCPhysReg> getFastCCArgGPRs(const RISCVABI::ABI ABI) { 177093b8bfeSCraig Topper // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used 178093b8bfeSCraig Topper // for save-restore libcall, so we don't use them. 179093b8bfeSCraig Topper // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register. 180093b8bfeSCraig Topper static const MCPhysReg FastCCIGPRs[] = { 181093b8bfeSCraig Topper RISCV::X10, RISCV::X11, RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15, 182093b8bfeSCraig Topper RISCV::X16, RISCV::X17, RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31}; 183093b8bfeSCraig Topper 184a43a2981SAlex Bradbury // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E. 185093b8bfeSCraig Topper static const MCPhysReg FastCCEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12, 186093b8bfeSCraig Topper RISCV::X13, RISCV::X14, RISCV::X15}; 187093b8bfeSCraig Topper 188093b8bfeSCraig Topper if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E) 189093b8bfeSCraig Topper return ArrayRef(FastCCEGPRs); 190093b8bfeSCraig Topper 191093b8bfeSCraig Topper return ArrayRef(FastCCIGPRs); 192093b8bfeSCraig Topper } 193093b8bfeSCraig Topper 1948a7843caSCraig Topper static ArrayRef<MCPhysReg> getFastCCArgGPRF16s(const RISCVABI::ABI ABI) { 1958a7843caSCraig Topper // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used 1968a7843caSCraig Topper // for save-restore libcall, so we don't use them. 1978a7843caSCraig Topper // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register. 1988a7843caSCraig Topper static const MCPhysReg FastCCIGPRs[] = { 1998a7843caSCraig Topper RISCV::X10_H, RISCV::X11_H, RISCV::X12_H, RISCV::X13_H, 2008a7843caSCraig Topper RISCV::X14_H, RISCV::X15_H, RISCV::X16_H, RISCV::X17_H, 2018a7843caSCraig Topper RISCV::X28_H, RISCV::X29_H, RISCV::X30_H, RISCV::X31_H}; 2028a7843caSCraig Topper 2038a7843caSCraig Topper // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E. 2048a7843caSCraig Topper static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_H, RISCV::X11_H, 2058a7843caSCraig Topper RISCV::X12_H, RISCV::X13_H, 2068a7843caSCraig Topper RISCV::X14_H, RISCV::X15_H}; 2078a7843caSCraig Topper 2088a7843caSCraig Topper if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E) 2098a7843caSCraig Topper return ArrayRef(FastCCEGPRs); 2108a7843caSCraig Topper 2118a7843caSCraig Topper return ArrayRef(FastCCIGPRs); 2128a7843caSCraig Topper } 2138a7843caSCraig Topper 214*bc91f3cdSCraig Topper static ArrayRef<MCPhysReg> getFastCCArgGPRF32s(const RISCVABI::ABI ABI) { 215*bc91f3cdSCraig Topper // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used 216*bc91f3cdSCraig Topper // for save-restore libcall, so we don't use them. 217*bc91f3cdSCraig Topper // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register. 218*bc91f3cdSCraig Topper static const MCPhysReg FastCCIGPRs[] = { 219*bc91f3cdSCraig Topper RISCV::X10_W, RISCV::X11_W, RISCV::X12_W, RISCV::X13_W, 220*bc91f3cdSCraig Topper RISCV::X14_W, RISCV::X15_W, RISCV::X16_W, RISCV::X17_W, 221*bc91f3cdSCraig Topper RISCV::X28_W, RISCV::X29_W, RISCV::X30_W, RISCV::X31_W}; 222*bc91f3cdSCraig Topper 223*bc91f3cdSCraig Topper // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E. 224*bc91f3cdSCraig Topper static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_W, RISCV::X11_W, 225*bc91f3cdSCraig Topper RISCV::X12_W, RISCV::X13_W, 226*bc91f3cdSCraig Topper RISCV::X14_W, RISCV::X15_W}; 227*bc91f3cdSCraig Topper 228*bc91f3cdSCraig Topper if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E) 229*bc91f3cdSCraig Topper return ArrayRef(FastCCEGPRs); 230*bc91f3cdSCraig Topper 231*bc91f3cdSCraig Topper return ArrayRef(FastCCIGPRs); 232*bc91f3cdSCraig Topper } 233*bc91f3cdSCraig Topper 234093b8bfeSCraig Topper // Pass a 2*XLEN argument that has been split into two XLEN values through 235093b8bfeSCraig Topper // registers or the stack as necessary. 236093b8bfeSCraig Topper static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1, 237093b8bfeSCraig Topper ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, 238093b8bfeSCraig Topper MVT ValVT2, MVT LocVT2, 239093b8bfeSCraig Topper ISD::ArgFlagsTy ArgFlags2, bool EABI) { 240093b8bfeSCraig Topper unsigned XLenInBytes = XLen / 8; 241093b8bfeSCraig Topper const RISCVSubtarget &STI = 242093b8bfeSCraig Topper State.getMachineFunction().getSubtarget<RISCVSubtarget>(); 243093b8bfeSCraig Topper ArrayRef<MCPhysReg> ArgGPRs = RISCV::getArgGPRs(STI.getTargetABI()); 244093b8bfeSCraig Topper 245093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(ArgGPRs)) { 246093b8bfeSCraig Topper // At least one half can be passed via register. 247093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(VA1.getValNo(), VA1.getValVT(), Reg, 248093b8bfeSCraig Topper VA1.getLocVT(), CCValAssign::Full)); 249093b8bfeSCraig Topper } else { 250093b8bfeSCraig Topper // Both halves must be passed on the stack, with proper alignment. 251093b8bfeSCraig Topper // TODO: To be compatible with GCC's behaviors, we force them to have 4-byte 252093b8bfeSCraig Topper // alignment. This behavior may be changed when RV32E/ILP32E is ratified. 253093b8bfeSCraig Topper Align StackAlign(XLenInBytes); 254093b8bfeSCraig Topper if (!EABI || XLen != 32) 255093b8bfeSCraig Topper StackAlign = std::max(StackAlign, ArgFlags1.getNonZeroOrigAlign()); 256093b8bfeSCraig Topper State.addLoc( 257093b8bfeSCraig Topper CCValAssign::getMem(VA1.getValNo(), VA1.getValVT(), 258093b8bfeSCraig Topper State.AllocateStack(XLenInBytes, StackAlign), 259093b8bfeSCraig Topper VA1.getLocVT(), CCValAssign::Full)); 260093b8bfeSCraig Topper State.addLoc(CCValAssign::getMem( 261093b8bfeSCraig Topper ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)), 262093b8bfeSCraig Topper LocVT2, CCValAssign::Full)); 263093b8bfeSCraig Topper return false; 264093b8bfeSCraig Topper } 265093b8bfeSCraig Topper 266093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(ArgGPRs)) { 267093b8bfeSCraig Topper // The second half can also be passed via register. 268093b8bfeSCraig Topper State.addLoc( 269093b8bfeSCraig Topper CCValAssign::getReg(ValNo2, ValVT2, Reg, LocVT2, CCValAssign::Full)); 270093b8bfeSCraig Topper } else { 271093b8bfeSCraig Topper // The second half is passed via the stack, without additional alignment. 272093b8bfeSCraig Topper State.addLoc(CCValAssign::getMem( 273093b8bfeSCraig Topper ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)), 274093b8bfeSCraig Topper LocVT2, CCValAssign::Full)); 275093b8bfeSCraig Topper } 276093b8bfeSCraig Topper 277093b8bfeSCraig Topper return false; 278093b8bfeSCraig Topper } 279093b8bfeSCraig Topper 280093b8bfeSCraig Topper static MCRegister allocateRVVReg(MVT ValVT, unsigned ValNo, CCState &State, 281093b8bfeSCraig Topper const RISCVTargetLowering &TLI) { 282093b8bfeSCraig Topper const TargetRegisterClass *RC = TLI.getRegClassFor(ValVT); 283093b8bfeSCraig Topper if (RC == &RISCV::VRRegClass) { 284093b8bfeSCraig Topper // Assign the first mask argument to V0. 285093b8bfeSCraig Topper // This is an interim calling convention and it may be changed in the 286093b8bfeSCraig Topper // future. 287093b8bfeSCraig Topper if (ValVT.getVectorElementType() == MVT::i1) 288093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(RISCV::V0)) 289093b8bfeSCraig Topper return Reg; 290093b8bfeSCraig Topper return State.AllocateReg(ArgVRs); 291093b8bfeSCraig Topper } 292093b8bfeSCraig Topper if (RC == &RISCV::VRM2RegClass) 293093b8bfeSCraig Topper return State.AllocateReg(ArgVRM2s); 294093b8bfeSCraig Topper if (RC == &RISCV::VRM4RegClass) 295093b8bfeSCraig Topper return State.AllocateReg(ArgVRM4s); 296093b8bfeSCraig Topper if (RC == &RISCV::VRM8RegClass) 297093b8bfeSCraig Topper return State.AllocateReg(ArgVRM8s); 298093b8bfeSCraig Topper if (RC == &RISCV::VRN2M1RegClass) 299093b8bfeSCraig Topper return State.AllocateReg(ArgVRN2M1s); 300093b8bfeSCraig Topper if (RC == &RISCV::VRN3M1RegClass) 301093b8bfeSCraig Topper return State.AllocateReg(ArgVRN3M1s); 302093b8bfeSCraig Topper if (RC == &RISCV::VRN4M1RegClass) 303093b8bfeSCraig Topper return State.AllocateReg(ArgVRN4M1s); 304093b8bfeSCraig Topper if (RC == &RISCV::VRN5M1RegClass) 305093b8bfeSCraig Topper return State.AllocateReg(ArgVRN5M1s); 306093b8bfeSCraig Topper if (RC == &RISCV::VRN6M1RegClass) 307093b8bfeSCraig Topper return State.AllocateReg(ArgVRN6M1s); 308093b8bfeSCraig Topper if (RC == &RISCV::VRN7M1RegClass) 309093b8bfeSCraig Topper return State.AllocateReg(ArgVRN7M1s); 310093b8bfeSCraig Topper if (RC == &RISCV::VRN8M1RegClass) 311093b8bfeSCraig Topper return State.AllocateReg(ArgVRN8M1s); 312093b8bfeSCraig Topper if (RC == &RISCV::VRN2M2RegClass) 313093b8bfeSCraig Topper return State.AllocateReg(ArgVRN2M2s); 314093b8bfeSCraig Topper if (RC == &RISCV::VRN3M2RegClass) 315093b8bfeSCraig Topper return State.AllocateReg(ArgVRN3M2s); 316093b8bfeSCraig Topper if (RC == &RISCV::VRN4M2RegClass) 317093b8bfeSCraig Topper return State.AllocateReg(ArgVRN4M2s); 318093b8bfeSCraig Topper if (RC == &RISCV::VRN2M4RegClass) 319093b8bfeSCraig Topper return State.AllocateReg(ArgVRN2M4s); 320093b8bfeSCraig Topper llvm_unreachable("Unhandled register class for ValueType"); 321093b8bfeSCraig Topper } 322093b8bfeSCraig Topper 323093b8bfeSCraig Topper // Implements the RISC-V calling convention. Returns true upon failure. 32462180dfdSCraig Topper bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, 32562180dfdSCraig Topper CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, 32662180dfdSCraig Topper CCState &State, bool IsFixed, bool IsRet, Type *OrigTy) { 32762180dfdSCraig Topper const MachineFunction &MF = State.getMachineFunction(); 32862180dfdSCraig Topper const DataLayout &DL = MF.getDataLayout(); 32962180dfdSCraig Topper const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>(); 33062180dfdSCraig Topper const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering(); 33162180dfdSCraig Topper 3321b8e26ffSCraig Topper unsigned XLen = Subtarget.getXLen(); 3331b8e26ffSCraig Topper MVT XLenVT = Subtarget.getXLenVT(); 334093b8bfeSCraig Topper 335093b8bfeSCraig Topper // Static chain parameter must not be passed in normal argument registers, 336093b8bfeSCraig Topper // so we assign t2 for it as done in GCC's __builtin_call_with_static_chain 337093b8bfeSCraig Topper if (ArgFlags.isNest()) { 338093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(RISCV::X7)) { 339093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 340093b8bfeSCraig Topper return false; 341093b8bfeSCraig Topper } 342093b8bfeSCraig Topper } 343093b8bfeSCraig Topper 344093b8bfeSCraig Topper // Any return value split in to more than two values can't be returned 345093b8bfeSCraig Topper // directly. Vectors are returned via the available vector registers. 346093b8bfeSCraig Topper if (!LocVT.isVector() && IsRet && ValNo > 1) 347093b8bfeSCraig Topper return true; 348093b8bfeSCraig Topper 349093b8bfeSCraig Topper // UseGPRForF16_F32 if targeting one of the soft-float ABIs, if passing a 350093b8bfeSCraig Topper // variadic argument, or if no F16/F32 argument registers are available. 351093b8bfeSCraig Topper bool UseGPRForF16_F32 = true; 352093b8bfeSCraig Topper // UseGPRForF64 if targeting soft-float ABIs or an FLEN=32 ABI, if passing a 353093b8bfeSCraig Topper // variadic argument, or if no F64 argument registers are available. 354093b8bfeSCraig Topper bool UseGPRForF64 = true; 355093b8bfeSCraig Topper 35662180dfdSCraig Topper RISCVABI::ABI ABI = Subtarget.getTargetABI(); 357093b8bfeSCraig Topper switch (ABI) { 358093b8bfeSCraig Topper default: 359093b8bfeSCraig Topper llvm_unreachable("Unexpected ABI"); 360093b8bfeSCraig Topper case RISCVABI::ABI_ILP32: 361093b8bfeSCraig Topper case RISCVABI::ABI_ILP32E: 362093b8bfeSCraig Topper case RISCVABI::ABI_LP64: 363093b8bfeSCraig Topper case RISCVABI::ABI_LP64E: 364093b8bfeSCraig Topper break; 365093b8bfeSCraig Topper case RISCVABI::ABI_ILP32F: 366093b8bfeSCraig Topper case RISCVABI::ABI_LP64F: 367093b8bfeSCraig Topper UseGPRForF16_F32 = !IsFixed; 368093b8bfeSCraig Topper break; 369093b8bfeSCraig Topper case RISCVABI::ABI_ILP32D: 370093b8bfeSCraig Topper case RISCVABI::ABI_LP64D: 371093b8bfeSCraig Topper UseGPRForF16_F32 = !IsFixed; 372093b8bfeSCraig Topper UseGPRForF64 = !IsFixed; 373093b8bfeSCraig Topper break; 374093b8bfeSCraig Topper } 375093b8bfeSCraig Topper 37614b43563SCraig Topper if ((LocVT == MVT::f16 || LocVT == MVT::bf16) && !UseGPRForF16_F32) { 37714b43563SCraig Topper if (MCRegister Reg = State.AllocateReg(ArgFPR16s)) { 37814b43563SCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 37914b43563SCraig Topper return false; 38014b43563SCraig Topper } 381093b8bfeSCraig Topper } 382093b8bfeSCraig Topper 38314b43563SCraig Topper if (LocVT == MVT::f32 && !UseGPRForF16_F32) { 38414b43563SCraig Topper if (MCRegister Reg = State.AllocateReg(ArgFPR32s)) { 38514b43563SCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 38614b43563SCraig Topper return false; 38714b43563SCraig Topper } 38814b43563SCraig Topper } 38914b43563SCraig Topper 39014b43563SCraig Topper if (LocVT == MVT::f64 && !UseGPRForF64) { 39114b43563SCraig Topper if (MCRegister Reg = State.AllocateReg(ArgFPR64s)) { 39214b43563SCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 39314b43563SCraig Topper return false; 39414b43563SCraig Topper } 39514b43563SCraig Topper } 396093b8bfeSCraig Topper 3978a7843caSCraig Topper if ((ValVT == MVT::f16 && Subtarget.hasStdExtZhinxmin())) { 3988a7843caSCraig Topper if (MCRegister Reg = State.AllocateReg(getArgGPR16s(ABI))) { 3998a7843caSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 4008a7843caSCraig Topper return false; 4018a7843caSCraig Topper } 4028a7843caSCraig Topper } 4038a7843caSCraig Topper 404*bc91f3cdSCraig Topper if (ValVT == MVT::f32 && Subtarget.hasStdExtZfinx()) { 405*bc91f3cdSCraig Topper if (MCRegister Reg = State.AllocateReg(getArgGPR32s(ABI))) { 406*bc91f3cdSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 407*bc91f3cdSCraig Topper return false; 408*bc91f3cdSCraig Topper } 409*bc91f3cdSCraig Topper } 410*bc91f3cdSCraig Topper 411093b8bfeSCraig Topper ArrayRef<MCPhysReg> ArgGPRs = RISCV::getArgGPRs(ABI); 412093b8bfeSCraig Topper 413*bc91f3cdSCraig Topper // Zdinx use GPR without a bitcast when possible. 414*bc91f3cdSCraig Topper if (LocVT == MVT::f64 && XLen == 64 && Subtarget.hasStdExtZdinx()) { 41549660e55SCraig Topper if (MCRegister Reg = State.AllocateReg(ArgGPRs)) { 41649660e55SCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 41749660e55SCraig Topper return false; 41849660e55SCraig Topper } 41949660e55SCraig Topper } 42049660e55SCraig Topper 42114b43563SCraig Topper // FP smaller than XLen, uses custom GPR. 42214b43563SCraig Topper if (LocVT == MVT::f16 || LocVT == MVT::bf16 || 42314b43563SCraig Topper (LocVT == MVT::f32 && XLen == 64)) { 42414b43563SCraig Topper if (MCRegister Reg = State.AllocateReg(ArgGPRs)) { 425093b8bfeSCraig Topper LocVT = XLenVT; 426093b8bfeSCraig Topper State.addLoc( 427093b8bfeSCraig Topper CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 428093b8bfeSCraig Topper return false; 429093b8bfeSCraig Topper } 430093b8bfeSCraig Topper } 431093b8bfeSCraig Topper 43214b43563SCraig Topper // Bitcast FP to GPR if we can use a GPR register. 43314b43563SCraig Topper if ((XLen == 32 && LocVT == MVT::f32) || (XLen == 64 && LocVT == MVT::f64)) { 43414b43563SCraig Topper if (MCRegister Reg = State.AllocateReg(ArgGPRs)) { 435093b8bfeSCraig Topper LocVT = XLenVT; 436093b8bfeSCraig Topper LocInfo = CCValAssign::BCvt; 43714b43563SCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 43814b43563SCraig Topper return false; 43914b43563SCraig Topper } 440093b8bfeSCraig Topper } 441093b8bfeSCraig Topper 442093b8bfeSCraig Topper // If this is a variadic argument, the RISC-V calling convention requires 443093b8bfeSCraig Topper // that it is assigned an 'even' or 'aligned' register if it has 8-byte 444093b8bfeSCraig Topper // alignment (RV32) or 16-byte alignment (RV64). An aligned register should 445093b8bfeSCraig Topper // be used regardless of whether the original argument was split during 446093b8bfeSCraig Topper // legalisation or not. The argument will not be passed by registers if the 447093b8bfeSCraig Topper // original type is larger than 2*XLEN, so the register alignment rule does 448093b8bfeSCraig Topper // not apply. 449093b8bfeSCraig Topper // TODO: To be compatible with GCC's behaviors, we don't align registers 450093b8bfeSCraig Topper // currently if we are using ILP32E calling convention. This behavior may be 451093b8bfeSCraig Topper // changed when RV32E/ILP32E is ratified. 452093b8bfeSCraig Topper unsigned TwoXLenInBytes = (2 * XLen) / 8; 453093b8bfeSCraig Topper if (!IsFixed && ArgFlags.getNonZeroOrigAlign() == TwoXLenInBytes && 454093b8bfeSCraig Topper DL.getTypeAllocSize(OrigTy) == TwoXLenInBytes && 455093b8bfeSCraig Topper ABI != RISCVABI::ABI_ILP32E) { 456093b8bfeSCraig Topper unsigned RegIdx = State.getFirstUnallocated(ArgGPRs); 457093b8bfeSCraig Topper // Skip 'odd' register if necessary. 458093b8bfeSCraig Topper if (RegIdx != std::size(ArgGPRs) && RegIdx % 2 == 1) 459093b8bfeSCraig Topper State.AllocateReg(ArgGPRs); 460093b8bfeSCraig Topper } 461093b8bfeSCraig Topper 462093b8bfeSCraig Topper SmallVectorImpl<CCValAssign> &PendingLocs = State.getPendingLocs(); 463093b8bfeSCraig Topper SmallVectorImpl<ISD::ArgFlagsTy> &PendingArgFlags = 464093b8bfeSCraig Topper State.getPendingArgFlags(); 465093b8bfeSCraig Topper 466093b8bfeSCraig Topper assert(PendingLocs.size() == PendingArgFlags.size() && 467093b8bfeSCraig Topper "PendingLocs and PendingArgFlags out of sync"); 468093b8bfeSCraig Topper 469093b8bfeSCraig Topper // Handle passing f64 on RV32D with a soft float ABI or when floating point 470093b8bfeSCraig Topper // registers are exhausted. 47114b43563SCraig Topper if (XLen == 32 && LocVT == MVT::f64) { 472093b8bfeSCraig Topper assert(PendingLocs.empty() && "Can't lower f64 if it is split"); 473093b8bfeSCraig Topper // Depending on available argument GPRS, f64 may be passed in a pair of 474093b8bfeSCraig Topper // GPRs, split between a GPR and the stack, or passed completely on the 475093b8bfeSCraig Topper // stack. LowerCall/LowerFormalArguments/LowerReturn must recognise these 476093b8bfeSCraig Topper // cases. 477093b8bfeSCraig Topper MCRegister Reg = State.AllocateReg(ArgGPRs); 478093b8bfeSCraig Topper if (!Reg) { 479f93114d7SCraig Topper int64_t StackOffset = State.AllocateStack(8, Align(8)); 480093b8bfeSCraig Topper State.addLoc( 481093b8bfeSCraig Topper CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo)); 482093b8bfeSCraig Topper return false; 483093b8bfeSCraig Topper } 484093b8bfeSCraig Topper LocVT = MVT::i32; 485093b8bfeSCraig Topper State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 486093b8bfeSCraig Topper MCRegister HiReg = State.AllocateReg(ArgGPRs); 487093b8bfeSCraig Topper if (HiReg) { 488093b8bfeSCraig Topper State.addLoc( 489093b8bfeSCraig Topper CCValAssign::getCustomReg(ValNo, ValVT, HiReg, LocVT, LocInfo)); 490093b8bfeSCraig Topper } else { 491f93114d7SCraig Topper int64_t StackOffset = State.AllocateStack(4, Align(4)); 492093b8bfeSCraig Topper State.addLoc( 493093b8bfeSCraig Topper CCValAssign::getCustomMem(ValNo, ValVT, StackOffset, LocVT, LocInfo)); 494093b8bfeSCraig Topper } 495093b8bfeSCraig Topper return false; 496093b8bfeSCraig Topper } 497093b8bfeSCraig Topper 498093b8bfeSCraig Topper // Split arguments might be passed indirectly, so keep track of the pending 499093b8bfeSCraig Topper // values. Split vectors are passed via a mix of registers and indirectly, so 500093b8bfeSCraig Topper // treat them as we would any other argument. 501093b8bfeSCraig Topper if (ValVT.isScalarInteger() && (ArgFlags.isSplit() || !PendingLocs.empty())) { 502093b8bfeSCraig Topper LocVT = XLenVT; 503093b8bfeSCraig Topper LocInfo = CCValAssign::Indirect; 504093b8bfeSCraig Topper PendingLocs.push_back( 505093b8bfeSCraig Topper CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo)); 506093b8bfeSCraig Topper PendingArgFlags.push_back(ArgFlags); 507093b8bfeSCraig Topper if (!ArgFlags.isSplitEnd()) { 508093b8bfeSCraig Topper return false; 509093b8bfeSCraig Topper } 510093b8bfeSCraig Topper } 511093b8bfeSCraig Topper 512093b8bfeSCraig Topper // If the split argument only had two elements, it should be passed directly 513093b8bfeSCraig Topper // in registers or on the stack. 514093b8bfeSCraig Topper if (ValVT.isScalarInteger() && ArgFlags.isSplitEnd() && 515093b8bfeSCraig Topper PendingLocs.size() <= 2) { 516093b8bfeSCraig Topper assert(PendingLocs.size() == 2 && "Unexpected PendingLocs.size()"); 517093b8bfeSCraig Topper // Apply the normal calling convention rules to the first half of the 518093b8bfeSCraig Topper // split argument. 519093b8bfeSCraig Topper CCValAssign VA = PendingLocs[0]; 520093b8bfeSCraig Topper ISD::ArgFlagsTy AF = PendingArgFlags[0]; 521093b8bfeSCraig Topper PendingLocs.clear(); 522093b8bfeSCraig Topper PendingArgFlags.clear(); 523093b8bfeSCraig Topper return CC_RISCVAssign2XLen( 524093b8bfeSCraig Topper XLen, State, VA, AF, ValNo, ValVT, LocVT, ArgFlags, 525093b8bfeSCraig Topper ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E); 526093b8bfeSCraig Topper } 527093b8bfeSCraig Topper 528093b8bfeSCraig Topper // Allocate to a register if possible, or else a stack slot. 529093b8bfeSCraig Topper MCRegister Reg; 530093b8bfeSCraig Topper unsigned StoreSizeBytes = XLen / 8; 531093b8bfeSCraig Topper Align StackAlign = Align(XLen / 8); 532093b8bfeSCraig Topper 53314b43563SCraig Topper if (ValVT.isVector() || ValVT.isRISCVVectorTuple()) { 534093b8bfeSCraig Topper Reg = allocateRVVReg(ValVT, ValNo, State, TLI); 5350e775b8cSCraig Topper if (Reg) { 5360e775b8cSCraig Topper // Fixed-length vectors are located in the corresponding scalable-vector 5370e775b8cSCraig Topper // container types. 538ee4582f9SCraig Topper if (ValVT.isFixedLengthVector()) { 5390e775b8cSCraig Topper LocVT = TLI.getContainerForFixedLengthVector(LocVT); 540ee4582f9SCraig Topper State.addLoc( 541ee4582f9SCraig Topper CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 542ee4582f9SCraig Topper return false; 543ee4582f9SCraig Topper } 5440e775b8cSCraig Topper } else { 545093b8bfeSCraig Topper // For return values, the vector must be passed fully via registers or 546093b8bfeSCraig Topper // via the stack. 547093b8bfeSCraig Topper // FIXME: The proposed vector ABI only mandates v8-v15 for return values, 548093b8bfeSCraig Topper // but we're using all of them. 549093b8bfeSCraig Topper if (IsRet) 550093b8bfeSCraig Topper return true; 551093b8bfeSCraig Topper // Try using a GPR to pass the address 552093b8bfeSCraig Topper if ((Reg = State.AllocateReg(ArgGPRs))) { 553093b8bfeSCraig Topper LocVT = XLenVT; 554093b8bfeSCraig Topper LocInfo = CCValAssign::Indirect; 555093b8bfeSCraig Topper } else if (ValVT.isScalableVector()) { 556093b8bfeSCraig Topper LocVT = XLenVT; 557093b8bfeSCraig Topper LocInfo = CCValAssign::Indirect; 558093b8bfeSCraig Topper } else { 559093b8bfeSCraig Topper StoreSizeBytes = ValVT.getStoreSize(); 560093b8bfeSCraig Topper // Align vectors to their element sizes, being careful for vXi1 561093b8bfeSCraig Topper // vectors. 562093b8bfeSCraig Topper StackAlign = MaybeAlign(ValVT.getScalarSizeInBits() / 8).valueOrOne(); 563093b8bfeSCraig Topper } 564093b8bfeSCraig Topper } 565093b8bfeSCraig Topper } else { 566093b8bfeSCraig Topper Reg = State.AllocateReg(ArgGPRs); 567093b8bfeSCraig Topper } 568093b8bfeSCraig Topper 569f93114d7SCraig Topper int64_t StackOffset = 570093b8bfeSCraig Topper Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign); 571093b8bfeSCraig Topper 572093b8bfeSCraig Topper // If we reach this point and PendingLocs is non-empty, we must be at the 573093b8bfeSCraig Topper // end of a split argument that must be passed indirectly. 574093b8bfeSCraig Topper if (!PendingLocs.empty()) { 575093b8bfeSCraig Topper assert(ArgFlags.isSplitEnd() && "Expected ArgFlags.isSplitEnd()"); 576093b8bfeSCraig Topper assert(PendingLocs.size() > 2 && "Unexpected PendingLocs.size()"); 577093b8bfeSCraig Topper 578093b8bfeSCraig Topper for (auto &It : PendingLocs) { 579093b8bfeSCraig Topper if (Reg) 580093b8bfeSCraig Topper It.convertToReg(Reg); 581093b8bfeSCraig Topper else 582093b8bfeSCraig Topper It.convertToMem(StackOffset); 583093b8bfeSCraig Topper State.addLoc(It); 584093b8bfeSCraig Topper } 585093b8bfeSCraig Topper PendingLocs.clear(); 586093b8bfeSCraig Topper PendingArgFlags.clear(); 587093b8bfeSCraig Topper return false; 588093b8bfeSCraig Topper } 589093b8bfeSCraig Topper 59014b43563SCraig Topper assert(((ValVT.isFloatingPoint() && !ValVT.isVector()) || LocVT == XLenVT || 591093b8bfeSCraig Topper (TLI.getSubtarget().hasVInstructions() && 592093b8bfeSCraig Topper (ValVT.isVector() || ValVT.isRISCVVectorTuple()))) && 593093b8bfeSCraig Topper "Expected an XLenVT or vector types at this stage"); 594093b8bfeSCraig Topper 595093b8bfeSCraig Topper if (Reg) { 596093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 597093b8bfeSCraig Topper return false; 598093b8bfeSCraig Topper } 599093b8bfeSCraig Topper 600093b8bfeSCraig Topper State.addLoc(CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo)); 601093b8bfeSCraig Topper return false; 602093b8bfeSCraig Topper } 603093b8bfeSCraig Topper 604093b8bfeSCraig Topper // FastCC has less than 1% performance improvement for some particular 605093b8bfeSCraig Topper // benchmark. But theoretically, it may have benefit for some cases. 60662180dfdSCraig Topper bool llvm::CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, 607093b8bfeSCraig Topper CCValAssign::LocInfo LocInfo, 608093b8bfeSCraig Topper ISD::ArgFlagsTy ArgFlags, CCState &State, 60962180dfdSCraig Topper bool IsFixed, bool IsRet, Type *OrigTy) { 61062180dfdSCraig Topper const MachineFunction &MF = State.getMachineFunction(); 61162180dfdSCraig Topper const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>(); 61262180dfdSCraig Topper const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering(); 61362180dfdSCraig Topper RISCVABI::ABI ABI = Subtarget.getTargetABI(); 61462180dfdSCraig Topper 615748ae69bSCraig Topper if ((LocVT == MVT::f16 && Subtarget.hasStdExtZfhmin()) || 616748ae69bSCraig Topper (LocVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin())) { 617093b8bfeSCraig Topper static const MCPhysReg FPR16List[] = { 618093b8bfeSCraig Topper RISCV::F10_H, RISCV::F11_H, RISCV::F12_H, RISCV::F13_H, RISCV::F14_H, 619093b8bfeSCraig Topper RISCV::F15_H, RISCV::F16_H, RISCV::F17_H, RISCV::F0_H, RISCV::F1_H, 620093b8bfeSCraig Topper RISCV::F2_H, RISCV::F3_H, RISCV::F4_H, RISCV::F5_H, RISCV::F6_H, 621093b8bfeSCraig Topper RISCV::F7_H, RISCV::F28_H, RISCV::F29_H, RISCV::F30_H, RISCV::F31_H}; 622093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(FPR16List)) { 623093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 624093b8bfeSCraig Topper return false; 625093b8bfeSCraig Topper } 626093b8bfeSCraig Topper } 627093b8bfeSCraig Topper 628093b8bfeSCraig Topper if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) { 629093b8bfeSCraig Topper static const MCPhysReg FPR32List[] = { 630093b8bfeSCraig Topper RISCV::F10_F, RISCV::F11_F, RISCV::F12_F, RISCV::F13_F, RISCV::F14_F, 631093b8bfeSCraig Topper RISCV::F15_F, RISCV::F16_F, RISCV::F17_F, RISCV::F0_F, RISCV::F1_F, 632093b8bfeSCraig Topper RISCV::F2_F, RISCV::F3_F, RISCV::F4_F, RISCV::F5_F, RISCV::F6_F, 633093b8bfeSCraig Topper RISCV::F7_F, RISCV::F28_F, RISCV::F29_F, RISCV::F30_F, RISCV::F31_F}; 634093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(FPR32List)) { 635093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 636093b8bfeSCraig Topper return false; 637093b8bfeSCraig Topper } 638093b8bfeSCraig Topper } 639093b8bfeSCraig Topper 640093b8bfeSCraig Topper if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) { 641093b8bfeSCraig Topper static const MCPhysReg FPR64List[] = { 642093b8bfeSCraig Topper RISCV::F10_D, RISCV::F11_D, RISCV::F12_D, RISCV::F13_D, RISCV::F14_D, 643093b8bfeSCraig Topper RISCV::F15_D, RISCV::F16_D, RISCV::F17_D, RISCV::F0_D, RISCV::F1_D, 644093b8bfeSCraig Topper RISCV::F2_D, RISCV::F3_D, RISCV::F4_D, RISCV::F5_D, RISCV::F6_D, 645093b8bfeSCraig Topper RISCV::F7_D, RISCV::F28_D, RISCV::F29_D, RISCV::F30_D, RISCV::F31_D}; 646093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(FPR64List)) { 647093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 648093b8bfeSCraig Topper return false; 649093b8bfeSCraig Topper } 650093b8bfeSCraig Topper } 651093b8bfeSCraig Topper 652859b785bSCraig Topper MVT XLenVT = Subtarget.getXLenVT(); 653859b785bSCraig Topper 6548a7843caSCraig Topper // Check if there is an available GPRF16 before hitting the stack. 6558a7843caSCraig Topper if ((LocVT == MVT::f16 && Subtarget.hasStdExtZhinxmin())) { 6568a7843caSCraig Topper if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF16s(ABI))) { 6578a7843caSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 6588a7843caSCraig Topper return false; 6598a7843caSCraig Topper } 6608a7843caSCraig Topper } 6618a7843caSCraig Topper 662*bc91f3cdSCraig Topper // Check if there is an available GPRF32 before hitting the stack. 663*bc91f3cdSCraig Topper if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) { 664*bc91f3cdSCraig Topper if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF32s(ABI))) { 665*bc91f3cdSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 666*bc91f3cdSCraig Topper return false; 667*bc91f3cdSCraig Topper } 668*bc91f3cdSCraig Topper } 669*bc91f3cdSCraig Topper 670093b8bfeSCraig Topper // Check if there is an available GPR before hitting the stack. 671*bc91f3cdSCraig Topper if (LocVT == MVT::f64 && Subtarget.is64Bit() && Subtarget.hasStdExtZdinx()) { 672093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) { 673093b8bfeSCraig Topper if (LocVT.getSizeInBits() != Subtarget.getXLen()) { 674859b785bSCraig Topper LocVT = XLenVT; 675093b8bfeSCraig Topper State.addLoc( 676093b8bfeSCraig Topper CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 677093b8bfeSCraig Topper return false; 678093b8bfeSCraig Topper } 679093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 680093b8bfeSCraig Topper return false; 681093b8bfeSCraig Topper } 682093b8bfeSCraig Topper } 683093b8bfeSCraig Topper 684859b785bSCraig Topper ArrayRef<MCPhysReg> ArgGPRs = getFastCCArgGPRs(ABI); 685093b8bfeSCraig Topper 686093b8bfeSCraig Topper if (LocVT.isVector()) { 687093b8bfeSCraig Topper if (MCRegister Reg = allocateRVVReg(ValVT, ValNo, State, TLI)) { 688093b8bfeSCraig Topper // Fixed-length vectors are located in the corresponding scalable-vector 689093b8bfeSCraig Topper // container types. 690ee4582f9SCraig Topper if (LocVT.isFixedLengthVector()) { 691093b8bfeSCraig Topper LocVT = TLI.getContainerForFixedLengthVector(LocVT); 692ee4582f9SCraig Topper State.addLoc( 693ee4582f9SCraig Topper CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 694ee4582f9SCraig Topper return false; 695ee4582f9SCraig Topper } 696093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 697d5ef3f8cSCraig Topper return false; 698d5ef3f8cSCraig Topper } 699d5ef3f8cSCraig Topper 700859b785bSCraig Topper // Pass scalable vectors indirectly. Pass fixed vectors indirectly if we 701859b785bSCraig Topper // have a free GPR. 702859b785bSCraig Topper if (LocVT.isScalableVector() || 703859b785bSCraig Topper State.getFirstUnallocated(ArgGPRs) != ArgGPRs.size()) { 704093b8bfeSCraig Topper LocInfo = CCValAssign::Indirect; 705859b785bSCraig Topper LocVT = XLenVT; 706859b785bSCraig Topper } 707d5ef3f8cSCraig Topper } 708d5ef3f8cSCraig Topper 709859b785bSCraig Topper if (LocVT == XLenVT) { 710859b785bSCraig Topper if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) { 711859b785bSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 712d5ef3f8cSCraig Topper return false; 713d5ef3f8cSCraig Topper } 714859b785bSCraig Topper } 715d5ef3f8cSCraig Topper 716859b785bSCraig Topper if (LocVT == XLenVT || LocVT == MVT::f16 || LocVT == MVT::bf16 || 717859b785bSCraig Topper LocVT == MVT::f32 || LocVT == MVT::f64 || LocVT.isFixedLengthVector()) { 718859b785bSCraig Topper Align StackAlign = MaybeAlign(ValVT.getScalarSizeInBits() / 8).valueOrOne(); 719859b785bSCraig Topper int64_t Offset = State.AllocateStack(LocVT.getStoreSize(), StackAlign); 720859b785bSCraig Topper State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 721093b8bfeSCraig Topper return false; 722093b8bfeSCraig Topper } 723093b8bfeSCraig Topper 724093b8bfeSCraig Topper return true; // CC didn't match. 725093b8bfeSCraig Topper } 726093b8bfeSCraig Topper 727093b8bfeSCraig Topper bool llvm::CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, 728093b8bfeSCraig Topper CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, 729093b8bfeSCraig Topper CCState &State) { 730093b8bfeSCraig Topper if (ArgFlags.isNest()) { 731093b8bfeSCraig Topper report_fatal_error( 732093b8bfeSCraig Topper "Attribute 'nest' is not supported in GHC calling convention"); 733093b8bfeSCraig Topper } 734093b8bfeSCraig Topper 735093b8bfeSCraig Topper static const MCPhysReg GPRList[] = { 736093b8bfeSCraig Topper RISCV::X9, RISCV::X18, RISCV::X19, RISCV::X20, RISCV::X21, RISCV::X22, 737093b8bfeSCraig Topper RISCV::X23, RISCV::X24, RISCV::X25, RISCV::X26, RISCV::X27}; 738093b8bfeSCraig Topper 739093b8bfeSCraig Topper if (LocVT == MVT::i32 || LocVT == MVT::i64) { 740093b8bfeSCraig Topper // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, R7, SpLim 741093b8bfeSCraig Topper // s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 742093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(GPRList)) { 743093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 744093b8bfeSCraig Topper return false; 745093b8bfeSCraig Topper } 746093b8bfeSCraig Topper } 747093b8bfeSCraig Topper 748093b8bfeSCraig Topper const RISCVSubtarget &Subtarget = 749093b8bfeSCraig Topper State.getMachineFunction().getSubtarget<RISCVSubtarget>(); 750093b8bfeSCraig Topper 751093b8bfeSCraig Topper if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) { 752093b8bfeSCraig Topper // Pass in STG registers: F1, ..., F6 753093b8bfeSCraig Topper // fs0 ... fs5 754093b8bfeSCraig Topper static const MCPhysReg FPR32List[] = {RISCV::F8_F, RISCV::F9_F, 755093b8bfeSCraig Topper RISCV::F18_F, RISCV::F19_F, 756093b8bfeSCraig Topper RISCV::F20_F, RISCV::F21_F}; 757093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(FPR32List)) { 758093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 759093b8bfeSCraig Topper return false; 760093b8bfeSCraig Topper } 761093b8bfeSCraig Topper } 762093b8bfeSCraig Topper 763093b8bfeSCraig Topper if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) { 764093b8bfeSCraig Topper // Pass in STG registers: D1, ..., D6 765093b8bfeSCraig Topper // fs6 ... fs11 766093b8bfeSCraig Topper static const MCPhysReg FPR64List[] = {RISCV::F22_D, RISCV::F23_D, 767093b8bfeSCraig Topper RISCV::F24_D, RISCV::F25_D, 768093b8bfeSCraig Topper RISCV::F26_D, RISCV::F27_D}; 769093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(FPR64List)) { 770093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 771093b8bfeSCraig Topper return false; 772093b8bfeSCraig Topper } 773093b8bfeSCraig Topper } 774093b8bfeSCraig Topper 775*bc91f3cdSCraig Topper if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) { 776*bc91f3cdSCraig Topper static const MCPhysReg GPR32List[] = { 777*bc91f3cdSCraig Topper RISCV::X9_W, RISCV::X18_W, RISCV::X19_W, RISCV::X20_W, 778*bc91f3cdSCraig Topper RISCV::X21_W, RISCV::X22_W, RISCV::X23_W, RISCV::X24_W, 779*bc91f3cdSCraig Topper RISCV::X25_W, RISCV::X26_W, RISCV::X27_W}; 780*bc91f3cdSCraig Topper if (MCRegister Reg = State.AllocateReg(GPR32List)) { 781*bc91f3cdSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 782*bc91f3cdSCraig Topper return false; 783*bc91f3cdSCraig Topper } 784*bc91f3cdSCraig Topper } 785*bc91f3cdSCraig Topper 786*bc91f3cdSCraig Topper if (LocVT == MVT::f64 && Subtarget.hasStdExtZdinx() && Subtarget.is64Bit()) { 787093b8bfeSCraig Topper if (MCRegister Reg = State.AllocateReg(GPRList)) { 788093b8bfeSCraig Topper State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 789093b8bfeSCraig Topper return false; 790093b8bfeSCraig Topper } 791093b8bfeSCraig Topper } 792093b8bfeSCraig Topper 793093b8bfeSCraig Topper report_fatal_error("No registers left in GHC calling convention"); 794093b8bfeSCraig Topper return true; 795093b8bfeSCraig Topper } 796