LLVM 24.0.0git
RISCVCallingConv.cpp
Go to the documentation of this file.
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"
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,
25 ISD::ArgFlagsTy ArgFlags, Type *OrigTy,
26 CCState &State, bool IsRet);
27
28/// Used for assigning arguments with CallingConvention::GHC
30
31/// Used for assigning arguments with CallingConvention::Fast
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
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
186 if (STI.isSoftFPABI() || !STI.hasStdExtF())
187 return {};
188
189 if (STI.hasStdExtQ())
190 return ArrayRef(ArgFPR128s);
191
192 if (STI.hasStdExtD())
193 return ArrayRef(ArgFPR64s);
194
195 return ArrayRef(ArgFPR32s);
196}
197
199 if (STI.hasVInstructions())
200 return ArrayRef(ArgVRs);
201
202 return {};
203}
204
206 // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except
207 // the ILP32E ABI.
208 static const MCPhysReg ArgIGPRs[] = {RISCV::X10_H, RISCV::X11_H, RISCV::X12_H,
209 RISCV::X13_H, RISCV::X14_H, RISCV::X15_H,
210 RISCV::X16_H, RISCV::X17_H};
211 // The GPRs used for passing arguments in the ILP32E/LP64E ABI.
212 static const MCPhysReg ArgEGPRs[] = {RISCV::X10_H, RISCV::X11_H,
213 RISCV::X12_H, RISCV::X13_H,
214 RISCV::X14_H, RISCV::X15_H};
215
216 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)
217 return ArrayRef(ArgEGPRs);
218
219 return ArrayRef(ArgIGPRs);
220}
221
223 // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except
224 // the ILP32E ABI.
225 static const MCPhysReg ArgIGPRs[] = {RISCV::X10_W, RISCV::X11_W, RISCV::X12_W,
226 RISCV::X13_W, RISCV::X14_W, RISCV::X15_W,
227 RISCV::X16_W, RISCV::X17_W};
228 // The GPRs used for passing arguments in the ILP32E/LP64E ABI.
229 static const MCPhysReg ArgEGPRs[] = {RISCV::X10_W, RISCV::X11_W,
230 RISCV::X12_W, RISCV::X13_W,
231 RISCV::X14_W, RISCV::X15_W};
232
233 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)
234 return ArrayRef(ArgEGPRs);
235
236 return ArrayRef(ArgIGPRs);
237}
238
240 // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used
241 // for save-restore libcall, so we don't use them.
242 // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.
243 static const MCPhysReg FastCCIGPRs[] = {
244 RISCV::X10, RISCV::X11, RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15,
245 RISCV::X16, RISCV::X17, RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31};
246
247 // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.
248 static const MCPhysReg FastCCEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,
249 RISCV::X13, RISCV::X14, RISCV::X15};
250
251 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)
252 return ArrayRef(FastCCEGPRs);
253
254 return ArrayRef(FastCCIGPRs);
255}
256
258 // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used
259 // for save-restore libcall, so we don't use them.
260 // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.
261 static const MCPhysReg FastCCIGPRs[] = {
262 RISCV::X10_H, RISCV::X11_H, RISCV::X12_H, RISCV::X13_H,
263 RISCV::X14_H, RISCV::X15_H, RISCV::X16_H, RISCV::X17_H,
264 RISCV::X28_H, RISCV::X29_H, RISCV::X30_H, RISCV::X31_H};
265
266 // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.
267 static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_H, RISCV::X11_H,
268 RISCV::X12_H, RISCV::X13_H,
269 RISCV::X14_H, RISCV::X15_H};
270
271 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)
272 return ArrayRef(FastCCEGPRs);
273
274 return ArrayRef(FastCCIGPRs);
275}
276
278 // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used
279 // for save-restore libcall, so we don't use them.
280 // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.
281 static const MCPhysReg FastCCIGPRs[] = {
282 RISCV::X10_W, RISCV::X11_W, RISCV::X12_W, RISCV::X13_W,
283 RISCV::X14_W, RISCV::X15_W, RISCV::X16_W, RISCV::X17_W,
284 RISCV::X28_W, RISCV::X29_W, RISCV::X30_W, RISCV::X31_W};
285
286 // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.
287 static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_W, RISCV::X11_W,
288 RISCV::X12_W, RISCV::X13_W,
289 RISCV::X14_W, RISCV::X15_W};
290
291 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)
292 return ArrayRef(FastCCEGPRs);
293
294 return ArrayRef(FastCCIGPRs);
295}
296
297// Pass a 2*XLEN argument that has been split into two XLEN values through
298// registers or the stack as necessary.
300 ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2,
301 MVT ValVT2, MVT LocVT2,
302 ISD::ArgFlagsTy ArgFlags2,
303 const RISCVSubtarget &Subtarget) {
304 unsigned XLen = Subtarget.getXLen();
305 unsigned XLenInBytes = XLen / 8;
306 RISCVABI::ABI ABI = Subtarget.getTargetABI();
307 bool EABI = ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E;
308
310
311 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {
312 // At least one half can be passed via register.
313 State.addLoc(CCValAssign::getReg(VA1.getValNo(), VA1.getValVT(), Reg,
315 } else {
316 // Both halves must be passed on the stack, with proper alignment.
317 // TODO: To be compatible with GCC's behaviors, we force them to have 4-byte
318 // alignment. This behavior may be changed when RV32E/ILP32E is ratified.
319 Align StackAlign(XLenInBytes);
320 if (!EABI || XLen != 32)
321 StackAlign = std::max(StackAlign, ArgFlags1.getNonZeroOrigAlign());
322 State.addLoc(
324 State.AllocateStack(XLenInBytes, StackAlign),
326 State.addLoc(CCValAssign::getMem(
327 ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)),
328 LocVT2, CCValAssign::Full));
329 return false;
330 }
331
332 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {
333 // The second half can also be passed via register.
334 State.addLoc(
335 CCValAssign::getReg(ValNo2, ValVT2, Reg, LocVT2, CCValAssign::Full));
336 } else {
337 // The second half is passed via the stack, without additional alignment.
338 State.addLoc(CCValAssign::getMem(
339 ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)),
340 LocVT2, CCValAssign::Full));
341 }
342
343 return false;
344}
345
346static MCRegister allocateRVVReg(MVT LocVT, unsigned ValNo, CCState &State,
347 const RISCVTargetLowering &TLI) {
348 const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT);
349 if (RC == &RISCV::VRRegClass) {
350 // Assign the first mask argument to V0.
351 // This is an interim calling convention and it may be changed in the
352 // future.
353 if (LocVT.getVectorElementType() == MVT::i1)
354 if (MCRegister Reg = State.AllocateReg(RISCV::V0))
355 return Reg;
356 return State.AllocateReg(ArgVRs);
357 }
358 if (RC == &RISCV::VRM2RegClass)
359 return State.AllocateReg(ArgVRM2s);
360 if (RC == &RISCV::VRM4RegClass)
361 return State.AllocateReg(ArgVRM4s);
362 if (RC == &RISCV::VRM8RegClass)
363 return State.AllocateReg(ArgVRM8s);
364 if (RC == &RISCV::VRN2M1RegClass)
365 return State.AllocateReg(ArgVRN2M1s);
366 if (RC == &RISCV::VRN3M1RegClass)
367 return State.AllocateReg(ArgVRN3M1s);
368 if (RC == &RISCV::VRN4M1RegClass)
369 return State.AllocateReg(ArgVRN4M1s);
370 if (RC == &RISCV::VRN5M1RegClass)
371 return State.AllocateReg(ArgVRN5M1s);
372 if (RC == &RISCV::VRN6M1RegClass)
373 return State.AllocateReg(ArgVRN6M1s);
374 if (RC == &RISCV::VRN7M1RegClass)
375 return State.AllocateReg(ArgVRN7M1s);
376 if (RC == &RISCV::VRN8M1RegClass)
377 return State.AllocateReg(ArgVRN8M1s);
378 if (RC == &RISCV::VRN2M2RegClass)
379 return State.AllocateReg(ArgVRN2M2s);
380 if (RC == &RISCV::VRN3M2RegClass)
381 return State.AllocateReg(ArgVRN3M2s);
382 if (RC == &RISCV::VRN4M2RegClass)
383 return State.AllocateReg(ArgVRN4M2s);
384 if (RC == &RISCV::VRN2M4RegClass)
385 return State.AllocateReg(ArgVRN2M4s);
386 llvm_unreachable("Unhandled register class for ValueType");
387}
388
389// Implements the RISC-V calling convention. Returns true upon failure.
390//
391// This has a slightly different signature to CCAssignFn - it adds `bool IsRet`.
392static bool CC_RISCV_Impl(unsigned ValNo, MVT ValVT, MVT LocVT,
393 CCValAssign::LocInfo LocInfo,
394 ISD::ArgFlagsTy ArgFlags, Type *OrigTy,
395 CCState &State, bool IsRet) {
396 assert(ValVT == LocVT && "Expected ValVT and LocVT to match");
397 const MachineFunction &MF = State.getMachineFunction();
398 const DataLayout &DL = MF.getDataLayout();
399 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
400 const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering();
401
402 unsigned XLen = Subtarget.getXLen();
403 MVT XLenVT = Subtarget.getXLenVT();
404
405 if (ArgFlags.isNest()) {
406 // Static chain parameter must not be passed in normal argument registers,
407 // so we assign t2/t3 for it as done in GCC's
408 // __builtin_call_with_static_chain
409 bool HasCFBranch =
410 MF.getInfo<RISCVMachineFunctionInfo>()->hasCFProtectionBranch();
411
412 // Normal: t2, Branch control flow protection: t3
413 const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7;
414
415 RISCVABI::ABI ABI = Subtarget.getTargetABI();
416 if (HasCFBranch &&
417 (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E))
419 "Nested functions with control flow protection are not "
420 "usable with ILP32E or LP64E ABI.");
421 if (MCRegister Reg = State.AllocateReg(StaticChainReg)) {
422 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
423 return false;
424 }
425 }
426
427 // Any return value split in to more than two values can't be returned
428 // directly. Vectors are returned via the available vector registers.
429 if ((!LocVT.isVector() || Subtarget.isPExtPackedType(LocVT)) && IsRet &&
430 ValNo > 1)
431 return true;
432
433 // Double wide packed types require 2 GPRs so we can only return 1 of them.
434 if (Subtarget.isPExtPackedDoubleType(LocVT) && IsRet && ValNo > 0)
435 return true;
436
437 // AllowFPRForF16_F32 if targeting an FLEN>=32 ABI and the argument isn't
438 // variadic.
439 bool AllowFPRForF16_F32 = false;
440 // UseFPRForF64 if targeting an FLEN>=64 ABI and the argument isn't variadic.
441 bool AllowFPRForF64 = false;
442
443 RISCVABI::ABI ABI = Subtarget.getTargetABI();
444 switch (ABI) {
445 default:
446 llvm_unreachable("Unexpected ABI");
451 break;
454 AllowFPRForF64 = !ArgFlags.isVarArg();
455 [[fallthrough]];
458 AllowFPRForF16_F32 = !ArgFlags.isVarArg();
459 break;
460 }
461
462 if ((LocVT == MVT::f16 || LocVT == MVT::bf16) && AllowFPRForF16_F32) {
463 if (MCRegister Reg = State.AllocateReg(ArgFPR16s)) {
464 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
465 return false;
466 }
467 }
468
469 if (LocVT == MVT::f32 && AllowFPRForF16_F32) {
470 if (MCRegister Reg = State.AllocateReg(ArgFPR32s)) {
471 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
472 return false;
473 }
474 }
475
476 if (LocVT == MVT::f64 && AllowFPRForF64) {
477 if (MCRegister Reg = State.AllocateReg(ArgFPR64s)) {
478 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
479 return false;
480 }
481 }
482
483 if (LocVT == MVT::f16 && Subtarget.hasStdExtZhinxmin()) {
484 if (MCRegister Reg = State.AllocateReg(getArgGPR16s(ABI))) {
485 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
486 return false;
487 }
488 }
489
490 if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {
491 if (MCRegister Reg = State.AllocateReg(getArgGPR32s(ABI))) {
492 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
493 return false;
494 }
495 }
496
498
499 // Zdinx use GPR without a bitcast when possible.
500 if (LocVT == MVT::f64 && XLen == 64 && Subtarget.hasStdExtZdinx()) {
501 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {
502 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
503 return false;
504 }
505 }
506
507 // FP smaller than XLen, uses custom GPR.
508 if (LocVT == MVT::f16 || LocVT == MVT::bf16 ||
509 (LocVT == MVT::f32 && XLen == 64)) {
510 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {
511 LocVT = XLenVT;
512 State.addLoc(
513 CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
514 return false;
515 }
516 }
517
518 // Bitcast FP to GPR if we can use a GPR register.
519 if ((XLen == 32 && LocVT == MVT::f32) || (XLen == 64 && LocVT == MVT::f64)) {
520 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {
521 LocVT = XLenVT;
522 LocInfo = CCValAssign::BCvt;
523 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
524 return false;
525 }
526 }
527
528 // If this is a variadic argument, the RISC-V calling convention requires
529 // that it is assigned an 'even' or 'aligned' register if it has 8-byte
530 // alignment (RV32) or 16-byte alignment (RV64). An aligned register should
531 // be used regardless of whether the original argument was split during
532 // legalisation or not. The argument will not be passed by registers if the
533 // original type is larger than 2*XLEN, so the register alignment rule does
534 // not apply.
535 // TODO: To be compatible with GCC's behaviors, we don't align registers
536 // currently if we are using ILP32E calling convention. This behavior may be
537 // changed when RV32E/ILP32E is ratified.
538 unsigned TwoXLenInBytes = (2 * XLen) / 8;
539 if (ArgFlags.isVarArg() && ArgFlags.getNonZeroOrigAlign() == TwoXLenInBytes &&
540 DL.getTypeAllocSize(OrigTy) == TwoXLenInBytes &&
541 ABI != RISCVABI::ABI_ILP32E) {
542 unsigned RegIdx = State.getFirstUnallocated(ArgGPRs);
543 // Skip 'odd' register if necessary.
544 if (RegIdx != std::size(ArgGPRs) && RegIdx % 2 == 1)
545 State.AllocateReg(ArgGPRs);
546 }
547
548 SmallVectorImpl<CCValAssign> &PendingLocs = State.getPendingLocs();
549 SmallVectorImpl<ISD::ArgFlagsTy> &PendingArgFlags =
550 State.getPendingArgFlags();
551
552 assert(PendingLocs.size() == PendingArgFlags.size() &&
553 "PendingLocs and PendingArgFlags out of sync");
554
555 // Handle passing f64 on RV32D with a soft float ABI or when floating point
556 // registers are exhausted. Or 64-bit P extension vectors on RV32.
557 if (XLen == 32 &&
558 (LocVT == MVT::f64 || (Subtarget.isPExtPackedDoubleType(LocVT) &&
559 !ArgFlags.isSplit() && PendingLocs.empty()))) {
560 assert(PendingLocs.empty() &&
561 "Can't lower f64 or P extension vector if it is split");
562 // Depending on available argument GPRS, f64 may be passed in a pair of
563 // GPRs, split between a GPR and the stack, or passed completely on the
564 // stack. LowerCall/LowerFormalArguments/LowerReturn must recognise these
565 // cases.
566 MCRegister Reg = State.AllocateReg(ArgGPRs);
567 if (!Reg) {
568 int64_t StackOffset = State.AllocateStack(8, Align(8));
569 State.addLoc(
570 CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));
571 return false;
572 }
573 LocVT = MVT::i32;
574 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
575 MCRegister HiReg = State.AllocateReg(ArgGPRs);
576 if (HiReg) {
577 State.addLoc(
578 CCValAssign::getCustomReg(ValNo, ValVT, HiReg, LocVT, LocInfo));
579 } else {
580 int64_t StackOffset = State.AllocateStack(4, Align(4));
581 State.addLoc(
582 CCValAssign::getCustomMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));
583 }
584 return false;
585 }
586
587 // If the split argument only had two elements, it should be passed directly
588 // in registers or on the stack.
589 if ((LocVT.isScalarInteger() ||
590 (Subtarget.isPExtPackedType(LocVT) && LocVT.getSizeInBits() == XLen)) &&
591 ArgFlags.isSplitEnd() && PendingLocs.size() <= 1) {
592 assert(PendingLocs.size() == 1 && "Unexpected PendingLocs.size()");
593 // Apply the normal calling convention rules to the first half of the
594 // split argument.
595 CCValAssign VA = PendingLocs[0];
596 ISD::ArgFlagsTy AF = PendingArgFlags[0];
597 PendingLocs.clear();
598 PendingArgFlags.clear();
599 return CC_RISCVAssign2XLen(State, VA, AF, ValNo, ValVT, LocVT, ArgFlags,
600 Subtarget);
601 }
602
603 // Split arguments might be passed indirectly, so keep track of the pending
604 // values. Split vectors excluding P extension packed vectors(see
605 // isPExtPackedType) are passed via a mix of registers and indirectly, so
606 // treat them as we would any other argument.
607 if ((LocVT.isScalarInteger() || Subtarget.isPExtPackedType(LocVT)) &&
608 (ArgFlags.isSplit() || !PendingLocs.empty())) {
609 PendingLocs.push_back(
610 CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo));
611 PendingArgFlags.push_back(ArgFlags);
612 if (!ArgFlags.isSplitEnd()) {
613 return false;
614 }
615 }
616
617 // Allocate to a register if possible, or else a stack slot.
619 unsigned StoreSizeBytes = XLen / 8;
620 Align StackAlign = Align(XLen / 8);
621
622 // FIXME: If P extension and V extension are enabled at the same time,
623 // who should go first?
624 if (!Subtarget.isPExtPackedType(LocVT) &&
625 (LocVT.isVector() || LocVT.isRISCVVectorTuple())) {
626 Reg = allocateRVVReg(LocVT, ValNo, State, TLI);
627 if (Reg) {
628 // Fixed-length vectors are located in the corresponding scalable-vector
629 // container types.
630 if (LocVT.isFixedLengthVector()) {
631 LocVT = TLI.getContainerForFixedLengthVector(LocVT);
632 State.addLoc(
633 CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
634 return false;
635 }
636 } else {
637 // For return values, the vector must be passed fully via registers or
638 // via the stack.
639 if (IsRet)
640 return true;
641 // Try using a GPR to pass the address
642 if ((Reg = State.AllocateReg(ArgGPRs))) {
643 LocVT = XLenVT;
644 LocInfo = CCValAssign::Indirect;
645 } else if (LocVT.isScalableVector()) {
646 LocVT = XLenVT;
647 LocInfo = CCValAssign::Indirect;
648 } else {
649 StoreSizeBytes = LocVT.getStoreSize();
650 // Align vectors to their element sizes, being careful for vXi1
651 // vectors.
652 StackAlign = MaybeAlign(LocVT.getScalarSizeInBits() / 8).valueOrOne();
653 }
654 }
655 } else {
656 Reg = State.AllocateReg(ArgGPRs);
657 }
658
659 int64_t StackOffset =
660 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
661
662 // If we reach this point and PendingLocs is non-empty, we must be at the
663 // end of a split argument that must be passed indirectly.
664 if (!PendingLocs.empty()) {
665 assert(ArgFlags.isSplitEnd() && "Expected ArgFlags.isSplitEnd()");
666 assert(PendingLocs.size() > 1 && "Unexpected PendingLocs.size()");
667
668 for (auto &It : PendingLocs) {
669 if (Reg)
670 State.addLoc(CCValAssign::getReg(It.getValNo(), It.getValVT(), Reg,
671 XLenVT, CCValAssign::Indirect));
672 else
673 State.addLoc(CCValAssign::getMem(It.getValNo(), It.getValVT(),
674 StackOffset, XLenVT,
676 }
677 PendingLocs.clear();
678 PendingArgFlags.clear();
679 return false;
680 }
681
682 assert(((LocVT.isFloatingPoint() && !LocVT.isVector()) || LocVT == XLenVT ||
683 Subtarget.isPExtPackedType(LocVT) ||
684 (TLI.getSubtarget().hasVInstructions() &&
685 (LocVT.isVector() || LocVT.isRISCVVectorTuple()))) &&
686 "Expected an XLenVT or vector types at this stage");
687
688 if (Reg) {
689 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
690 return false;
691 }
692
693 State.addLoc(CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));
694 return false;
695}
696
697// FastCC has less than 1% performance improvement for some particular
698// benchmark. But theoretically, it may have benefit for some cases.
699static bool CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT,
700 CCValAssign::LocInfo LocInfo,
701 ISD::ArgFlagsTy ArgFlags, Type *OrigTy,
702 CCState &State) {
703 const MachineFunction &MF = State.getMachineFunction();
704 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
705 const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering();
706 RISCVABI::ABI ABI = Subtarget.getTargetABI();
707
708 if ((LocVT == MVT::f16 && Subtarget.hasStdExtZfhmin()) ||
709 (LocVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin())) {
710 static const MCPhysReg FPR16List[] = {
711 RISCV::F10_H, RISCV::F11_H, RISCV::F12_H, RISCV::F13_H, RISCV::F14_H,
712 RISCV::F15_H, RISCV::F16_H, RISCV::F17_H, RISCV::F0_H, RISCV::F1_H,
713 RISCV::F2_H, RISCV::F3_H, RISCV::F4_H, RISCV::F5_H, RISCV::F6_H,
714 RISCV::F7_H, RISCV::F28_H, RISCV::F29_H, RISCV::F30_H, RISCV::F31_H};
715 if (MCRegister Reg = State.AllocateReg(FPR16List)) {
716 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
717 return false;
718 }
719 }
720
721 if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {
722 static const MCPhysReg FPR32List[] = {
723 RISCV::F10_F, RISCV::F11_F, RISCV::F12_F, RISCV::F13_F, RISCV::F14_F,
724 RISCV::F15_F, RISCV::F16_F, RISCV::F17_F, RISCV::F0_F, RISCV::F1_F,
725 RISCV::F2_F, RISCV::F3_F, RISCV::F4_F, RISCV::F5_F, RISCV::F6_F,
726 RISCV::F7_F, RISCV::F28_F, RISCV::F29_F, RISCV::F30_F, RISCV::F31_F};
727 if (MCRegister Reg = State.AllocateReg(FPR32List)) {
728 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
729 return false;
730 }
731 }
732
733 if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {
734 static const MCPhysReg FPR64List[] = {
735 RISCV::F10_D, RISCV::F11_D, RISCV::F12_D, RISCV::F13_D, RISCV::F14_D,
736 RISCV::F15_D, RISCV::F16_D, RISCV::F17_D, RISCV::F0_D, RISCV::F1_D,
737 RISCV::F2_D, RISCV::F3_D, RISCV::F4_D, RISCV::F5_D, RISCV::F6_D,
738 RISCV::F7_D, RISCV::F28_D, RISCV::F29_D, RISCV::F30_D, RISCV::F31_D};
739 if (MCRegister Reg = State.AllocateReg(FPR64List)) {
740 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
741 return false;
742 }
743 }
744
745 MVT XLenVT = Subtarget.getXLenVT();
746
747 // Check if there is an available GPRF16 before hitting the stack.
748 if ((LocVT == MVT::f16 && Subtarget.hasStdExtZhinxmin())) {
749 if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF16s(ABI))) {
750 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
751 return false;
752 }
753 }
754
755 // Check if there is an available GPRF32 before hitting the stack.
756 if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {
757 if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF32s(ABI))) {
758 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
759 return false;
760 }
761 }
762
763 // Check if there is an available GPR before hitting the stack.
764 if (LocVT == MVT::f64 && Subtarget.is64Bit() && Subtarget.hasStdExtZdinx()) {
765 if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) {
766 if (LocVT.getSizeInBits() != Subtarget.getXLen()) {
767 LocVT = XLenVT;
768 State.addLoc(
769 CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
770 return false;
771 }
772 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
773 return false;
774 }
775 }
776
778
779 if (LocVT.isVector()) {
780 if (MCRegister Reg = allocateRVVReg(ValVT, ValNo, State, TLI)) {
781 // Fixed-length vectors are located in the corresponding scalable-vector
782 // container types.
783 if (LocVT.isFixedLengthVector()) {
784 LocVT = TLI.getContainerForFixedLengthVector(LocVT);
785 State.addLoc(
786 CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
787 return false;
788 }
789 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
790 return false;
791 }
792
793 // Pass scalable vectors indirectly. Pass fixed vectors indirectly if we
794 // have a free GPR.
795 if (LocVT.isScalableVector() ||
796 State.getFirstUnallocated(ArgGPRs) != ArgGPRs.size()) {
797 LocInfo = CCValAssign::Indirect;
798 LocVT = XLenVT;
799 }
800 }
801
802 if (LocVT == XLenVT) {
803 if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) {
804 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
805 return false;
806 }
807 }
808
809 if (LocVT == XLenVT || LocVT == MVT::f16 || LocVT == MVT::bf16 ||
810 LocVT == MVT::f32 || LocVT == MVT::f64 || LocVT.isFixedLengthVector()) {
811 Align StackAlign = MaybeAlign(ValVT.getScalarSizeInBits() / 8).valueOrOne();
812 int64_t Offset = State.AllocateStack(LocVT.getStoreSize(), StackAlign);
813 State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
814 return false;
815 }
816
817 return true; // CC didn't match.
818}
819
820static bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,
821 CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
822 Type *OrigTy, CCState &State) {
823 if (ArgFlags.isNest()) {
825 "Attribute 'nest' is not supported in GHC calling convention");
826 }
827
828 static const MCPhysReg GPRList[] = {
829 RISCV::X9, RISCV::X18, RISCV::X19, RISCV::X20, RISCV::X21, RISCV::X22,
830 RISCV::X23, RISCV::X24, RISCV::X25, RISCV::X26, RISCV::X27};
831
832 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
833 // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, R7, SpLim
834 // s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11
835 if (MCRegister Reg = State.AllocateReg(GPRList)) {
836 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
837 return false;
838 }
839 }
840
841 const RISCVSubtarget &Subtarget =
842 State.getMachineFunction().getSubtarget<RISCVSubtarget>();
843
844 if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {
845 // Pass in STG registers: F1, ..., F6
846 // fs0 ... fs5
847 static const MCPhysReg FPR32List[] = {RISCV::F8_F, RISCV::F9_F,
848 RISCV::F18_F, RISCV::F19_F,
849 RISCV::F20_F, RISCV::F21_F};
850 if (MCRegister Reg = State.AllocateReg(FPR32List)) {
851 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
852 return false;
853 }
854 }
855
856 if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {
857 // Pass in STG registers: D1, ..., D6
858 // fs6 ... fs11
859 static const MCPhysReg FPR64List[] = {RISCV::F22_D, RISCV::F23_D,
860 RISCV::F24_D, RISCV::F25_D,
861 RISCV::F26_D, RISCV::F27_D};
862 if (MCRegister Reg = State.AllocateReg(FPR64List)) {
863 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
864 return false;
865 }
866 }
867
868 if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {
869 static const MCPhysReg GPR32List[] = {
870 RISCV::X9_W, RISCV::X18_W, RISCV::X19_W, RISCV::X20_W,
871 RISCV::X21_W, RISCV::X22_W, RISCV::X23_W, RISCV::X24_W,
872 RISCV::X25_W, RISCV::X26_W, RISCV::X27_W};
873 if (MCRegister Reg = State.AllocateReg(GPR32List)) {
874 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
875 return false;
876 }
877 }
878
879 if (LocVT == MVT::f64 && Subtarget.hasStdExtZdinx() && Subtarget.is64Bit()) {
880 if (MCRegister Reg = State.AllocateReg(GPRList)) {
881 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
882 return false;
883 }
884 }
885
886 report_fatal_error("No registers left in GHC calling convention");
887 return true;
888}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const MCPhysReg ArgFPR32s[]
const MCPhysReg ArgVRs[]
const MCPhysReg ArgFPR64s[]
const MCPhysReg ArgGPRs[]
Register Reg
static const MCPhysReg ArgVRN2M2s[]
static CCAssignFn CC_RISCV_FastCC
Used for assigning arguments with CallingConvention::Fast.
static const MCPhysReg ArgVRM2s[]
static CCAssignFn CC_RISCV_GHC
Used for assigning arguments with CallingConvention::GHC.
static const MCPhysReg ArgVRN3M2s[]
static const MCPhysReg ArgVRN4M1s[]
static const MCPhysReg ArgVRN6M1s[]
static bool CC_RISCV_Impl(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State, bool IsRet)
static ArrayRef< MCPhysReg > getFastCCArgGPRF32s(const RISCVABI::ABI ABI)
static const MCPhysReg ArgVRN4M2s[]
static const MCPhysReg ArgFPR128s[]
static const MCPhysReg ArgVRN3M1s[]
static const MCPhysReg ArgVRN7M1s[]
static bool CC_RISCVAssign2XLen(CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2, const RISCVSubtarget &Subtarget)
static MCRegister allocateRVVReg(MVT LocVT, unsigned ValNo, CCState &State, const RISCVTargetLowering &TLI)
static const MCPhysReg ArgVRN5M1s[]
static const MCPhysReg ArgVRN2M4s[]
static ArrayRef< MCPhysReg > getFastCCArgGPRF16s(const RISCVABI::ABI ABI)
static ArrayRef< MCPhysReg > getArgGPR32s(const RISCVABI::ABI ABI)
static const MCPhysReg ArgVRN2M1s[]
static const MCPhysReg ArgVRN8M1s[]
static ArrayRef< MCPhysReg > getArgGPR16s(const RISCVABI::ABI ABI)
static ArrayRef< MCPhysReg > getFastCCArgGPRs(const RISCVABI::ABI ABI)
static const MCPhysReg ArgVRM8s[]
static const MCPhysReg ArgVRM4s[]
static const MCPhysReg ArgFPR16s[]
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
CCState - This class holds information needed while lowering arguments and return values.
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Machine Value Type.
bool isRISCVVectorTuple() const
Return true if this is a RISCV vector tuple type where the runtime length is machine dependent.
uint64_t getScalarSizeInBits() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isFixedLengthVector() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
RISCVABI::ABI getTargetABI() const
bool isPExtPackedDoubleType(MVT VT) const
bool isPExtPackedType(MVT VT) const
unsigned getXLen() const
bool hasVInstructions() const
const RISCVTargetLowering * getTargetLowering() const override
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:31
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
Definition CallingConv.h:50
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
ArrayRef< MCPhysReg > getArgFPRs(const RISCVSubtarget &STI)
ArrayRef< MCPhysReg > getArgGPRs(const RISCVSubtarget &STI)
ArrayRef< MCPhysReg > getArgVRs(const RISCVSubtarget &STI)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
CCAssignFn RetCC_RISCV
This is used for assigning return values to locations when making calls.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
ArrayRef(const T &OneElt) -> ArrayRef< T >
CCAssignFn CC_RISCV
This is used for assigining arguments to locations when making calls.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Align getNonZeroOrigAlign() const
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:111
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:135