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();
144 if (getContext().getTypeSize(EltTy) > FRLen)
146 Field1Ty = CGT.ConvertType(EltTy);
149 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
153 if (
const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) {
154 uint64_t ArraySize = ATy->getZExtSize();
155 QualType EltTy = ATy->getElementType();
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))
178 const RecordDecl *RD = RTy->getDecl()->getDefinitionOrSelf();
185 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
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(
192 Field1Ty, Field1Off, Field2Ty, Field2Off))
196 for (
const FieldDecl *FD : RD->
fields()) {
197 QualType QTy = FD->getType();
198 if (FD->isBitField()) {
199 unsigned BitWidth = FD->getBitWidthValue();
205 if (getContext().getTypeSize(QTy) > GRLen && BitWidth <= GRLen) {
206 QTy = getContext().getIntTypeForBitwidth(GRLen,
false);
210 if (!detectFARsEligibleStructHelper(
212 CurOff + getContext().toCharUnitsFromBits(
214 Field1Ty, Field1Off, Field2Ty, Field2Off))
217 return Field1Ty !=
nullptr;
226bool LoongArchABIInfo::detectFARsEligibleStruct(
227 QualType Ty, llvm::Type *&Field1Ty, CharUnits &Field1Off,
228 llvm::Type *&Field2Ty, CharUnits &Field2Off,
int &NeededGARs,
229 int &NeededFARs)
const {
235 Field1Off, Field2Ty, Field2Off))
240 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
242 if (Field1Ty && Field1Ty->isFloatingPointTy())
246 if (Field2Ty && Field2Ty->isFloatingPointTy())
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;
262 CoerceElts.push_back(llvm::ArrayType::get(
263 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
265 CoerceElts.push_back(Field1Ty);
266 UnpaddedCoerceElts.push_back(Field1Ty);
270 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
271 UnpaddedCoerceElts[0]);
274 CharUnits Field2Align =
276 CharUnits Field1End =
279 CharUnits Field2OffNoPadNoPack = Field1End.
alignTo(Field2Align);
282 if (Field2Off > Field2OffNoPadNoPack)
283 Padding = Field2Off - Field2OffNoPadNoPack;
284 else if (Field2Off != Field2Align && Field2Off > Field1End)
285 Padding = Field2Off - Field1End;
290 CoerceElts.push_back(llvm::ArrayType::get(
291 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
293 CoerceElts.push_back(Field2Ty);
294 UnpaddedCoerceElts.push_back(Field2Ty);
297 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked),
298 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked));
301ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty,
bool IsFixed,
303 int &FARsLeft)
const {
304 assert(GARsLeft <= NumGARs &&
"GAR tracking underflow");
312 return getNaturalAlignIndirect(
313 Ty, getDataLayout().getAllocaAddrSpace(),
327 FRLen >= Size && FARsLeft) {
334 if (IsFixed && Ty->
isComplexType() && FRLen && FARsLeft >= 2) {
335 QualType EltTy = Ty->
castAs<ComplexType>()->getElementType();
336 if (getContext().getTypeSize(EltTy) <= FRLen) {
343 llvm::Type *Field1Ty =
nullptr;
344 llvm::Type *Field2Ty =
nullptr;
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,
359 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
364 if (!IsFixed && NeededAlign == 2 * GRLen)
365 NeededGARs = 2 + (GARsLeft % 2);
366 else if (Size > GRLen && Size <= 2 * GRLen)
369 if (NeededGARs > GARsLeft)
370 NeededGARs = GARsLeft;
372 GARsLeft -= NeededGARs;
377 Ty = ED->getIntegerType();
380 if (Size < GRLen && Ty->isIntegralOrEnumerationType())
381 return extendType(Ty);
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, getDataLayout().getAllocaAddrSpace(),
399 if (Size <= 2 * GRLen) {
405 llvm::IntegerType::get(getVMContext(), GRLen));
407 if (getContext().getTypeAlign(Ty) == 2 * GRLen) {
409 llvm::IntegerType::get(getVMContext(), 2 * GRLen));
412 llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), GRLen), 2));
414 return getNaturalAlignIndirect(
415 Ty, getDataLayout().getAllocaAddrSpace(),
419ABIArgInfo LoongArchABIInfo::classifyReturnType(QualType RetTy)
const {
425 int FARsLeft = FRLen ? 2 : 0;
429RValue LoongArchABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
430 QualType Ty, AggValueSlot Slot)
const {
437 auto TInfo = getContext().getTypeInfoInChars(Ty);
441 TInfo.Width > 2 * SlotSize, TInfo,
446ABIArgInfo LoongArchABIInfo::extendType(QualType Ty)
const {
447 int TySize = getContext().getTypeSize(Ty);
455class LoongArchTargetCodeGenInfo :
public TargetCodeGenInfo {
457 LoongArchTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
unsigned GRLen,
460 std::make_unique<LoongArchABIInfo>(CGT, GRLen, FRLen)) {}
464std::unique_ptr<TargetCodeGenInfo>
467 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 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)
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)
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)