clang 24.0.0git
LoongArch.cpp
Go to the documentation of this file.
1//===- LoongArch.cpp ------------------------------------------------------===//
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#include "ABIInfoImpl.h"
10#include "TargetInfo.h"
11
12using namespace clang;
13using namespace clang::CodeGen;
14
15// LoongArch ABI Implementation. Documented at
16// https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html
17//
18//===----------------------------------------------------------------------===//
19
20namespace {
21class LoongArchABIInfo : public DefaultABIInfo {
22private:
23 // Size of the integer ('r') registers in bits.
24 unsigned GRLen;
25 // Size of the floating point ('f') registers in bits.
26 unsigned FRLen;
27 // Number of general-purpose argument registers.
28 static const int NumGARs = 8;
29 // Number of floating-point argument registers.
30 static const int NumFARs = 8;
31 bool detectFARsEligibleStructHelper(QualType Ty, CharUnits CurOff,
32 llvm::Type *&Field1Ty,
33 CharUnits &Field1Off,
34 llvm::Type *&Field2Ty,
35 CharUnits &Field2Off) const;
36
37public:
38 LoongArchABIInfo(CodeGen::CodeGenTypes &CGT, unsigned GRLen, unsigned FRLen)
39 : DefaultABIInfo(CGT), GRLen(GRLen), FRLen(FRLen) {}
40
41 void computeInfo(CGFunctionInfo &FI) const override;
42
43 ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, int &GARsLeft,
44 int &FARsLeft) const;
45 ABIArgInfo classifyReturnType(QualType RetTy) const;
46
47 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
48 AggValueSlot Slot) const override;
49
50 ABIArgInfo extendType(QualType Ty) const;
51
52 bool detectFARsEligibleStruct(QualType Ty, llvm::Type *&Field1Ty,
53 CharUnits &Field1Off, llvm::Type *&Field2Ty,
54 CharUnits &Field2Off, int &NeededArgGPRs,
55 int &NeededArgFPRs) const;
56 ABIArgInfo coerceAndExpandFARsEligibleStruct(llvm::Type *Field1Ty,
57 CharUnits Field1Off,
58 llvm::Type *Field2Ty,
59 CharUnits Field2Off) const;
60};
61} // end anonymous namespace
62
63void LoongArchABIInfo::computeInfo(CGFunctionInfo &FI) const {
64 QualType RetTy = FI.getReturnType();
65 if (!getCXXABI().classifyReturnType(FI))
67
68 // IsRetIndirect is true if classifyArgumentType indicated the value should
69 // be passed indirect, or if the type size is a scalar greater than 2*GRLen
70 // and not a complex type with elements <= FRLen. e.g. fp128 is passed direct
71 // in LLVM IR, relying on the backend lowering code to rewrite the argument
72 // list and pass indirectly on LA32.
73 bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect;
74 if (!IsRetIndirect && RetTy->isScalarType() &&
75 getContext().getTypeSize(RetTy) > (2 * GRLen)) {
76 if (RetTy->isComplexType() && FRLen) {
77 QualType EltTy = RetTy->castAs<ComplexType>()->getElementType();
78 IsRetIndirect = getContext().getTypeSize(EltTy) > FRLen;
79 } else {
80 // This is a normal scalar > 2*GRLen, such as fp128 on LA32.
81 IsRetIndirect = true;
82 }
83 }
84
85 // We must track the number of GARs and FARs used in order to conform to the
86 // LoongArch ABI. As GAR usage is different for variadic arguments, we must
87 // also track whether we are examining a vararg or not.
88 int GARsLeft = IsRetIndirect ? NumGARs - 1 : NumGARs;
89 int FARsLeft = FRLen ? NumFARs : 0;
90 int NumFixedArgs = FI.getNumRequiredArgs();
91
92 int ArgNum = 0;
93 for (auto &ArgInfo : FI.arguments()) {
94 ArgInfo.info = classifyArgumentType(
95 ArgInfo.type, /*IsFixed=*/ArgNum < NumFixedArgs, GARsLeft, FARsLeft);
96 ArgNum++;
97 }
98}
99
100// Returns true if the struct is a potential candidate to be passed in FARs (and
101// GARs). If this function returns true, the caller is responsible for checking
102// that if there is only a single field then that field is a float.
103bool LoongArchABIInfo::detectFARsEligibleStructHelper(
104 QualType Ty, CharUnits CurOff, llvm::Type *&Field1Ty, CharUnits &Field1Off,
105 llvm::Type *&Field2Ty, CharUnits &Field2Off) const {
106 bool IsInt = Ty->isIntegralOrEnumerationType();
107 bool IsFloat = Ty->isRealFloatingType();
108
109 if (IsInt || IsFloat) {
110 uint64_t Size = getContext().getTypeSize(Ty);
111 if (IsInt && Size > GRLen)
112 return false;
113 // Can't be eligible if larger than the FP registers. Handling of half
114 // precision values has been specified in the ABI, so don't block those.
115 if (IsFloat && Size > FRLen)
116 return false;
117 // Can't be eligible if an integer type was already found (int+int pairs
118 // are not eligible).
119 if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
120 return false;
121 if (!Field1Ty) {
122 Field1Ty = CGT.ConvertType(Ty);
123 Field1Off = CurOff;
124 return true;
125 }
126 if (!Field2Ty) {
127 Field2Ty = CGT.ConvertType(Ty);
128 Field2Off = CurOff;
129 return true;
130 }
131 return false;
132 }
133
134 if (auto CTy = Ty->getAs<ComplexType>()) {
135 if (Field1Ty)
136 return false;
137 QualType EltTy = CTy->getElementType();
138 // Only floating-point complex types (e.g. _Complex float/double) are
139 // eligible to be passed in floating-point argument registers. Complex
140 // integer types (a GNU extension) should be treated like a normal
141 // aggregate and packed into GARs instead.
142 if (!EltTy->isRealFloatingType())
143 return false;
144 if (getContext().getTypeSize(EltTy) > FRLen)
145 return false;
146 Field1Ty = CGT.ConvertType(EltTy);
147 Field1Off = CurOff;
148 Field2Ty = Field1Ty;
149 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
150 return true;
151 }
152
153 if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) {
154 uint64_t ArraySize = ATy->getZExtSize();
155 QualType EltTy = ATy->getElementType();
156 // Non-zero-length arrays of empty records make the struct ineligible to be
157 // passed via FARs in C++.
158 if (const auto *RTy = EltTy->getAsCanonical<RecordType>()) {
159 if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) &&
160 isEmptyRecord(getContext(), EltTy, true, true))
161 return false;
162 }
163 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
164 for (uint64_t i = 0; i < ArraySize; ++i) {
165 if (!detectFARsEligibleStructHelper(EltTy, CurOff, Field1Ty, Field1Off,
166 Field2Ty, Field2Off))
167 return false;
168 CurOff += EltSize;
169 }
170 return true;
171 }
172
173 if (const auto *RTy = Ty->getAsCanonical<RecordType>()) {
174 // Structures with either a non-trivial destructor or a non-trivial
175 // copy constructor are not eligible for the FP calling convention.
176 if (getRecordArgABI(Ty, CGT.getCXXABI()))
177 return false;
178 const RecordDecl *RD = RTy->getDecl()->getDefinitionOrSelf();
179 if (isEmptyRecord(getContext(), Ty, true, true) &&
180 (!RD->isUnion() || !isa<CXXRecordDecl>(RD)))
181 return true;
182 // Unions aren't eligible unless they're empty in C (which is caught above).
183 if (RD->isUnion())
184 return false;
185 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
186 // If this is a C++ record, check the bases first.
187 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
188 for (const CXXBaseSpecifier &B : CXXRD->bases()) {
189 const auto *BDecl = B.getType()->castAsCXXRecordDecl();
190 if (!detectFARsEligibleStructHelper(
191 B.getType(), CurOff + Layout.getBaseClassOffset(BDecl),
192 Field1Ty, Field1Off, Field2Ty, Field2Off))
193 return false;
194 }
195 }
196 for (const FieldDecl *FD : RD->fields()) {
197 QualType QTy = FD->getType();
198 if (FD->isBitField()) {
199 unsigned BitWidth = FD->getBitWidthValue();
200 // Zero-width bitfields are ignored.
201 if (BitWidth == 0)
202 continue;
203 // Allow a bitfield with a type greater than GRLen as long as the
204 // bitwidth is GRLen or less.
205 if (getContext().getTypeSize(QTy) > GRLen && BitWidth <= GRLen) {
206 QTy = getContext().getIntTypeForBitwidth(GRLen, false);
207 }
208 }
209
210 if (!detectFARsEligibleStructHelper(
211 QTy,
212 CurOff + getContext().toCharUnitsFromBits(
213 Layout.getFieldOffset(FD->getFieldIndex())),
214 Field1Ty, Field1Off, Field2Ty, Field2Off))
215 return false;
216 }
217 return Field1Ty != nullptr;
218 }
219
220 return false;
221}
222
223// Determine if a struct is eligible to be passed in FARs (and GARs) (i.e., when
224// flattened it contains a single fp value, fp+fp, or int+fp of appropriate
225// size). If so, NeededFARs and NeededGARs are incremented appropriately.
226bool LoongArchABIInfo::detectFARsEligibleStruct(
227 QualType Ty, llvm::Type *&Field1Ty, CharUnits &Field1Off,
228 llvm::Type *&Field2Ty, CharUnits &Field2Off, int &NeededGARs,
229 int &NeededFARs) const {
230 Field1Ty = nullptr;
231 Field2Ty = nullptr;
232 NeededGARs = 0;
233 NeededFARs = 0;
234 if (!detectFARsEligibleStructHelper(Ty, CharUnits::Zero(), Field1Ty,
235 Field1Off, Field2Ty, Field2Off))
236 return false;
237 if (!Field1Ty)
238 return false;
239 // Not really a candidate if we have a single int but no float.
240 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
241 return false;
242 if (Field1Ty && Field1Ty->isFloatingPointTy())
243 NeededFARs++;
244 else if (Field1Ty)
245 NeededGARs++;
246 if (Field2Ty && Field2Ty->isFloatingPointTy())
247 NeededFARs++;
248 else if (Field2Ty)
249 NeededGARs++;
250 return true;
251}
252
253// Call getCoerceAndExpand for the two-element flattened struct described by
254// Field1Ty, Field1Off, Field2Ty, Field2Off. This method will create an
255// appropriate coerceToType and unpaddedCoerceToType.
256ABIArgInfo LoongArchABIInfo::coerceAndExpandFARsEligibleStruct(
257 llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty,
258 CharUnits Field2Off) const {
259 SmallVector<llvm::Type *, 3> CoerceElts;
260 SmallVector<llvm::Type *, 2> UnpaddedCoerceElts;
261 if (!Field1Off.isZero())
262 CoerceElts.push_back(llvm::ArrayType::get(
263 llvm::Type::getInt8Ty(getVMContext()), Field1Off.getQuantity()));
264
265 CoerceElts.push_back(Field1Ty);
266 UnpaddedCoerceElts.push_back(Field1Ty);
267
268 if (!Field2Ty) {
270 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.isZero()),
271 UnpaddedCoerceElts[0]);
272 }
273
274 CharUnits Field2Align =
275 CharUnits::fromQuantity(getDataLayout().getABITypeAlign(Field2Ty));
276 CharUnits Field1End =
277 Field1Off +
278 CharUnits::fromQuantity(getDataLayout().getTypeStoreSize(Field1Ty));
279 CharUnits Field2OffNoPadNoPack = Field1End.alignTo(Field2Align);
280
281 CharUnits Padding = CharUnits::Zero();
282 if (Field2Off > Field2OffNoPadNoPack)
283 Padding = Field2Off - Field2OffNoPadNoPack;
284 else if (Field2Off != Field2Align && Field2Off > Field1End)
285 Padding = Field2Off - Field1End;
286
287 bool IsPacked = !Field2Off.isMultipleOf(Field2Align);
288
289 if (!Padding.isZero())
290 CoerceElts.push_back(llvm::ArrayType::get(
291 llvm::Type::getInt8Ty(getVMContext()), Padding.getQuantity()));
292
293 CoerceElts.push_back(Field2Ty);
294 UnpaddedCoerceElts.push_back(Field2Ty);
295
297 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked),
298 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked));
299}
300
301ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
302 int &GARsLeft,
303 int &FARsLeft) const {
304 assert(GARsLeft <= NumGARs && "GAR tracking underflow");
306
307 // Structures with either a non-trivial destructor or a non-trivial
308 // copy constructor are always passed indirectly.
309 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
310 if (GARsLeft)
311 GARsLeft -= 1;
312 return getNaturalAlignIndirect(
313 Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
314 /*ByVal=*/RAA == CGCXXABI::RAA_DirectInMemory);
315 }
316
317 uint64_t Size = getContext().getTypeSize(Ty);
318
319 // Ignore empty struct or union whose size is zero, e.g. `struct { }` in C or
320 // `struct { int a[0]; }` in C++. In C++, `struct { }` is empty but it's size
321 // is 1 byte and g++ doesn't ignore it; clang++ matches this behaviour.
322 if (isEmptyRecord(getContext(), Ty, true) && Size == 0)
323 return ABIArgInfo::getIgnore();
324
325 // Pass floating point values via FARs if possible.
326 if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() &&
327 FRLen >= Size && FARsLeft) {
328 FARsLeft--;
329 return ABIArgInfo::getDirect();
330 }
331
332 // Complex types for the *f or *d ABI must be passed directly rather than
333 // using CoerceAndExpand.
334 if (IsFixed && Ty->isComplexType() && FRLen && FARsLeft >= 2) {
335 QualType EltTy = Ty->castAs<ComplexType>()->getElementType();
336 if (getContext().getTypeSize(EltTy) <= FRLen) {
337 FARsLeft -= 2;
338 return ABIArgInfo::getDirect();
339 }
340 }
341
342 if (IsFixed && FRLen && Ty->isStructureOrClassType()) {
343 llvm::Type *Field1Ty = nullptr;
344 llvm::Type *Field2Ty = nullptr;
345 CharUnits Field1Off = CharUnits::Zero();
346 CharUnits Field2Off = CharUnits::Zero();
347 int NeededGARs = 0;
348 int NeededFARs = 0;
349 bool IsCandidate = detectFARsEligibleStruct(
350 Ty, Field1Ty, Field1Off, Field2Ty, Field2Off, NeededGARs, NeededFARs);
351 if (IsCandidate && NeededGARs <= GARsLeft && NeededFARs <= FARsLeft) {
352 GARsLeft -= NeededGARs;
353 FARsLeft -= NeededFARs;
354 return coerceAndExpandFARsEligibleStruct(Field1Ty, Field1Off, Field2Ty,
355 Field2Off);
356 }
357 }
358
359 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
360 // Determine the number of GARs needed to pass the current argument
361 // according to the ABI. 2*GRLen-aligned varargs are passed in "aligned"
362 // register pairs, so may consume 3 registers.
363 int NeededGARs = 1;
364 if (!IsFixed && NeededAlign == 2 * GRLen)
365 NeededGARs = 2 + (GARsLeft % 2);
366 else if (Size > GRLen && Size <= 2 * GRLen)
367 NeededGARs = 2;
368
369 if (NeededGARs > GARsLeft)
370 NeededGARs = GARsLeft;
371
372 GARsLeft -= NeededGARs;
373
374 if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) {
375 // Treat an enum type as its underlying type.
376 if (const auto *ED = Ty->getAsEnumDecl())
377 Ty = ED->getIntegerType();
378
379 // All integral types are promoted to GRLen width.
380 if (Size < GRLen && Ty->isIntegralOrEnumerationType())
381 return extendType(Ty);
382
383 if (const auto *EIT = Ty->getAs<BitIntType>()) {
384 if (EIT->getNumBits() < GRLen)
385 return extendType(Ty);
386 if (EIT->getNumBits() > 128 ||
387 (!getContext().getTargetInfo().hasInt128Type() &&
388 EIT->getNumBits() > 64))
389 return getNaturalAlignIndirect(
390 Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
391 /*ByVal=*/false);
392 }
393
394 return ABIArgInfo::getDirect();
395 }
396
397 // Aggregates which are <= 2*GRLen will be passed in registers if possible,
398 // so coerce to integers.
399 if (Size <= 2 * GRLen) {
400 // Use a single GRLen int if possible, 2*GRLen if 2*GRLen alignment is
401 // required, and a 2-element GRLen array if only GRLen alignment is
402 // required.
403 if (Size <= GRLen) {
405 llvm::IntegerType::get(getVMContext(), GRLen));
406 }
407 if (getContext().getTypeAlign(Ty) == 2 * GRLen) {
409 llvm::IntegerType::get(getVMContext(), 2 * GRLen));
410 }
412 llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), GRLen), 2));
413 }
414 return getNaturalAlignIndirect(
415 Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
416 /*ByVal=*/false);
417}
418
419ABIArgInfo LoongArchABIInfo::classifyReturnType(QualType RetTy) const {
420 if (RetTy->isVoidType())
421 return ABIArgInfo::getIgnore();
422 // The rules for return and argument types are the same, so defer to
423 // classifyArgumentType.
424 int GARsLeft = 2;
425 int FARsLeft = FRLen ? 2 : 0;
426 return classifyArgumentType(RetTy, /*IsFixed=*/true, GARsLeft, FARsLeft);
427}
428
429RValue LoongArchABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
430 QualType Ty, AggValueSlot Slot) const {
431 CharUnits SlotSize = CharUnits::fromQuantity(GRLen / 8);
432
433 // Empty records are ignored for parameter passing purposes.
434 if (isEmptyRecord(getContext(), Ty, true))
435 return Slot.asRValue();
436
437 auto TInfo = getContext().getTypeInfoInChars(Ty);
438
439 // Arguments bigger than 2*GRLen bytes are passed indirectly.
440 return emitVoidPtrVAArg(CGF, VAListAddr, Ty,
441 /*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo,
442 SlotSize,
443 /*AllowHigherAlign=*/true, Slot);
444}
445
446ABIArgInfo LoongArchABIInfo::extendType(QualType Ty) const {
447 int TySize = getContext().getTypeSize(Ty);
448 // LA64 ABI requires unsigned 32 bit integers to be sign extended.
449 if (GRLen == 64 && Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
450 return ABIArgInfo::getSignExtend(Ty);
451 return ABIArgInfo::getExtend(Ty);
452}
453
454namespace {
455class LoongArchTargetCodeGenInfo : public TargetCodeGenInfo {
456public:
457 LoongArchTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned GRLen,
458 unsigned FRLen)
459 : TargetCodeGenInfo(
460 std::make_unique<LoongArchABIInfo>(CGT, GRLen, FRLen)) {}
461};
462} // namespace
463
464std::unique_ptr<TargetCodeGenInfo>
466 unsigned FLen) {
467 return std::make_unique<LoongArchTargetCodeGenInfo>(CGM.getTypes(), GRLen,
468 FLen);
469}
static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type)
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
Definition CharUnits.h:143
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Definition CharUnits.h:201
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T=nullptr, llvm::Type *Padding=nullptr)
static ABIArgInfo getIgnore()
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr, llvm::Type *Padding=nullptr)
static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, llvm::Type *unpaddedCoerceToType)
RValue asRValue() const
Definition CGValue.h:713
RecordArgABI
Specify how one should pass an argument of a record type.
Definition CGCXXABI.h:150
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
Definition CGCXXABI.h:158
CGFunctionInfo - Class to encapsulate the information about a function definition.
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
This class organizes the cross-function state that is used while generating LLVM code.
DefaultABIInfo - The default implementation for ABI specific details.
Definition ABIInfoImpl.h:21
field_range fields() const
Definition Decl.h:4662
bool isUnion() const
Definition Decl.h:4062
bool isVoidType() const
Definition TypeBase.h:9113
bool isComplexType() const
isComplexType() does not include complex integers (a GCC extension).
Definition Type.cpp:761
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition Type.cpp:2385
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9407
bool isScalarType() const
Definition TypeBase.h:9219
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9235
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
bool isStructureOrClassType() const
Definition Type.cpp:743
bool isVectorType() const
Definition TypeBase.h:8880
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2435
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2998
bool isFloatingType() const
Definition Type.cpp:2419
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9340
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
RValue emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, AggValueSlot Slot, bool ForceRightAdjust=false)
Emit va_arg for a platform using the common void* representation, where arguments are simply emitted ...
bool isAggregateTypeForABI(QualType T)
QualType useFirstFieldIfTransparentUnion(QualType Ty)
Pass transparent unions as if they were the type of the first element.
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyRecord - Return true iff a structure contains only empty fields.
std::unique_ptr< TargetCodeGenInfo > createLoongArchTargetCodeGenInfo(CodeGenModule &CGM, unsigned GRLen, unsigned FLen)
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
unsigned long uint64_t