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