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