clang 22.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 if (getContext().getTypeSize(EltTy) > FRLen)
139 return false;
140 Field1Ty = CGT.ConvertType(EltTy);
141 Field1Off = CurOff;
142 Field2Ty = Field1Ty;
143 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
144 return true;
145 }
146
147 if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) {
148 uint64_t ArraySize = ATy->getZExtSize();
149 QualType EltTy = ATy->getElementType();
150 // Non-zero-length arrays of empty records make the struct ineligible to be
151 // passed via FARs in C++.
152 if (const auto *RTy = EltTy->getAsCanonical<RecordType>()) {
153 if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getOriginalDecl()) &&
154 isEmptyRecord(getContext(), EltTy, true, true))
155 return false;
156 }
157 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
158 for (uint64_t i = 0; i < ArraySize; ++i) {
159 if (!detectFARsEligibleStructHelper(EltTy, CurOff, Field1Ty, Field1Off,
160 Field2Ty, Field2Off))
161 return false;
162 CurOff += EltSize;
163 }
164 return true;
165 }
166
167 if (const auto *RTy = Ty->getAsCanonical<RecordType>()) {
168 // Structures with either a non-trivial destructor or a non-trivial
169 // copy constructor are not eligible for the FP calling convention.
170 if (getRecordArgABI(Ty, CGT.getCXXABI()))
171 return false;
172 const RecordDecl *RD = RTy->getOriginalDecl()->getDefinitionOrSelf();
173 if (isEmptyRecord(getContext(), Ty, true, true) &&
174 (!RD->isUnion() || !isa<CXXRecordDecl>(RD)))
175 return true;
176 // Unions aren't eligible unless they're empty in C (which is caught above).
177 if (RD->isUnion())
178 return false;
179 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
180 // If this is a C++ record, check the bases first.
181 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
182 for (const CXXBaseSpecifier &B : CXXRD->bases()) {
183 const auto *BDecl = B.getType()->castAsCXXRecordDecl();
184 if (!detectFARsEligibleStructHelper(
185 B.getType(), CurOff + Layout.getBaseClassOffset(BDecl),
186 Field1Ty, Field1Off, Field2Ty, Field2Off))
187 return false;
188 }
189 }
190 for (const FieldDecl *FD : RD->fields()) {
191 QualType QTy = FD->getType();
192 if (FD->isBitField()) {
193 unsigned BitWidth = FD->getBitWidthValue();
194 // Zero-width bitfields are ignored.
195 if (BitWidth == 0)
196 continue;
197 // Allow a bitfield with a type greater than GRLen as long as the
198 // bitwidth is GRLen or less.
199 if (getContext().getTypeSize(QTy) > GRLen && BitWidth <= GRLen) {
200 QTy = getContext().getIntTypeForBitwidth(GRLen, false);
201 }
202 }
203
204 if (!detectFARsEligibleStructHelper(
205 QTy,
206 CurOff + getContext().toCharUnitsFromBits(
207 Layout.getFieldOffset(FD->getFieldIndex())),
208 Field1Ty, Field1Off, Field2Ty, Field2Off))
209 return false;
210 }
211 return Field1Ty != nullptr;
212 }
213
214 return false;
215}
216
217// Determine if a struct is eligible to be passed in FARs (and GARs) (i.e., when
218// flattened it contains a single fp value, fp+fp, or int+fp of appropriate
219// size). If so, NeededFARs and NeededGARs are incremented appropriately.
220bool LoongArchABIInfo::detectFARsEligibleStruct(
221 QualType Ty, llvm::Type *&Field1Ty, CharUnits &Field1Off,
222 llvm::Type *&Field2Ty, CharUnits &Field2Off, int &NeededGARs,
223 int &NeededFARs) const {
224 Field1Ty = nullptr;
225 Field2Ty = nullptr;
226 NeededGARs = 0;
227 NeededFARs = 0;
228 if (!detectFARsEligibleStructHelper(Ty, CharUnits::Zero(), Field1Ty,
229 Field1Off, Field2Ty, Field2Off))
230 return false;
231 if (!Field1Ty)
232 return false;
233 // Not really a candidate if we have a single int but no float.
234 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
235 return false;
236 if (Field1Ty && Field1Ty->isFloatingPointTy())
237 NeededFARs++;
238 else if (Field1Ty)
239 NeededGARs++;
240 if (Field2Ty && Field2Ty->isFloatingPointTy())
241 NeededFARs++;
242 else if (Field2Ty)
243 NeededGARs++;
244 return true;
245}
246
247// Call getCoerceAndExpand for the two-element flattened struct described by
248// Field1Ty, Field1Off, Field2Ty, Field2Off. This method will create an
249// appropriate coerceToType and unpaddedCoerceToType.
250ABIArgInfo LoongArchABIInfo::coerceAndExpandFARsEligibleStruct(
251 llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty,
252 CharUnits Field2Off) const {
253 SmallVector<llvm::Type *, 3> CoerceElts;
254 SmallVector<llvm::Type *, 2> UnpaddedCoerceElts;
255 if (!Field1Off.isZero())
256 CoerceElts.push_back(llvm::ArrayType::get(
257 llvm::Type::getInt8Ty(getVMContext()), Field1Off.getQuantity()));
258
259 CoerceElts.push_back(Field1Ty);
260 UnpaddedCoerceElts.push_back(Field1Ty);
261
262 if (!Field2Ty) {
264 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.isZero()),
265 UnpaddedCoerceElts[0]);
266 }
267
268 CharUnits Field2Align =
269 CharUnits::fromQuantity(getDataLayout().getABITypeAlign(Field2Ty));
270 CharUnits Field1End =
271 Field1Off +
272 CharUnits::fromQuantity(getDataLayout().getTypeStoreSize(Field1Ty));
273 CharUnits Field2OffNoPadNoPack = Field1End.alignTo(Field2Align);
274
275 CharUnits Padding = CharUnits::Zero();
276 if (Field2Off > Field2OffNoPadNoPack)
277 Padding = Field2Off - Field2OffNoPadNoPack;
278 else if (Field2Off != Field2Align && Field2Off > Field1End)
279 Padding = Field2Off - Field1End;
280
281 bool IsPacked = !Field2Off.isMultipleOf(Field2Align);
282
283 if (!Padding.isZero())
284 CoerceElts.push_back(llvm::ArrayType::get(
285 llvm::Type::getInt8Ty(getVMContext()), Padding.getQuantity()));
286
287 CoerceElts.push_back(Field2Ty);
288 UnpaddedCoerceElts.push_back(Field2Ty);
289
291 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked),
292 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked));
293}
294
295ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
296 int &GARsLeft,
297 int &FARsLeft) const {
298 assert(GARsLeft <= NumGARs && "GAR tracking underflow");
300
301 // Structures with either a non-trivial destructor or a non-trivial
302 // copy constructor are always passed indirectly.
303 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
304 if (GARsLeft)
305 GARsLeft -= 1;
306 return getNaturalAlignIndirect(
307 Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
308 /*ByVal=*/RAA == CGCXXABI::RAA_DirectInMemory);
309 }
310
311 uint64_t Size = getContext().getTypeSize(Ty);
312
313 // Ignore empty struct or union whose size is zero, e.g. `struct { }` in C or
314 // `struct { int a[0]; }` in C++. In C++, `struct { }` is empty but it's size
315 // is 1 byte and g++ doesn't ignore it; clang++ matches this behaviour.
316 if (isEmptyRecord(getContext(), Ty, true) && Size == 0)
317 return ABIArgInfo::getIgnore();
318
319 // Pass floating point values via FARs if possible.
320 if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() &&
321 FRLen >= Size && FARsLeft) {
322 FARsLeft--;
323 return ABIArgInfo::getDirect();
324 }
325
326 // Complex types for the *f or *d ABI must be passed directly rather than
327 // using CoerceAndExpand.
328 if (IsFixed && Ty->isComplexType() && FRLen && FARsLeft >= 2) {
329 QualType EltTy = Ty->castAs<ComplexType>()->getElementType();
330 if (getContext().getTypeSize(EltTy) <= FRLen) {
331 FARsLeft -= 2;
332 return ABIArgInfo::getDirect();
333 }
334 }
335
336 if (IsFixed && FRLen && Ty->isStructureOrClassType()) {
337 llvm::Type *Field1Ty = nullptr;
338 llvm::Type *Field2Ty = nullptr;
339 CharUnits Field1Off = CharUnits::Zero();
340 CharUnits Field2Off = CharUnits::Zero();
341 int NeededGARs = 0;
342 int NeededFARs = 0;
343 bool IsCandidate = detectFARsEligibleStruct(
344 Ty, Field1Ty, Field1Off, Field2Ty, Field2Off, NeededGARs, NeededFARs);
345 if (IsCandidate && NeededGARs <= GARsLeft && NeededFARs <= FARsLeft) {
346 GARsLeft -= NeededGARs;
347 FARsLeft -= NeededFARs;
348 return coerceAndExpandFARsEligibleStruct(Field1Ty, Field1Off, Field2Ty,
349 Field2Off);
350 }
351 }
352
353 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
354 // Determine the number of GARs needed to pass the current argument
355 // according to the ABI. 2*GRLen-aligned varargs are passed in "aligned"
356 // register pairs, so may consume 3 registers.
357 int NeededGARs = 1;
358 if (!IsFixed && NeededAlign == 2 * GRLen)
359 NeededGARs = 2 + (GARsLeft % 2);
360 else if (Size > GRLen && Size <= 2 * GRLen)
361 NeededGARs = 2;
362
363 if (NeededGARs > GARsLeft)
364 NeededGARs = GARsLeft;
365
366 GARsLeft -= NeededGARs;
367
368 if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) {
369 // Treat an enum type as its underlying type.
370 if (const auto *ED = Ty->getAsEnumDecl())
371 Ty = ED->getIntegerType();
372
373 // All integral types are promoted to GRLen width.
374 if (Size < GRLen && Ty->isIntegralOrEnumerationType())
375 return extendType(Ty);
376
377 if (const auto *EIT = Ty->getAs<BitIntType>()) {
378 if (EIT->getNumBits() < GRLen)
379 return extendType(Ty);
380 if (EIT->getNumBits() > 128 ||
381 (!getContext().getTargetInfo().hasInt128Type() &&
382 EIT->getNumBits() > 64))
383 return getNaturalAlignIndirect(
384 Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
385 /*ByVal=*/false);
386 }
387
388 return ABIArgInfo::getDirect();
389 }
390
391 // Aggregates which are <= 2*GRLen will be passed in registers if possible,
392 // so coerce to integers.
393 if (Size <= 2 * GRLen) {
394 // Use a single GRLen int if possible, 2*GRLen if 2*GRLen alignment is
395 // required, and a 2-element GRLen array if only GRLen alignment is
396 // required.
397 if (Size <= GRLen) {
399 llvm::IntegerType::get(getVMContext(), GRLen));
400 }
401 if (getContext().getTypeAlign(Ty) == 2 * GRLen) {
403 llvm::IntegerType::get(getVMContext(), 2 * GRLen));
404 }
406 llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), GRLen), 2));
407 }
408 return getNaturalAlignIndirect(
409 Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
410 /*ByVal=*/false);
411}
412
413ABIArgInfo LoongArchABIInfo::classifyReturnType(QualType RetTy) const {
414 if (RetTy->isVoidType())
415 return ABIArgInfo::getIgnore();
416 // The rules for return and argument types are the same, so defer to
417 // classifyArgumentType.
418 int GARsLeft = 2;
419 int FARsLeft = FRLen ? 2 : 0;
420 return classifyArgumentType(RetTy, /*IsFixed=*/true, GARsLeft, FARsLeft);
421}
422
423RValue LoongArchABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
424 QualType Ty, AggValueSlot Slot) const {
425 CharUnits SlotSize = CharUnits::fromQuantity(GRLen / 8);
426
427 // Empty records are ignored for parameter passing purposes.
428 if (isEmptyRecord(getContext(), Ty, true))
429 return Slot.asRValue();
430
431 auto TInfo = getContext().getTypeInfoInChars(Ty);
432
433 // Arguments bigger than 2*GRLen bytes are passed indirectly.
434 return emitVoidPtrVAArg(CGF, VAListAddr, Ty,
435 /*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo,
436 SlotSize,
437 /*AllowHigherAlign=*/true, Slot);
438}
439
440ABIArgInfo LoongArchABIInfo::extendType(QualType Ty) const {
441 int TySize = getContext().getTypeSize(Ty);
442 // LA64 ABI requires unsigned 32 bit integers to be sign extended.
443 if (GRLen == 64 && Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
444 return ABIArgInfo::getSignExtend(Ty);
445 return ABIArgInfo::getExtend(Ty);
446}
447
448namespace {
449class LoongArchTargetCodeGenInfo : public TargetCodeGenInfo {
450public:
451 LoongArchTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned GRLen,
452 unsigned FRLen)
453 : TargetCodeGenInfo(
454 std::make_unique<LoongArchABIInfo>(CGT, GRLen, FRLen)) {}
455};
456} // namespace
457
458std::unique_ptr<TargetCodeGenInfo>
460 unsigned FLen) {
461 return std::make_unique<LoongArchTargetCodeGenInfo>(CGM.getTypes(), GRLen,
462 FLen);
463}
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 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)
static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, llvm::Type *unpaddedCoerceToType)
static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T=nullptr)
RValue asRValue() const
Definition CGValue.h:666
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:4512
bool isUnion() const
Definition Decl.h:3919
bool isVoidType() const
Definition TypeBase.h:8878
bool isComplexType() const
isComplexType() does not include complex integers (a GCC extension).
Definition Type.cpp:724
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition Type.cpp:2273
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9168
bool isScalarType() const
Definition TypeBase.h:8980
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:8996
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
bool isStructureOrClassType() const
Definition Type.cpp:706
bool isVectorType() const
Definition TypeBase.h:8661
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2320
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2921
bool isFloatingType() const
Definition Type.cpp:2304
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9101
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)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
unsigned long uint64_t