10#include "TargetInfo.h"
28 static const int NumGARs = 8;
30 static const int NumFARs = 8;
31 bool detectFARsEligibleStructHelper(QualType Ty, CharUnits CurOff,
32 llvm::Type *&Field1Ty,
34 llvm::Type *&Field2Ty,
35 CharUnits &Field2Off)
const;
38 LoongArchABIInfo(CodeGen::CodeGenTypes &CGT,
unsigned GRLen,
unsigned FRLen)
39 : DefaultABIInfo(CGT), GRLen(GRLen), FRLen(FRLen) {}
41 void computeInfo(CGFunctionInfo &FI)
const override;
47 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
48 AggValueSlot Slot)
const override;
50 ABIArgInfo extendType(QualType Ty)
const;
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,
59 CharUnits Field2Off)
const;
75 getContext().getTypeSize(RetTy) > (2 * GRLen)) {
77 QualType EltTy = RetTy->
castAs<ComplexType>()->getElementType();
78 IsRetIndirect = getContext().getTypeSize(EltTy) > FRLen;
88 int GARsLeft = IsRetIndirect ? NumGARs - 1 : NumGARs;
89 int FARsLeft = FRLen ? NumFARs : 0;
95 ArgInfo.type, ArgNum < NumFixedArgs, GARsLeft, FARsLeft);
103bool LoongArchABIInfo::detectFARsEligibleStructHelper(
104 QualType Ty, CharUnits CurOff, llvm::Type *&Field1Ty, CharUnits &Field1Off,
105 llvm::Type *&Field2Ty, CharUnits &Field2Off)
const {
109 if (IsInt || IsFloat) {
111 if (IsInt && Size > GRLen)
115 if (IsFloat && Size > FRLen)
119 if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
122 Field1Ty = CGT.ConvertType(Ty);
127 Field2Ty = CGT.ConvertType(Ty);
134 if (
auto CTy = Ty->
getAs<ComplexType>()) {
137 QualType EltTy = CTy->getElementType();
138 if (getContext().getTypeSize(EltTy) > FRLen)
140 Field1Ty = CGT.ConvertType(EltTy);
143 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
147 if (
const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) {
148 uint64_t ArraySize = ATy->getZExtSize();
149 QualType EltTy = ATy->getElementType();
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))
172 const RecordDecl *RD = RTy->getOriginalDecl()->getDefinitionOrSelf();
179 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
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(
186 Field1Ty, Field1Off, Field2Ty, Field2Off))
190 for (
const FieldDecl *FD : RD->
fields()) {
191 QualType QTy = FD->getType();
192 if (FD->isBitField()) {
193 unsigned BitWidth = FD->getBitWidthValue();
199 if (getContext().getTypeSize(QTy) > GRLen && BitWidth <= GRLen) {
200 QTy = getContext().getIntTypeForBitwidth(GRLen,
false);
204 if (!detectFARsEligibleStructHelper(
206 CurOff + getContext().toCharUnitsFromBits(
208 Field1Ty, Field1Off, Field2Ty, Field2Off))
211 return Field1Ty !=
nullptr;
220bool LoongArchABIInfo::detectFARsEligibleStruct(
221 QualType Ty, llvm::Type *&Field1Ty, CharUnits &Field1Off,
222 llvm::Type *&Field2Ty, CharUnits &Field2Off,
int &NeededGARs,
223 int &NeededFARs)
const {
229 Field1Off, Field2Ty, Field2Off))
234 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
236 if (Field1Ty && Field1Ty->isFloatingPointTy())
240 if (Field2Ty && Field2Ty->isFloatingPointTy())
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;
256 CoerceElts.push_back(llvm::ArrayType::get(
257 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
259 CoerceElts.push_back(Field1Ty);
260 UnpaddedCoerceElts.push_back(Field1Ty);
264 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
265 UnpaddedCoerceElts[0]);
268 CharUnits Field2Align =
270 CharUnits Field1End =
273 CharUnits Field2OffNoPadNoPack = Field1End.
alignTo(Field2Align);
276 if (Field2Off > Field2OffNoPadNoPack)
277 Padding = Field2Off - Field2OffNoPadNoPack;
278 else if (Field2Off != Field2Align && Field2Off > Field1End)
279 Padding = Field2Off - Field1End;
284 CoerceElts.push_back(llvm::ArrayType::get(
285 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
287 CoerceElts.push_back(Field2Ty);
288 UnpaddedCoerceElts.push_back(Field2Ty);
291 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked),
292 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked));
295ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty,
bool IsFixed,
297 int &FARsLeft)
const {
298 assert(GARsLeft <= NumGARs &&
"GAR tracking underflow");
306 return getNaturalAlignIndirect(
307 Ty, getDataLayout().getAllocaAddrSpace(),
321 FRLen >= Size && FARsLeft) {
328 if (IsFixed && Ty->
isComplexType() && FRLen && FARsLeft >= 2) {
329 QualType EltTy = Ty->
castAs<ComplexType>()->getElementType();
330 if (getContext().getTypeSize(EltTy) <= FRLen) {
337 llvm::Type *Field1Ty =
nullptr;
338 llvm::Type *Field2Ty =
nullptr;
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,
353 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
358 if (!IsFixed && NeededAlign == 2 * GRLen)
359 NeededGARs = 2 + (GARsLeft % 2);
360 else if (Size > GRLen && Size <= 2 * GRLen)
363 if (NeededGARs > GARsLeft)
364 NeededGARs = GARsLeft;
366 GARsLeft -= NeededGARs;
371 Ty = ED->getIntegerType();
374 if (Size < GRLen && Ty->isIntegralOrEnumerationType())
375 return extendType(Ty);
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, getDataLayout().getAllocaAddrSpace(),
393 if (Size <= 2 * GRLen) {
399 llvm::IntegerType::get(getVMContext(), GRLen));
401 if (getContext().getTypeAlign(Ty) == 2 * GRLen) {
403 llvm::IntegerType::get(getVMContext(), 2 * GRLen));
406 llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), GRLen), 2));
408 return getNaturalAlignIndirect(
409 Ty, getDataLayout().getAllocaAddrSpace(),
413ABIArgInfo LoongArchABIInfo::classifyReturnType(QualType RetTy)
const {
419 int FARsLeft = FRLen ? 2 : 0;
423RValue LoongArchABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
424 QualType Ty, AggValueSlot Slot)
const {
431 auto TInfo = getContext().getTypeInfoInChars(Ty);
435 TInfo.Width > 2 * SlotSize, TInfo,
440ABIArgInfo LoongArchABIInfo::extendType(QualType Ty)
const {
441 int TySize = getContext().getTypeSize(Ty);
449class LoongArchTargetCodeGenInfo :
public TargetCodeGenInfo {
451 LoongArchTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
unsigned GRLen,
454 std::make_unique<LoongArchABIInfo>(CGT, GRLen, FRLen)) {}
458std::unique_ptr<TargetCodeGenInfo>
461 return std::make_unique<LoongArchTargetCodeGenInfo>(CGM.
getTypes(), GRLen,
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.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
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 ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
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)
RecordArgABI
Specify how one should pass an argument of a record type.
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
CGFunctionInfo - Class to encapsulate the information about a function definition.
ABIArgInfo & getReturnInfo()
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
unsigned getNumRequiredArgs() const
This class organizes the cross-function state that is used while generating LLVM code.
CodeGenTypes & getTypes()
DefaultABIInfo - The default implementation for ABI specific details.
field_range fields() const
bool isComplexType() const
isComplexType() does not include complex integers (a GCC extension).
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
const T * castAs() const
Member-template castAs<specific type>.
bool isScalarType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
bool isStructureOrClassType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
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)