464 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "ABIInfoImpl.h"10#include "TargetInfo.h"11 12using namespace clang;13using namespace clang::CodeGen;14 15// LoongArch ABI Implementation. Documented at16// https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html17//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 namespace62 63void LoongArchABIInfo::computeInfo(CGFunctionInfo &FI) const {64 QualType RetTy = FI.getReturnType();65 if (!getCXXABI().classifyReturnType(FI))66 FI.getReturnInfo() = classifyReturnType(RetTy);67 68 // IsRetIndirect is true if classifyArgumentType indicated the value should69 // be passed indirect, or if the type size is a scalar greater than 2*GRLen70 // and not a complex type with elements <= FRLen. e.g. fp128 is passed direct71 // in LLVM IR, relying on the backend lowering code to rewrite the argument72 // 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 the86 // LoongArch ABI. As GAR usage is different for variadic arguments, we must87 // 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 (and101// GARs). If this function returns true, the caller is responsible for checking102// 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 half114 // 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 pairs118 // 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 be151 // passed via FARs in C++.152 if (const auto *RTy = EltTy->getAsCanonical<RecordType>()) {153 if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) &&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-trivial169 // copy constructor are not eligible for the FP calling convention.170 if (getRecordArgABI(Ty, CGT.getCXXABI()))171 return false;172 const RecordDecl *RD = RTy->getDecl()->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 the198 // 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., when218// flattened it contains a single fp value, fp+fp, or int+fp of appropriate219// 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 by248// Field1Ty, Field1Off, Field2Ty, Field2Off. This method will create an249// 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) {263 return ABIArgInfo::getCoerceAndExpand(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 290 return ABIArgInfo::getCoerceAndExpand(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");299 Ty = useFirstFieldIfTransparentUnion(Ty);300 301 // Structures with either a non-trivial destructor or a non-trivial302 // 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 or314 // `struct { int a[0]; }` in C++. In C++, `struct { }` is empty but it's size315 // 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 than327 // 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 argument355 // 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 is395 // required, and a 2-element GRLen array if only GRLen alignment is396 // required.397 if (Size <= GRLen) {398 return ABIArgInfo::getDirect(399 llvm::IntegerType::get(getVMContext(), GRLen));400 }401 if (getContext().getTypeAlign(Ty) == 2 * GRLen) {402 return ABIArgInfo::getDirect(403 llvm::IntegerType::get(getVMContext(), 2 * GRLen));404 }405 return ABIArgInfo::getDirect(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 to417 // 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} // namespace457 458std::unique_ptr<TargetCodeGenInfo>459CodeGen::createLoongArchTargetCodeGenInfo(CodeGenModule &CGM, unsigned GRLen,460 unsigned FLen) {461 return std::make_unique<LoongArchTargetCodeGenInfo>(CGM.getTypes(), GRLen,462 FLen);463}464