1*06c3fb27SDimitry Andric //===- LoongArch.cpp ------------------------------------------------------===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric 9*06c3fb27SDimitry Andric #include "ABIInfoImpl.h" 10*06c3fb27SDimitry Andric #include "TargetInfo.h" 11*06c3fb27SDimitry Andric 12*06c3fb27SDimitry Andric using namespace clang; 13*06c3fb27SDimitry Andric using namespace clang::CodeGen; 14*06c3fb27SDimitry Andric 15*06c3fb27SDimitry Andric // LoongArch ABI Implementation. Documented at 16*06c3fb27SDimitry Andric // https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html 17*06c3fb27SDimitry Andric // 18*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 19*06c3fb27SDimitry Andric 20*06c3fb27SDimitry Andric namespace { 21*06c3fb27SDimitry Andric class LoongArchABIInfo : public DefaultABIInfo { 22*06c3fb27SDimitry Andric private: 23*06c3fb27SDimitry Andric // Size of the integer ('r') registers in bits. 24*06c3fb27SDimitry Andric unsigned GRLen; 25*06c3fb27SDimitry Andric // Size of the floating point ('f') registers in bits. 26*06c3fb27SDimitry Andric unsigned FRLen; 27*06c3fb27SDimitry Andric // Number of general-purpose argument registers. 28*06c3fb27SDimitry Andric static const int NumGARs = 8; 29*06c3fb27SDimitry Andric // Number of floating-point argument registers. 30*06c3fb27SDimitry Andric static const int NumFARs = 8; 31*06c3fb27SDimitry Andric bool detectFARsEligibleStructHelper(QualType Ty, CharUnits CurOff, 32*06c3fb27SDimitry Andric llvm::Type *&Field1Ty, 33*06c3fb27SDimitry Andric CharUnits &Field1Off, 34*06c3fb27SDimitry Andric llvm::Type *&Field2Ty, 35*06c3fb27SDimitry Andric CharUnits &Field2Off) const; 36*06c3fb27SDimitry Andric 37*06c3fb27SDimitry Andric public: 38*06c3fb27SDimitry Andric LoongArchABIInfo(CodeGen::CodeGenTypes &CGT, unsigned GRLen, unsigned FRLen) 39*06c3fb27SDimitry Andric : DefaultABIInfo(CGT), GRLen(GRLen), FRLen(FRLen) {} 40*06c3fb27SDimitry Andric 41*06c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 42*06c3fb27SDimitry Andric 43*06c3fb27SDimitry Andric ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, int &GARsLeft, 44*06c3fb27SDimitry Andric int &FARsLeft) const; 45*06c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy) const; 46*06c3fb27SDimitry Andric 47*06c3fb27SDimitry Andric Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 48*06c3fb27SDimitry Andric QualType Ty) const override; 49*06c3fb27SDimitry Andric 50*06c3fb27SDimitry Andric ABIArgInfo extendType(QualType Ty) const; 51*06c3fb27SDimitry Andric 52*06c3fb27SDimitry Andric bool detectFARsEligibleStruct(QualType Ty, llvm::Type *&Field1Ty, 53*06c3fb27SDimitry Andric CharUnits &Field1Off, llvm::Type *&Field2Ty, 54*06c3fb27SDimitry Andric CharUnits &Field2Off, int &NeededArgGPRs, 55*06c3fb27SDimitry Andric int &NeededArgFPRs) const; 56*06c3fb27SDimitry Andric ABIArgInfo coerceAndExpandFARsEligibleStruct(llvm::Type *Field1Ty, 57*06c3fb27SDimitry Andric CharUnits Field1Off, 58*06c3fb27SDimitry Andric llvm::Type *Field2Ty, 59*06c3fb27SDimitry Andric CharUnits Field2Off) const; 60*06c3fb27SDimitry Andric }; 61*06c3fb27SDimitry Andric } // end anonymous namespace 62*06c3fb27SDimitry Andric 63*06c3fb27SDimitry Andric void LoongArchABIInfo::computeInfo(CGFunctionInfo &FI) const { 64*06c3fb27SDimitry Andric QualType RetTy = FI.getReturnType(); 65*06c3fb27SDimitry Andric if (!getCXXABI().classifyReturnType(FI)) 66*06c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(RetTy); 67*06c3fb27SDimitry Andric 68*06c3fb27SDimitry Andric // IsRetIndirect is true if classifyArgumentType indicated the value should 69*06c3fb27SDimitry Andric // be passed indirect, or if the type size is a scalar greater than 2*GRLen 70*06c3fb27SDimitry Andric // and not a complex type with elements <= FRLen. e.g. fp128 is passed direct 71*06c3fb27SDimitry Andric // in LLVM IR, relying on the backend lowering code to rewrite the argument 72*06c3fb27SDimitry Andric // list and pass indirectly on LA32. 73*06c3fb27SDimitry Andric bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect; 74*06c3fb27SDimitry Andric if (!IsRetIndirect && RetTy->isScalarType() && 75*06c3fb27SDimitry Andric getContext().getTypeSize(RetTy) > (2 * GRLen)) { 76*06c3fb27SDimitry Andric if (RetTy->isComplexType() && FRLen) { 77*06c3fb27SDimitry Andric QualType EltTy = RetTy->castAs<ComplexType>()->getElementType(); 78*06c3fb27SDimitry Andric IsRetIndirect = getContext().getTypeSize(EltTy) > FRLen; 79*06c3fb27SDimitry Andric } else { 80*06c3fb27SDimitry Andric // This is a normal scalar > 2*GRLen, such as fp128 on LA32. 81*06c3fb27SDimitry Andric IsRetIndirect = true; 82*06c3fb27SDimitry Andric } 83*06c3fb27SDimitry Andric } 84*06c3fb27SDimitry Andric 85*06c3fb27SDimitry Andric // We must track the number of GARs and FARs used in order to conform to the 86*06c3fb27SDimitry Andric // LoongArch ABI. As GAR usage is different for variadic arguments, we must 87*06c3fb27SDimitry Andric // also track whether we are examining a vararg or not. 88*06c3fb27SDimitry Andric int GARsLeft = IsRetIndirect ? NumGARs - 1 : NumGARs; 89*06c3fb27SDimitry Andric int FARsLeft = FRLen ? NumFARs : 0; 90*06c3fb27SDimitry Andric int NumFixedArgs = FI.getNumRequiredArgs(); 91*06c3fb27SDimitry Andric 92*06c3fb27SDimitry Andric int ArgNum = 0; 93*06c3fb27SDimitry Andric for (auto &ArgInfo : FI.arguments()) { 94*06c3fb27SDimitry Andric ArgInfo.info = classifyArgumentType( 95*06c3fb27SDimitry Andric ArgInfo.type, /*IsFixed=*/ArgNum < NumFixedArgs, GARsLeft, FARsLeft); 96*06c3fb27SDimitry Andric ArgNum++; 97*06c3fb27SDimitry Andric } 98*06c3fb27SDimitry Andric } 99*06c3fb27SDimitry Andric 100*06c3fb27SDimitry Andric // Returns true if the struct is a potential candidate to be passed in FARs (and 101*06c3fb27SDimitry Andric // GARs). If this function returns true, the caller is responsible for checking 102*06c3fb27SDimitry Andric // that if there is only a single field then that field is a float. 103*06c3fb27SDimitry Andric bool LoongArchABIInfo::detectFARsEligibleStructHelper( 104*06c3fb27SDimitry Andric QualType Ty, CharUnits CurOff, llvm::Type *&Field1Ty, CharUnits &Field1Off, 105*06c3fb27SDimitry Andric llvm::Type *&Field2Ty, CharUnits &Field2Off) const { 106*06c3fb27SDimitry Andric bool IsInt = Ty->isIntegralOrEnumerationType(); 107*06c3fb27SDimitry Andric bool IsFloat = Ty->isRealFloatingType(); 108*06c3fb27SDimitry Andric 109*06c3fb27SDimitry Andric if (IsInt || IsFloat) { 110*06c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty); 111*06c3fb27SDimitry Andric if (IsInt && Size > GRLen) 112*06c3fb27SDimitry Andric return false; 113*06c3fb27SDimitry Andric // Can't be eligible if larger than the FP registers. Half precision isn't 114*06c3fb27SDimitry Andric // currently supported on LoongArch and the ABI hasn't been confirmed, so 115*06c3fb27SDimitry Andric // default to the integer ABI in that case. 116*06c3fb27SDimitry Andric if (IsFloat && (Size > FRLen || Size < 32)) 117*06c3fb27SDimitry Andric return false; 118*06c3fb27SDimitry Andric // Can't be eligible if an integer type was already found (int+int pairs 119*06c3fb27SDimitry Andric // are not eligible). 120*06c3fb27SDimitry Andric if (IsInt && Field1Ty && Field1Ty->isIntegerTy()) 121*06c3fb27SDimitry Andric return false; 122*06c3fb27SDimitry Andric if (!Field1Ty) { 123*06c3fb27SDimitry Andric Field1Ty = CGT.ConvertType(Ty); 124*06c3fb27SDimitry Andric Field1Off = CurOff; 125*06c3fb27SDimitry Andric return true; 126*06c3fb27SDimitry Andric } 127*06c3fb27SDimitry Andric if (!Field2Ty) { 128*06c3fb27SDimitry Andric Field2Ty = CGT.ConvertType(Ty); 129*06c3fb27SDimitry Andric Field2Off = CurOff; 130*06c3fb27SDimitry Andric return true; 131*06c3fb27SDimitry Andric } 132*06c3fb27SDimitry Andric return false; 133*06c3fb27SDimitry Andric } 134*06c3fb27SDimitry Andric 135*06c3fb27SDimitry Andric if (auto CTy = Ty->getAs<ComplexType>()) { 136*06c3fb27SDimitry Andric if (Field1Ty) 137*06c3fb27SDimitry Andric return false; 138*06c3fb27SDimitry Andric QualType EltTy = CTy->getElementType(); 139*06c3fb27SDimitry Andric if (getContext().getTypeSize(EltTy) > FRLen) 140*06c3fb27SDimitry Andric return false; 141*06c3fb27SDimitry Andric Field1Ty = CGT.ConvertType(EltTy); 142*06c3fb27SDimitry Andric Field1Off = CurOff; 143*06c3fb27SDimitry Andric Field2Ty = Field1Ty; 144*06c3fb27SDimitry Andric Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy); 145*06c3fb27SDimitry Andric return true; 146*06c3fb27SDimitry Andric } 147*06c3fb27SDimitry Andric 148*06c3fb27SDimitry Andric if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) { 149*06c3fb27SDimitry Andric uint64_t ArraySize = ATy->getSize().getZExtValue(); 150*06c3fb27SDimitry Andric QualType EltTy = ATy->getElementType(); 151*06c3fb27SDimitry Andric CharUnits EltSize = getContext().getTypeSizeInChars(EltTy); 152*06c3fb27SDimitry Andric for (uint64_t i = 0; i < ArraySize; ++i) { 153*06c3fb27SDimitry Andric if (!detectFARsEligibleStructHelper(EltTy, CurOff, Field1Ty, Field1Off, 154*06c3fb27SDimitry Andric Field2Ty, Field2Off)) 155*06c3fb27SDimitry Andric return false; 156*06c3fb27SDimitry Andric CurOff += EltSize; 157*06c3fb27SDimitry Andric } 158*06c3fb27SDimitry Andric return true; 159*06c3fb27SDimitry Andric } 160*06c3fb27SDimitry Andric 161*06c3fb27SDimitry Andric if (const auto *RTy = Ty->getAs<RecordType>()) { 162*06c3fb27SDimitry Andric // Structures with either a non-trivial destructor or a non-trivial 163*06c3fb27SDimitry Andric // copy constructor are not eligible for the FP calling convention. 164*06c3fb27SDimitry Andric if (getRecordArgABI(Ty, CGT.getCXXABI())) 165*06c3fb27SDimitry Andric return false; 166*06c3fb27SDimitry Andric if (isEmptyRecord(getContext(), Ty, true)) 167*06c3fb27SDimitry Andric return true; 168*06c3fb27SDimitry Andric const RecordDecl *RD = RTy->getDecl(); 169*06c3fb27SDimitry Andric // Unions aren't eligible unless they're empty (which is caught above). 170*06c3fb27SDimitry Andric if (RD->isUnion()) 171*06c3fb27SDimitry Andric return false; 172*06c3fb27SDimitry Andric const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); 173*06c3fb27SDimitry Andric // If this is a C++ record, check the bases first. 174*06c3fb27SDimitry Andric if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { 175*06c3fb27SDimitry Andric for (const CXXBaseSpecifier &B : CXXRD->bases()) { 176*06c3fb27SDimitry Andric const auto *BDecl = 177*06c3fb27SDimitry Andric cast<CXXRecordDecl>(B.getType()->castAs<RecordType>()->getDecl()); 178*06c3fb27SDimitry Andric if (!detectFARsEligibleStructHelper( 179*06c3fb27SDimitry Andric B.getType(), CurOff + Layout.getBaseClassOffset(BDecl), 180*06c3fb27SDimitry Andric Field1Ty, Field1Off, Field2Ty, Field2Off)) 181*06c3fb27SDimitry Andric return false; 182*06c3fb27SDimitry Andric } 183*06c3fb27SDimitry Andric } 184*06c3fb27SDimitry Andric for (const FieldDecl *FD : RD->fields()) { 185*06c3fb27SDimitry Andric QualType QTy = FD->getType(); 186*06c3fb27SDimitry Andric if (FD->isBitField()) { 187*06c3fb27SDimitry Andric unsigned BitWidth = FD->getBitWidthValue(getContext()); 188*06c3fb27SDimitry Andric // Zero-width bitfields are ignored. 189*06c3fb27SDimitry Andric if (BitWidth == 0) 190*06c3fb27SDimitry Andric continue; 191*06c3fb27SDimitry Andric // Allow a bitfield with a type greater than GRLen as long as the 192*06c3fb27SDimitry Andric // bitwidth is GRLen or less. 193*06c3fb27SDimitry Andric if (getContext().getTypeSize(QTy) > GRLen && BitWidth <= GRLen) { 194*06c3fb27SDimitry Andric QTy = getContext().getIntTypeForBitwidth(GRLen, false); 195*06c3fb27SDimitry Andric } 196*06c3fb27SDimitry Andric } 197*06c3fb27SDimitry Andric 198*06c3fb27SDimitry Andric if (!detectFARsEligibleStructHelper( 199*06c3fb27SDimitry Andric QTy, 200*06c3fb27SDimitry Andric CurOff + getContext().toCharUnitsFromBits( 201*06c3fb27SDimitry Andric Layout.getFieldOffset(FD->getFieldIndex())), 202*06c3fb27SDimitry Andric Field1Ty, Field1Off, Field2Ty, Field2Off)) 203*06c3fb27SDimitry Andric return false; 204*06c3fb27SDimitry Andric } 205*06c3fb27SDimitry Andric return Field1Ty != nullptr; 206*06c3fb27SDimitry Andric } 207*06c3fb27SDimitry Andric 208*06c3fb27SDimitry Andric return false; 209*06c3fb27SDimitry Andric } 210*06c3fb27SDimitry Andric 211*06c3fb27SDimitry Andric // Determine if a struct is eligible to be passed in FARs (and GARs) (i.e., when 212*06c3fb27SDimitry Andric // flattened it contains a single fp value, fp+fp, or int+fp of appropriate 213*06c3fb27SDimitry Andric // size). If so, NeededFARs and NeededGARs are incremented appropriately. 214*06c3fb27SDimitry Andric bool LoongArchABIInfo::detectFARsEligibleStruct( 215*06c3fb27SDimitry Andric QualType Ty, llvm::Type *&Field1Ty, CharUnits &Field1Off, 216*06c3fb27SDimitry Andric llvm::Type *&Field2Ty, CharUnits &Field2Off, int &NeededGARs, 217*06c3fb27SDimitry Andric int &NeededFARs) const { 218*06c3fb27SDimitry Andric Field1Ty = nullptr; 219*06c3fb27SDimitry Andric Field2Ty = nullptr; 220*06c3fb27SDimitry Andric NeededGARs = 0; 221*06c3fb27SDimitry Andric NeededFARs = 0; 222*06c3fb27SDimitry Andric if (!detectFARsEligibleStructHelper(Ty, CharUnits::Zero(), Field1Ty, 223*06c3fb27SDimitry Andric Field1Off, Field2Ty, Field2Off)) 224*06c3fb27SDimitry Andric return false; 225*06c3fb27SDimitry Andric // Not really a candidate if we have a single int but no float. 226*06c3fb27SDimitry Andric if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy()) 227*06c3fb27SDimitry Andric return false; 228*06c3fb27SDimitry Andric if (Field1Ty && Field1Ty->isFloatingPointTy()) 229*06c3fb27SDimitry Andric NeededFARs++; 230*06c3fb27SDimitry Andric else if (Field1Ty) 231*06c3fb27SDimitry Andric NeededGARs++; 232*06c3fb27SDimitry Andric if (Field2Ty && Field2Ty->isFloatingPointTy()) 233*06c3fb27SDimitry Andric NeededFARs++; 234*06c3fb27SDimitry Andric else if (Field2Ty) 235*06c3fb27SDimitry Andric NeededGARs++; 236*06c3fb27SDimitry Andric return true; 237*06c3fb27SDimitry Andric } 238*06c3fb27SDimitry Andric 239*06c3fb27SDimitry Andric // Call getCoerceAndExpand for the two-element flattened struct described by 240*06c3fb27SDimitry Andric // Field1Ty, Field1Off, Field2Ty, Field2Off. This method will create an 241*06c3fb27SDimitry Andric // appropriate coerceToType and unpaddedCoerceToType. 242*06c3fb27SDimitry Andric ABIArgInfo LoongArchABIInfo::coerceAndExpandFARsEligibleStruct( 243*06c3fb27SDimitry Andric llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty, 244*06c3fb27SDimitry Andric CharUnits Field2Off) const { 245*06c3fb27SDimitry Andric SmallVector<llvm::Type *, 3> CoerceElts; 246*06c3fb27SDimitry Andric SmallVector<llvm::Type *, 2> UnpaddedCoerceElts; 247*06c3fb27SDimitry Andric if (!Field1Off.isZero()) 248*06c3fb27SDimitry Andric CoerceElts.push_back(llvm::ArrayType::get( 249*06c3fb27SDimitry Andric llvm::Type::getInt8Ty(getVMContext()), Field1Off.getQuantity())); 250*06c3fb27SDimitry Andric 251*06c3fb27SDimitry Andric CoerceElts.push_back(Field1Ty); 252*06c3fb27SDimitry Andric UnpaddedCoerceElts.push_back(Field1Ty); 253*06c3fb27SDimitry Andric 254*06c3fb27SDimitry Andric if (!Field2Ty) { 255*06c3fb27SDimitry Andric return ABIArgInfo::getCoerceAndExpand( 256*06c3fb27SDimitry Andric llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.isZero()), 257*06c3fb27SDimitry Andric UnpaddedCoerceElts[0]); 258*06c3fb27SDimitry Andric } 259*06c3fb27SDimitry Andric 260*06c3fb27SDimitry Andric CharUnits Field2Align = 261*06c3fb27SDimitry Andric CharUnits::fromQuantity(getDataLayout().getABITypeAlign(Field2Ty)); 262*06c3fb27SDimitry Andric CharUnits Field1End = 263*06c3fb27SDimitry Andric Field1Off + 264*06c3fb27SDimitry Andric CharUnits::fromQuantity(getDataLayout().getTypeStoreSize(Field1Ty)); 265*06c3fb27SDimitry Andric CharUnits Field2OffNoPadNoPack = Field1End.alignTo(Field2Align); 266*06c3fb27SDimitry Andric 267*06c3fb27SDimitry Andric CharUnits Padding = CharUnits::Zero(); 268*06c3fb27SDimitry Andric if (Field2Off > Field2OffNoPadNoPack) 269*06c3fb27SDimitry Andric Padding = Field2Off - Field2OffNoPadNoPack; 270*06c3fb27SDimitry Andric else if (Field2Off != Field2Align && Field2Off > Field1End) 271*06c3fb27SDimitry Andric Padding = Field2Off - Field1End; 272*06c3fb27SDimitry Andric 273*06c3fb27SDimitry Andric bool IsPacked = !Field2Off.isMultipleOf(Field2Align); 274*06c3fb27SDimitry Andric 275*06c3fb27SDimitry Andric if (!Padding.isZero()) 276*06c3fb27SDimitry Andric CoerceElts.push_back(llvm::ArrayType::get( 277*06c3fb27SDimitry Andric llvm::Type::getInt8Ty(getVMContext()), Padding.getQuantity())); 278*06c3fb27SDimitry Andric 279*06c3fb27SDimitry Andric CoerceElts.push_back(Field2Ty); 280*06c3fb27SDimitry Andric UnpaddedCoerceElts.push_back(Field2Ty); 281*06c3fb27SDimitry Andric 282*06c3fb27SDimitry Andric return ABIArgInfo::getCoerceAndExpand( 283*06c3fb27SDimitry Andric llvm::StructType::get(getVMContext(), CoerceElts, IsPacked), 284*06c3fb27SDimitry Andric llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked)); 285*06c3fb27SDimitry Andric } 286*06c3fb27SDimitry Andric 287*06c3fb27SDimitry Andric ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, 288*06c3fb27SDimitry Andric int &GARsLeft, 289*06c3fb27SDimitry Andric int &FARsLeft) const { 290*06c3fb27SDimitry Andric assert(GARsLeft <= NumGARs && "GAR tracking underflow"); 291*06c3fb27SDimitry Andric Ty = useFirstFieldIfTransparentUnion(Ty); 292*06c3fb27SDimitry Andric 293*06c3fb27SDimitry Andric // Structures with either a non-trivial destructor or a non-trivial 294*06c3fb27SDimitry Andric // copy constructor are always passed indirectly. 295*06c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { 296*06c3fb27SDimitry Andric if (GARsLeft) 297*06c3fb27SDimitry Andric GARsLeft -= 1; 298*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == 299*06c3fb27SDimitry Andric CGCXXABI::RAA_DirectInMemory); 300*06c3fb27SDimitry Andric } 301*06c3fb27SDimitry Andric 302*06c3fb27SDimitry Andric // Ignore empty structs/unions. 303*06c3fb27SDimitry Andric if (isEmptyRecord(getContext(), Ty, true)) 304*06c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 305*06c3fb27SDimitry Andric 306*06c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty); 307*06c3fb27SDimitry Andric 308*06c3fb27SDimitry Andric // Pass floating point values via FARs if possible. 309*06c3fb27SDimitry Andric if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() && 310*06c3fb27SDimitry Andric FRLen >= Size && FARsLeft) { 311*06c3fb27SDimitry Andric FARsLeft--; 312*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 313*06c3fb27SDimitry Andric } 314*06c3fb27SDimitry Andric 315*06c3fb27SDimitry Andric // Complex types for the *f or *d ABI must be passed directly rather than 316*06c3fb27SDimitry Andric // using CoerceAndExpand. 317*06c3fb27SDimitry Andric if (IsFixed && Ty->isComplexType() && FRLen && FARsLeft >= 2) { 318*06c3fb27SDimitry Andric QualType EltTy = Ty->castAs<ComplexType>()->getElementType(); 319*06c3fb27SDimitry Andric if (getContext().getTypeSize(EltTy) <= FRLen) { 320*06c3fb27SDimitry Andric FARsLeft -= 2; 321*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 322*06c3fb27SDimitry Andric } 323*06c3fb27SDimitry Andric } 324*06c3fb27SDimitry Andric 325*06c3fb27SDimitry Andric if (IsFixed && FRLen && Ty->isStructureOrClassType()) { 326*06c3fb27SDimitry Andric llvm::Type *Field1Ty = nullptr; 327*06c3fb27SDimitry Andric llvm::Type *Field2Ty = nullptr; 328*06c3fb27SDimitry Andric CharUnits Field1Off = CharUnits::Zero(); 329*06c3fb27SDimitry Andric CharUnits Field2Off = CharUnits::Zero(); 330*06c3fb27SDimitry Andric int NeededGARs = 0; 331*06c3fb27SDimitry Andric int NeededFARs = 0; 332*06c3fb27SDimitry Andric bool IsCandidate = detectFARsEligibleStruct( 333*06c3fb27SDimitry Andric Ty, Field1Ty, Field1Off, Field2Ty, Field2Off, NeededGARs, NeededFARs); 334*06c3fb27SDimitry Andric if (IsCandidate && NeededGARs <= GARsLeft && NeededFARs <= FARsLeft) { 335*06c3fb27SDimitry Andric GARsLeft -= NeededGARs; 336*06c3fb27SDimitry Andric FARsLeft -= NeededFARs; 337*06c3fb27SDimitry Andric return coerceAndExpandFARsEligibleStruct(Field1Ty, Field1Off, Field2Ty, 338*06c3fb27SDimitry Andric Field2Off); 339*06c3fb27SDimitry Andric } 340*06c3fb27SDimitry Andric } 341*06c3fb27SDimitry Andric 342*06c3fb27SDimitry Andric uint64_t NeededAlign = getContext().getTypeAlign(Ty); 343*06c3fb27SDimitry Andric // Determine the number of GARs needed to pass the current argument 344*06c3fb27SDimitry Andric // according to the ABI. 2*GRLen-aligned varargs are passed in "aligned" 345*06c3fb27SDimitry Andric // register pairs, so may consume 3 registers. 346*06c3fb27SDimitry Andric int NeededGARs = 1; 347*06c3fb27SDimitry Andric if (!IsFixed && NeededAlign == 2 * GRLen) 348*06c3fb27SDimitry Andric NeededGARs = 2 + (GARsLeft % 2); 349*06c3fb27SDimitry Andric else if (Size > GRLen && Size <= 2 * GRLen) 350*06c3fb27SDimitry Andric NeededGARs = 2; 351*06c3fb27SDimitry Andric 352*06c3fb27SDimitry Andric if (NeededGARs > GARsLeft) 353*06c3fb27SDimitry Andric NeededGARs = GARsLeft; 354*06c3fb27SDimitry Andric 355*06c3fb27SDimitry Andric GARsLeft -= NeededGARs; 356*06c3fb27SDimitry Andric 357*06c3fb27SDimitry Andric if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) { 358*06c3fb27SDimitry Andric // Treat an enum type as its underlying type. 359*06c3fb27SDimitry Andric if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 360*06c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType(); 361*06c3fb27SDimitry Andric 362*06c3fb27SDimitry Andric // All integral types are promoted to GRLen width. 363*06c3fb27SDimitry Andric if (Size < GRLen && Ty->isIntegralOrEnumerationType()) 364*06c3fb27SDimitry Andric return extendType(Ty); 365*06c3fb27SDimitry Andric 366*06c3fb27SDimitry Andric if (const auto *EIT = Ty->getAs<BitIntType>()) { 367*06c3fb27SDimitry Andric if (EIT->getNumBits() < GRLen) 368*06c3fb27SDimitry Andric return extendType(Ty); 369*06c3fb27SDimitry Andric if (EIT->getNumBits() > 128 || 370*06c3fb27SDimitry Andric (!getContext().getTargetInfo().hasInt128Type() && 371*06c3fb27SDimitry Andric EIT->getNumBits() > 64)) 372*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 373*06c3fb27SDimitry Andric } 374*06c3fb27SDimitry Andric 375*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 376*06c3fb27SDimitry Andric } 377*06c3fb27SDimitry Andric 378*06c3fb27SDimitry Andric // Aggregates which are <= 2*GRLen will be passed in registers if possible, 379*06c3fb27SDimitry Andric // so coerce to integers. 380*06c3fb27SDimitry Andric if (Size <= 2 * GRLen) { 381*06c3fb27SDimitry Andric // Use a single GRLen int if possible, 2*GRLen if 2*GRLen alignment is 382*06c3fb27SDimitry Andric // required, and a 2-element GRLen array if only GRLen alignment is 383*06c3fb27SDimitry Andric // required. 384*06c3fb27SDimitry Andric if (Size <= GRLen) { 385*06c3fb27SDimitry Andric return ABIArgInfo::getDirect( 386*06c3fb27SDimitry Andric llvm::IntegerType::get(getVMContext(), GRLen)); 387*06c3fb27SDimitry Andric } 388*06c3fb27SDimitry Andric if (getContext().getTypeAlign(Ty) == 2 * GRLen) { 389*06c3fb27SDimitry Andric return ABIArgInfo::getDirect( 390*06c3fb27SDimitry Andric llvm::IntegerType::get(getVMContext(), 2 * GRLen)); 391*06c3fb27SDimitry Andric } 392*06c3fb27SDimitry Andric return ABIArgInfo::getDirect( 393*06c3fb27SDimitry Andric llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), GRLen), 2)); 394*06c3fb27SDimitry Andric } 395*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 396*06c3fb27SDimitry Andric } 397*06c3fb27SDimitry Andric 398*06c3fb27SDimitry Andric ABIArgInfo LoongArchABIInfo::classifyReturnType(QualType RetTy) const { 399*06c3fb27SDimitry Andric if (RetTy->isVoidType()) 400*06c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 401*06c3fb27SDimitry Andric // The rules for return and argument types are the same, so defer to 402*06c3fb27SDimitry Andric // classifyArgumentType. 403*06c3fb27SDimitry Andric int GARsLeft = 2; 404*06c3fb27SDimitry Andric int FARsLeft = FRLen ? 2 : 0; 405*06c3fb27SDimitry Andric return classifyArgumentType(RetTy, /*IsFixed=*/true, GARsLeft, FARsLeft); 406*06c3fb27SDimitry Andric } 407*06c3fb27SDimitry Andric 408*06c3fb27SDimitry Andric Address LoongArchABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 409*06c3fb27SDimitry Andric QualType Ty) const { 410*06c3fb27SDimitry Andric CharUnits SlotSize = CharUnits::fromQuantity(GRLen / 8); 411*06c3fb27SDimitry Andric 412*06c3fb27SDimitry Andric // Empty records are ignored for parameter passing purposes. 413*06c3fb27SDimitry Andric if (isEmptyRecord(getContext(), Ty, true)) 414*06c3fb27SDimitry Andric return Address(CGF.Builder.CreateLoad(VAListAddr), 415*06c3fb27SDimitry Andric CGF.ConvertTypeForMem(Ty), SlotSize); 416*06c3fb27SDimitry Andric 417*06c3fb27SDimitry Andric auto TInfo = getContext().getTypeInfoInChars(Ty); 418*06c3fb27SDimitry Andric 419*06c3fb27SDimitry Andric // Arguments bigger than 2*GRLen bytes are passed indirectly. 420*06c3fb27SDimitry Andric return emitVoidPtrVAArg(CGF, VAListAddr, Ty, 421*06c3fb27SDimitry Andric /*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo, 422*06c3fb27SDimitry Andric SlotSize, 423*06c3fb27SDimitry Andric /*AllowHigherAlign=*/true); 424*06c3fb27SDimitry Andric } 425*06c3fb27SDimitry Andric 426*06c3fb27SDimitry Andric ABIArgInfo LoongArchABIInfo::extendType(QualType Ty) const { 427*06c3fb27SDimitry Andric int TySize = getContext().getTypeSize(Ty); 428*06c3fb27SDimitry Andric // LA64 ABI requires unsigned 32 bit integers to be sign extended. 429*06c3fb27SDimitry Andric if (GRLen == 64 && Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32) 430*06c3fb27SDimitry Andric return ABIArgInfo::getSignExtend(Ty); 431*06c3fb27SDimitry Andric return ABIArgInfo::getExtend(Ty); 432*06c3fb27SDimitry Andric } 433*06c3fb27SDimitry Andric 434*06c3fb27SDimitry Andric namespace { 435*06c3fb27SDimitry Andric class LoongArchTargetCodeGenInfo : public TargetCodeGenInfo { 436*06c3fb27SDimitry Andric public: 437*06c3fb27SDimitry Andric LoongArchTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned GRLen, 438*06c3fb27SDimitry Andric unsigned FRLen) 439*06c3fb27SDimitry Andric : TargetCodeGenInfo( 440*06c3fb27SDimitry Andric std::make_unique<LoongArchABIInfo>(CGT, GRLen, FRLen)) {} 441*06c3fb27SDimitry Andric }; 442*06c3fb27SDimitry Andric } // namespace 443*06c3fb27SDimitry Andric 444*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 445*06c3fb27SDimitry Andric CodeGen::createLoongArchTargetCodeGenInfo(CodeGenModule &CGM, unsigned GRLen, 446*06c3fb27SDimitry Andric unsigned FLen) { 447*06c3fb27SDimitry Andric return std::make_unique<LoongArchTargetCodeGenInfo>(CGM.getTypes(), GRLen, 448*06c3fb27SDimitry Andric FLen); 449*06c3fb27SDimitry Andric } 450