10#include "TargetInfo.h"
28 static const int NumGARs = 8;
30 static const int NumFARs = 8;
32 llvm::Type *&Field1Ty,
34 llvm::Type *&Field2Ty,
52 bool detectFARsEligibleStruct(
QualType Ty, llvm::Type *&Field1Ty,
53 CharUnits &Field1Off, llvm::Type *&Field2Ty,
55 int &NeededArgFPRs)
const;
56 ABIArgInfo coerceAndExpandFARsEligibleStruct(llvm::Type *Field1Ty,
75 getContext().getTypeSize(RetTy) > (2 * GRLen)) {
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(
105 llvm::Type *&Field2Ty,
CharUnits &Field2Off)
const {
109 if (IsInt || IsFloat) {
111 if (IsInt && Size > GRLen)
116 if (IsFloat && (Size > FRLen || Size < 32))
120 if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
123 Field1Ty = CGT.ConvertType(Ty);
128 Field2Ty = CGT.ConvertType(Ty);
138 QualType EltTy = CTy->getElementType();
139 if (getContext().getTypeSize(EltTy) > FRLen)
141 Field1Ty = CGT.ConvertType(EltTy);
144 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
149 uint64_t ArraySize = ATy->getSize().getZExtValue();
150 QualType EltTy = ATy->getElementType();
154 if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) &&
158 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
159 for (uint64_t i = 0; i < ArraySize; ++i) {
160 if (!detectFARsEligibleStructHelper(EltTy, CurOff, Field1Ty, Field1Off,
161 Field2Ty, Field2Off))
175 (!RD->
isUnion() || !isa<CXXRecordDecl>(RD)))
182 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
186 if (!detectFARsEligibleStructHelper(
188 Field1Ty, Field1Off, Field2Ty, Field2Off))
194 if (FD->isBitField()) {
195 unsigned BitWidth = FD->getBitWidthValue(getContext());
201 if (getContext().getTypeSize(QTy) > GRLen && BitWidth <= GRLen) {
202 QTy = getContext().getIntTypeForBitwidth(GRLen,
false);
206 if (!detectFARsEligibleStructHelper(
208 CurOff + getContext().toCharUnitsFromBits(
210 Field1Ty, Field1Off, Field2Ty, Field2Off))
213 return Field1Ty !=
nullptr;
222bool LoongArchABIInfo::detectFARsEligibleStruct(
224 llvm::Type *&Field2Ty,
CharUnits &Field2Off,
int &NeededGARs,
225 int &NeededFARs)
const {
231 Field1Off, Field2Ty, Field2Off))
236 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
238 if (Field1Ty && Field1Ty->isFloatingPointTy())
242 if (Field2Ty && Field2Ty->isFloatingPointTy())
252ABIArgInfo LoongArchABIInfo::coerceAndExpandFARsEligibleStruct(
253 llvm::Type *Field1Ty,
CharUnits Field1Off, llvm::Type *Field2Ty,
258 CoerceElts.push_back(llvm::ArrayType::get(
259 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
261 CoerceElts.push_back(Field1Ty);
262 UnpaddedCoerceElts.push_back(Field1Ty);
266 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
267 UnpaddedCoerceElts[0]);
278 if (Field2Off > Field2OffNoPadNoPack)
279 Padding = Field2Off - Field2OffNoPadNoPack;
280 else if (Field2Off != Field2Align && Field2Off > Field1End)
281 Padding = Field2Off - Field1End;
286 CoerceElts.push_back(llvm::ArrayType::get(
287 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
289 CoerceElts.push_back(Field2Ty);
290 UnpaddedCoerceElts.push_back(Field2Ty);
293 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked),
294 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked));
299 int &FARsLeft)
const {
300 assert(GARsLeft <= NumGARs &&
"GAR tracking underflow");
308 return getNaturalAlignIndirect(Ty, RAA ==
322 FRLen >= Size && FARsLeft) {
328 if (Ty->
isVectorType() && (((getContext().getTypeSize(Ty) == 128) &&
330 ((getContext().getTypeSize(Ty) == 256) &&
336 if (IsFixed && Ty->
isComplexType() && FRLen && FARsLeft >= 2) {
338 if (getContext().getTypeSize(EltTy) <= FRLen) {
345 llvm::Type *Field1Ty =
nullptr;
346 llvm::Type *Field2Ty =
nullptr;
351 bool IsCandidate = detectFARsEligibleStruct(
352 Ty, Field1Ty, Field1Off, Field2Ty, Field2Off, NeededGARs, NeededFARs);
353 if (IsCandidate && NeededGARs <= GARsLeft && NeededFARs <= FARsLeft) {
354 GARsLeft -= NeededGARs;
355 FARsLeft -= NeededFARs;
356 return coerceAndExpandFARsEligibleStruct(Field1Ty, Field1Off, Field2Ty,
361 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
366 if (!IsFixed && NeededAlign == 2 * GRLen)
367 NeededGARs = 2 + (GARsLeft % 2);
368 else if (Size > GRLen && Size <= 2 * GRLen)
371 if (NeededGARs > GARsLeft)
372 NeededGARs = GARsLeft;
374 GARsLeft -= NeededGARs;
379 Ty = EnumTy->getDecl()->getIntegerType();
382 if (Size < GRLen && Ty->isIntegralOrEnumerationType())
383 return extendType(Ty);
386 if (EIT->getNumBits() < GRLen)
387 return extendType(Ty);
388 if (EIT->getNumBits() > 128 ||
389 (!getContext().getTargetInfo().hasInt128Type() &&
390 EIT->getNumBits() > 64))
391 return getNaturalAlignIndirect(Ty,
false);
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(Ty,
false);
423 int FARsLeft = FRLen ? 2 : 0;
436 auto TInfo = getContext().getTypeInfoInChars(Ty);
440 TInfo.Width > 2 * SlotSize, TInfo,
446 int TySize = getContext().getTypeSize(Ty);
459 std::make_unique<LoongArchABIInfo>(CGT, GRLen, FRLen)) {}
463std::unique_ptr<TargetCodeGenInfo>
466 return std::make_unique<LoongArchTargetCodeGenInfo>(CGM.
getTypes(), GRLen,
static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, const TargetInfo &Target)
Determine whether a translation unit built using the current language options has the given feature.
static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type)
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
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.
A fixed int type of a specified bitwidth.
Represents a base class of a C++ class.
Represents a C++ struct/union/class.
CharUnits - This is an opaque type for sizes expressed in character units.
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.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
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)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
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
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Type * ConvertTypeForMem(QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
CodeGenTypes & getTypes()
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
DefaultABIInfo - The default implementation for ABI specific details.
ABIArgInfo classifyArgumentType(QualType RetTy) const
ABIArgInfo classifyReturnType(QualType RetTy) const
void computeInfo(CGFunctionInfo &FI) const override
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty) const override
EmitVAArg - Emit the target dependent code to load a value of.
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
Complex values, per C99 6.2.5p11.
Represents the canonical version of C arrays with a specified constant size.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Represents a member of a struct/union/class.
A (possibly-)qualified type.
Represents a struct/union/class.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() 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.
bool isStructureOrClassType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
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)
Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, 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)