xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===- ABIInfo.cpp --------------------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #include "ABIInfo.h"
1006c3fb27SDimitry Andric #include "ABIInfoImpl.h"
1106c3fb27SDimitry Andric 
1206c3fb27SDimitry Andric using namespace clang;
1306c3fb27SDimitry Andric using namespace clang::CodeGen;
1406c3fb27SDimitry Andric 
1506c3fb27SDimitry Andric // Pin the vtable to this file.
1606c3fb27SDimitry Andric ABIInfo::~ABIInfo() = default;
1706c3fb27SDimitry Andric 
1806c3fb27SDimitry Andric CGCXXABI &ABIInfo::getCXXABI() const { return CGT.getCXXABI(); }
1906c3fb27SDimitry Andric 
2006c3fb27SDimitry Andric ASTContext &ABIInfo::getContext() const { return CGT.getContext(); }
2106c3fb27SDimitry Andric 
2206c3fb27SDimitry Andric llvm::LLVMContext &ABIInfo::getVMContext() const {
2306c3fb27SDimitry Andric   return CGT.getLLVMContext();
2406c3fb27SDimitry Andric }
2506c3fb27SDimitry Andric 
2606c3fb27SDimitry Andric const llvm::DataLayout &ABIInfo::getDataLayout() const {
2706c3fb27SDimitry Andric   return CGT.getDataLayout();
2806c3fb27SDimitry Andric }
2906c3fb27SDimitry Andric 
3006c3fb27SDimitry Andric const TargetInfo &ABIInfo::getTarget() const { return CGT.getTarget(); }
3106c3fb27SDimitry Andric 
3206c3fb27SDimitry Andric const CodeGenOptions &ABIInfo::getCodeGenOpts() const {
3306c3fb27SDimitry Andric   return CGT.getCodeGenOpts();
3406c3fb27SDimitry Andric }
3506c3fb27SDimitry Andric 
3606c3fb27SDimitry Andric bool ABIInfo::isAndroid() const { return getTarget().getTriple().isAndroid(); }
3706c3fb27SDimitry Andric 
3806c3fb27SDimitry Andric bool ABIInfo::isOHOSFamily() const {
3906c3fb27SDimitry Andric   return getTarget().getTriple().isOHOSFamily();
4006c3fb27SDimitry Andric }
4106c3fb27SDimitry Andric 
42*0fca6ea1SDimitry Andric RValue ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
43*0fca6ea1SDimitry Andric                             QualType Ty, AggValueSlot Slot) const {
44*0fca6ea1SDimitry Andric   return RValue::getIgnored();
4506c3fb27SDimitry Andric }
4606c3fb27SDimitry Andric 
4706c3fb27SDimitry Andric bool ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
4806c3fb27SDimitry Andric   return false;
4906c3fb27SDimitry Andric }
5006c3fb27SDimitry Andric 
5106c3fb27SDimitry Andric bool ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
5206c3fb27SDimitry Andric                                                 uint64_t Members) const {
5306c3fb27SDimitry Andric   return false;
5406c3fb27SDimitry Andric }
5506c3fb27SDimitry Andric 
5606c3fb27SDimitry Andric bool ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const {
5706c3fb27SDimitry Andric   // For compatibility with GCC, ignore empty bitfields in C++ mode.
5806c3fb27SDimitry Andric   return getContext().getLangOpts().CPlusPlus;
5906c3fb27SDimitry Andric }
6006c3fb27SDimitry Andric 
6106c3fb27SDimitry Andric bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base,
6206c3fb27SDimitry Andric                                      uint64_t &Members) const {
6306c3fb27SDimitry Andric   if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
64*0fca6ea1SDimitry Andric     uint64_t NElements = AT->getZExtSize();
6506c3fb27SDimitry Andric     if (NElements == 0)
6606c3fb27SDimitry Andric       return false;
6706c3fb27SDimitry Andric     if (!isHomogeneousAggregate(AT->getElementType(), Base, Members))
6806c3fb27SDimitry Andric       return false;
6906c3fb27SDimitry Andric     Members *= NElements;
7006c3fb27SDimitry Andric   } else if (const RecordType *RT = Ty->getAs<RecordType>()) {
7106c3fb27SDimitry Andric     const RecordDecl *RD = RT->getDecl();
7206c3fb27SDimitry Andric     if (RD->hasFlexibleArrayMember())
7306c3fb27SDimitry Andric       return false;
7406c3fb27SDimitry Andric 
7506c3fb27SDimitry Andric     Members = 0;
7606c3fb27SDimitry Andric 
7706c3fb27SDimitry Andric     // If this is a C++ record, check the properties of the record such as
7806c3fb27SDimitry Andric     // bases and ABI specific restrictions
7906c3fb27SDimitry Andric     if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
8006c3fb27SDimitry Andric       if (!getCXXABI().isPermittedToBeHomogeneousAggregate(CXXRD))
8106c3fb27SDimitry Andric         return false;
8206c3fb27SDimitry Andric 
8306c3fb27SDimitry Andric       for (const auto &I : CXXRD->bases()) {
8406c3fb27SDimitry Andric         // Ignore empty records.
8506c3fb27SDimitry Andric         if (isEmptyRecord(getContext(), I.getType(), true))
8606c3fb27SDimitry Andric           continue;
8706c3fb27SDimitry Andric 
8806c3fb27SDimitry Andric         uint64_t FldMembers;
8906c3fb27SDimitry Andric         if (!isHomogeneousAggregate(I.getType(), Base, FldMembers))
9006c3fb27SDimitry Andric           return false;
9106c3fb27SDimitry Andric 
9206c3fb27SDimitry Andric         Members += FldMembers;
9306c3fb27SDimitry Andric       }
9406c3fb27SDimitry Andric     }
9506c3fb27SDimitry Andric 
9606c3fb27SDimitry Andric     for (const auto *FD : RD->fields()) {
9706c3fb27SDimitry Andric       // Ignore (non-zero arrays of) empty records.
9806c3fb27SDimitry Andric       QualType FT = FD->getType();
9906c3fb27SDimitry Andric       while (const ConstantArrayType *AT =
10006c3fb27SDimitry Andric              getContext().getAsConstantArrayType(FT)) {
101*0fca6ea1SDimitry Andric         if (AT->isZeroSize())
10206c3fb27SDimitry Andric           return false;
10306c3fb27SDimitry Andric         FT = AT->getElementType();
10406c3fb27SDimitry Andric       }
10506c3fb27SDimitry Andric       if (isEmptyRecord(getContext(), FT, true))
10606c3fb27SDimitry Andric         continue;
10706c3fb27SDimitry Andric 
10806c3fb27SDimitry Andric       if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() &&
10906c3fb27SDimitry Andric           FD->isZeroLengthBitField(getContext()))
11006c3fb27SDimitry Andric         continue;
11106c3fb27SDimitry Andric 
11206c3fb27SDimitry Andric       uint64_t FldMembers;
11306c3fb27SDimitry Andric       if (!isHomogeneousAggregate(FD->getType(), Base, FldMembers))
11406c3fb27SDimitry Andric         return false;
11506c3fb27SDimitry Andric 
11606c3fb27SDimitry Andric       Members = (RD->isUnion() ?
11706c3fb27SDimitry Andric                  std::max(Members, FldMembers) : Members + FldMembers);
11806c3fb27SDimitry Andric     }
11906c3fb27SDimitry Andric 
12006c3fb27SDimitry Andric     if (!Base)
12106c3fb27SDimitry Andric       return false;
12206c3fb27SDimitry Andric 
12306c3fb27SDimitry Andric     // Ensure there is no padding.
12406c3fb27SDimitry Andric     if (getContext().getTypeSize(Base) * Members !=
12506c3fb27SDimitry Andric         getContext().getTypeSize(Ty))
12606c3fb27SDimitry Andric       return false;
12706c3fb27SDimitry Andric   } else {
12806c3fb27SDimitry Andric     Members = 1;
12906c3fb27SDimitry Andric     if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
13006c3fb27SDimitry Andric       Members = 2;
13106c3fb27SDimitry Andric       Ty = CT->getElementType();
13206c3fb27SDimitry Andric     }
13306c3fb27SDimitry Andric 
13406c3fb27SDimitry Andric     // Most ABIs only support float, double, and some vector type widths.
13506c3fb27SDimitry Andric     if (!isHomogeneousAggregateBaseType(Ty))
13606c3fb27SDimitry Andric       return false;
13706c3fb27SDimitry Andric 
13806c3fb27SDimitry Andric     // The base type must be the same for all members.  Types that
13906c3fb27SDimitry Andric     // agree in both total size and mode (float vs. vector) are
14006c3fb27SDimitry Andric     // treated as being equivalent here.
14106c3fb27SDimitry Andric     const Type *TyPtr = Ty.getTypePtr();
14206c3fb27SDimitry Andric     if (!Base) {
14306c3fb27SDimitry Andric       Base = TyPtr;
14406c3fb27SDimitry Andric       // If it's a non-power-of-2 vector, its size is already a power-of-2,
14506c3fb27SDimitry Andric       // so make sure to widen it explicitly.
14606c3fb27SDimitry Andric       if (const VectorType *VT = Base->getAs<VectorType>()) {
14706c3fb27SDimitry Andric         QualType EltTy = VT->getElementType();
14806c3fb27SDimitry Andric         unsigned NumElements =
14906c3fb27SDimitry Andric             getContext().getTypeSize(VT) / getContext().getTypeSize(EltTy);
15006c3fb27SDimitry Andric         Base = getContext()
15106c3fb27SDimitry Andric                    .getVectorType(EltTy, NumElements, VT->getVectorKind())
15206c3fb27SDimitry Andric                    .getTypePtr();
15306c3fb27SDimitry Andric       }
15406c3fb27SDimitry Andric     }
15506c3fb27SDimitry Andric 
15606c3fb27SDimitry Andric     if (Base->isVectorType() != TyPtr->isVectorType() ||
15706c3fb27SDimitry Andric         getContext().getTypeSize(Base) != getContext().getTypeSize(TyPtr))
15806c3fb27SDimitry Andric       return false;
15906c3fb27SDimitry Andric   }
16006c3fb27SDimitry Andric   return Members > 0 && isHomogeneousAggregateSmallEnough(Base, Members);
16106c3fb27SDimitry Andric }
16206c3fb27SDimitry Andric 
16306c3fb27SDimitry Andric bool ABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
16406c3fb27SDimitry Andric   if (getContext().isPromotableIntegerType(Ty))
16506c3fb27SDimitry Andric     return true;
16606c3fb27SDimitry Andric 
16706c3fb27SDimitry Andric   if (const auto *EIT = Ty->getAs<BitIntType>())
16806c3fb27SDimitry Andric     if (EIT->getNumBits() < getContext().getTypeSize(getContext().IntTy))
16906c3fb27SDimitry Andric       return true;
17006c3fb27SDimitry Andric 
17106c3fb27SDimitry Andric   return false;
17206c3fb27SDimitry Andric }
17306c3fb27SDimitry Andric 
17406c3fb27SDimitry Andric ABIArgInfo ABIInfo::getNaturalAlignIndirect(QualType Ty, bool ByVal,
17506c3fb27SDimitry Andric                                             bool Realign,
17606c3fb27SDimitry Andric                                             llvm::Type *Padding) const {
17706c3fb27SDimitry Andric   return ABIArgInfo::getIndirect(getContext().getTypeAlignInChars(Ty), ByVal,
17806c3fb27SDimitry Andric                                  Realign, Padding);
17906c3fb27SDimitry Andric }
18006c3fb27SDimitry Andric 
18106c3fb27SDimitry Andric ABIArgInfo ABIInfo::getNaturalAlignIndirectInReg(QualType Ty,
18206c3fb27SDimitry Andric                                                  bool Realign) const {
18306c3fb27SDimitry Andric   return ABIArgInfo::getIndirectInReg(getContext().getTypeAlignInChars(Ty),
18406c3fb27SDimitry Andric                                       /*ByVal*/ false, Realign);
18506c3fb27SDimitry Andric }
18606c3fb27SDimitry Andric 
187*0fca6ea1SDimitry Andric void ABIInfo::appendAttributeMangling(TargetAttr *Attr,
188*0fca6ea1SDimitry Andric                                       raw_ostream &Out) const {
189*0fca6ea1SDimitry Andric   if (Attr->isDefaultVersion())
190*0fca6ea1SDimitry Andric     return;
191*0fca6ea1SDimitry Andric   appendAttributeMangling(Attr->getFeaturesStr(), Out);
192*0fca6ea1SDimitry Andric }
193*0fca6ea1SDimitry Andric 
194*0fca6ea1SDimitry Andric void ABIInfo::appendAttributeMangling(TargetVersionAttr *Attr,
195*0fca6ea1SDimitry Andric                                       raw_ostream &Out) const {
196*0fca6ea1SDimitry Andric   appendAttributeMangling(Attr->getNamesStr(), Out);
197*0fca6ea1SDimitry Andric }
198*0fca6ea1SDimitry Andric 
199*0fca6ea1SDimitry Andric void ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
200*0fca6ea1SDimitry Andric                                       raw_ostream &Out) const {
201*0fca6ea1SDimitry Andric   appendAttributeMangling(Attr->getFeatureStr(Index), Out);
202*0fca6ea1SDimitry Andric   Out << '.' << Attr->getMangledIndex(Index);
203*0fca6ea1SDimitry Andric }
204*0fca6ea1SDimitry Andric 
205*0fca6ea1SDimitry Andric void ABIInfo::appendAttributeMangling(StringRef AttrStr,
206*0fca6ea1SDimitry Andric                                       raw_ostream &Out) const {
207*0fca6ea1SDimitry Andric   if (AttrStr == "default") {
208*0fca6ea1SDimitry Andric     Out << ".default";
209*0fca6ea1SDimitry Andric     return;
210*0fca6ea1SDimitry Andric   }
211*0fca6ea1SDimitry Andric 
212*0fca6ea1SDimitry Andric   Out << '.';
213*0fca6ea1SDimitry Andric   const TargetInfo &TI = CGT.getTarget();
214*0fca6ea1SDimitry Andric   ParsedTargetAttr Info = TI.parseTargetAttr(AttrStr);
215*0fca6ea1SDimitry Andric 
216*0fca6ea1SDimitry Andric   llvm::sort(Info.Features, [&TI](StringRef LHS, StringRef RHS) {
217*0fca6ea1SDimitry Andric     // Multiversioning doesn't allow "no-${feature}", so we can
218*0fca6ea1SDimitry Andric     // only have "+" prefixes here.
219*0fca6ea1SDimitry Andric     assert(LHS.starts_with("+") && RHS.starts_with("+") &&
220*0fca6ea1SDimitry Andric            "Features should always have a prefix.");
221*0fca6ea1SDimitry Andric     return TI.multiVersionSortPriority(LHS.substr(1)) >
222*0fca6ea1SDimitry Andric            TI.multiVersionSortPriority(RHS.substr(1));
223*0fca6ea1SDimitry Andric   });
224*0fca6ea1SDimitry Andric 
225*0fca6ea1SDimitry Andric   bool IsFirst = true;
226*0fca6ea1SDimitry Andric   if (!Info.CPU.empty()) {
227*0fca6ea1SDimitry Andric     IsFirst = false;
228*0fca6ea1SDimitry Andric     Out << "arch_" << Info.CPU;
229*0fca6ea1SDimitry Andric   }
230*0fca6ea1SDimitry Andric 
231*0fca6ea1SDimitry Andric   for (StringRef Feat : Info.Features) {
232*0fca6ea1SDimitry Andric     if (!IsFirst)
233*0fca6ea1SDimitry Andric       Out << '_';
234*0fca6ea1SDimitry Andric     IsFirst = false;
235*0fca6ea1SDimitry Andric     Out << Feat.substr(1);
236*0fca6ea1SDimitry Andric   }
237*0fca6ea1SDimitry Andric }
238*0fca6ea1SDimitry Andric 
23906c3fb27SDimitry Andric // Pin the vtable to this file.
24006c3fb27SDimitry Andric SwiftABIInfo::~SwiftABIInfo() = default;
24106c3fb27SDimitry Andric 
24206c3fb27SDimitry Andric /// Does the given lowering require more than the given number of
24306c3fb27SDimitry Andric /// registers when expanded?
24406c3fb27SDimitry Andric ///
24506c3fb27SDimitry Andric /// This is intended to be the basis of a reasonable basic implementation
24606c3fb27SDimitry Andric /// of should{Pass,Return}Indirectly.
24706c3fb27SDimitry Andric ///
24806c3fb27SDimitry Andric /// For most targets, a limit of four total registers is reasonable; this
24906c3fb27SDimitry Andric /// limits the amount of code required in order to move around the value
25006c3fb27SDimitry Andric /// in case it wasn't produced immediately prior to the call by the caller
25106c3fb27SDimitry Andric /// (or wasn't produced in exactly the right registers) or isn't used
25206c3fb27SDimitry Andric /// immediately within the callee.  But some targets may need to further
25306c3fb27SDimitry Andric /// limit the register count due to an inability to support that many
25406c3fb27SDimitry Andric /// return registers.
25506c3fb27SDimitry Andric bool SwiftABIInfo::occupiesMoreThan(ArrayRef<llvm::Type *> scalarTypes,
25606c3fb27SDimitry Andric                                     unsigned maxAllRegisters) const {
25706c3fb27SDimitry Andric   unsigned intCount = 0, fpCount = 0;
25806c3fb27SDimitry Andric   for (llvm::Type *type : scalarTypes) {
25906c3fb27SDimitry Andric     if (type->isPointerTy()) {
26006c3fb27SDimitry Andric       intCount++;
26106c3fb27SDimitry Andric     } else if (auto intTy = dyn_cast<llvm::IntegerType>(type)) {
26206c3fb27SDimitry Andric       auto ptrWidth = CGT.getTarget().getPointerWidth(LangAS::Default);
26306c3fb27SDimitry Andric       intCount += (intTy->getBitWidth() + ptrWidth - 1) / ptrWidth;
26406c3fb27SDimitry Andric     } else {
26506c3fb27SDimitry Andric       assert(type->isVectorTy() || type->isFloatingPointTy());
26606c3fb27SDimitry Andric       fpCount++;
26706c3fb27SDimitry Andric     }
26806c3fb27SDimitry Andric   }
26906c3fb27SDimitry Andric 
27006c3fb27SDimitry Andric   return (intCount + fpCount > maxAllRegisters);
27106c3fb27SDimitry Andric }
27206c3fb27SDimitry Andric 
27306c3fb27SDimitry Andric bool SwiftABIInfo::shouldPassIndirectly(ArrayRef<llvm::Type *> ComponentTys,
27406c3fb27SDimitry Andric                                         bool AsReturnValue) const {
27506c3fb27SDimitry Andric   return occupiesMoreThan(ComponentTys, /*total=*/4);
27606c3fb27SDimitry Andric }
27706c3fb27SDimitry Andric 
27806c3fb27SDimitry Andric bool SwiftABIInfo::isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy,
27906c3fb27SDimitry Andric                                      unsigned NumElts) const {
28006c3fb27SDimitry Andric   // The default implementation of this assumes that the target guarantees
28106c3fb27SDimitry Andric   // 128-bit SIMD support but nothing more.
28206c3fb27SDimitry Andric   return (VectorSize.getQuantity() > 8 && VectorSize.getQuantity() <= 16);
28306c3fb27SDimitry Andric }
284