xref: /llvm-project/llvm/lib/Target/RISCV/RISCVCallingConv.cpp (revision bc91f3cdd57cbe4b0a456626f52960158cb3232f)
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