xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===- ABIInfo.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 "ABIInfo.h"
10*06c3fb27SDimitry Andric #include "ABIInfoImpl.h"
11*06c3fb27SDimitry Andric 
12*06c3fb27SDimitry Andric using namespace clang;
13*06c3fb27SDimitry Andric using namespace clang::CodeGen;
14*06c3fb27SDimitry Andric 
15*06c3fb27SDimitry Andric // Pin the vtable to this file.
16*06c3fb27SDimitry Andric ABIInfo::~ABIInfo() = default;
17*06c3fb27SDimitry Andric 
18*06c3fb27SDimitry Andric CGCXXABI &ABIInfo::getCXXABI() const { return CGT.getCXXABI(); }
19*06c3fb27SDimitry Andric 
20*06c3fb27SDimitry Andric ASTContext &ABIInfo::getContext() const { return CGT.getContext(); }
21*06c3fb27SDimitry Andric 
22*06c3fb27SDimitry Andric llvm::LLVMContext &ABIInfo::getVMContext() const {
23*06c3fb27SDimitry Andric   return CGT.getLLVMContext();
24*06c3fb27SDimitry Andric }
25*06c3fb27SDimitry Andric 
26*06c3fb27SDimitry Andric const llvm::DataLayout &ABIInfo::getDataLayout() const {
27*06c3fb27SDimitry Andric   return CGT.getDataLayout();
28*06c3fb27SDimitry Andric }
29*06c3fb27SDimitry Andric 
30*06c3fb27SDimitry Andric const TargetInfo &ABIInfo::getTarget() const { return CGT.getTarget(); }
31*06c3fb27SDimitry Andric 
32*06c3fb27SDimitry Andric const CodeGenOptions &ABIInfo::getCodeGenOpts() const {
33*06c3fb27SDimitry Andric   return CGT.getCodeGenOpts();
34*06c3fb27SDimitry Andric }
35*06c3fb27SDimitry Andric 
36*06c3fb27SDimitry Andric bool ABIInfo::isAndroid() const { return getTarget().getTriple().isAndroid(); }
37*06c3fb27SDimitry Andric 
38*06c3fb27SDimitry Andric bool ABIInfo::isOHOSFamily() const {
39*06c3fb27SDimitry Andric   return getTarget().getTriple().isOHOSFamily();
40*06c3fb27SDimitry Andric }
41*06c3fb27SDimitry Andric 
42*06c3fb27SDimitry Andric Address ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
43*06c3fb27SDimitry Andric                              QualType Ty) const {
44*06c3fb27SDimitry Andric   return Address::invalid();
45*06c3fb27SDimitry Andric }
46*06c3fb27SDimitry Andric 
47*06c3fb27SDimitry Andric bool ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
48*06c3fb27SDimitry Andric   return false;
49*06c3fb27SDimitry Andric }
50*06c3fb27SDimitry Andric 
51*06c3fb27SDimitry Andric bool ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
52*06c3fb27SDimitry Andric                                                 uint64_t Members) const {
53*06c3fb27SDimitry Andric   return false;
54*06c3fb27SDimitry Andric }
55*06c3fb27SDimitry Andric 
56*06c3fb27SDimitry Andric bool ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const {
57*06c3fb27SDimitry Andric   // For compatibility with GCC, ignore empty bitfields in C++ mode.
58*06c3fb27SDimitry Andric   return getContext().getLangOpts().CPlusPlus;
59*06c3fb27SDimitry Andric }
60*06c3fb27SDimitry Andric 
61*06c3fb27SDimitry Andric bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base,
62*06c3fb27SDimitry Andric                                      uint64_t &Members) const {
63*06c3fb27SDimitry Andric   if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
64*06c3fb27SDimitry Andric     uint64_t NElements = AT->getSize().getZExtValue();
65*06c3fb27SDimitry Andric     if (NElements == 0)
66*06c3fb27SDimitry Andric       return false;
67*06c3fb27SDimitry Andric     if (!isHomogeneousAggregate(AT->getElementType(), Base, Members))
68*06c3fb27SDimitry Andric       return false;
69*06c3fb27SDimitry Andric     Members *= NElements;
70*06c3fb27SDimitry Andric   } else if (const RecordType *RT = Ty->getAs<RecordType>()) {
71*06c3fb27SDimitry Andric     const RecordDecl *RD = RT->getDecl();
72*06c3fb27SDimitry Andric     if (RD->hasFlexibleArrayMember())
73*06c3fb27SDimitry Andric       return false;
74*06c3fb27SDimitry Andric 
75*06c3fb27SDimitry Andric     Members = 0;
76*06c3fb27SDimitry Andric 
77*06c3fb27SDimitry Andric     // If this is a C++ record, check the properties of the record such as
78*06c3fb27SDimitry Andric     // bases and ABI specific restrictions
79*06c3fb27SDimitry Andric     if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
80*06c3fb27SDimitry Andric       if (!getCXXABI().isPermittedToBeHomogeneousAggregate(CXXRD))
81*06c3fb27SDimitry Andric         return false;
82*06c3fb27SDimitry Andric 
83*06c3fb27SDimitry Andric       for (const auto &I : CXXRD->bases()) {
84*06c3fb27SDimitry Andric         // Ignore empty records.
85*06c3fb27SDimitry Andric         if (isEmptyRecord(getContext(), I.getType(), true))
86*06c3fb27SDimitry Andric           continue;
87*06c3fb27SDimitry Andric 
88*06c3fb27SDimitry Andric         uint64_t FldMembers;
89*06c3fb27SDimitry Andric         if (!isHomogeneousAggregate(I.getType(), Base, FldMembers))
90*06c3fb27SDimitry Andric           return false;
91*06c3fb27SDimitry Andric 
92*06c3fb27SDimitry Andric         Members += FldMembers;
93*06c3fb27SDimitry Andric       }
94*06c3fb27SDimitry Andric     }
95*06c3fb27SDimitry Andric 
96*06c3fb27SDimitry Andric     for (const auto *FD : RD->fields()) {
97*06c3fb27SDimitry Andric       // Ignore (non-zero arrays of) empty records.
98*06c3fb27SDimitry Andric       QualType FT = FD->getType();
99*06c3fb27SDimitry Andric       while (const ConstantArrayType *AT =
100*06c3fb27SDimitry Andric              getContext().getAsConstantArrayType(FT)) {
101*06c3fb27SDimitry Andric         if (AT->getSize().getZExtValue() == 0)
102*06c3fb27SDimitry Andric           return false;
103*06c3fb27SDimitry Andric         FT = AT->getElementType();
104*06c3fb27SDimitry Andric       }
105*06c3fb27SDimitry Andric       if (isEmptyRecord(getContext(), FT, true))
106*06c3fb27SDimitry Andric         continue;
107*06c3fb27SDimitry Andric 
108*06c3fb27SDimitry Andric       if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() &&
109*06c3fb27SDimitry Andric           FD->isZeroLengthBitField(getContext()))
110*06c3fb27SDimitry Andric         continue;
111*06c3fb27SDimitry Andric 
112*06c3fb27SDimitry Andric       uint64_t FldMembers;
113*06c3fb27SDimitry Andric       if (!isHomogeneousAggregate(FD->getType(), Base, FldMembers))
114*06c3fb27SDimitry Andric         return false;
115*06c3fb27SDimitry Andric 
116*06c3fb27SDimitry Andric       Members = (RD->isUnion() ?
117*06c3fb27SDimitry Andric                  std::max(Members, FldMembers) : Members + FldMembers);
118*06c3fb27SDimitry Andric     }
119*06c3fb27SDimitry Andric 
120*06c3fb27SDimitry Andric     if (!Base)
121*06c3fb27SDimitry Andric       return false;
122*06c3fb27SDimitry Andric 
123*06c3fb27SDimitry Andric     // Ensure there is no padding.
124*06c3fb27SDimitry Andric     if (getContext().getTypeSize(Base) * Members !=
125*06c3fb27SDimitry Andric         getContext().getTypeSize(Ty))
126*06c3fb27SDimitry Andric       return false;
127*06c3fb27SDimitry Andric   } else {
128*06c3fb27SDimitry Andric     Members = 1;
129*06c3fb27SDimitry Andric     if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
130*06c3fb27SDimitry Andric       Members = 2;
131*06c3fb27SDimitry Andric       Ty = CT->getElementType();
132*06c3fb27SDimitry Andric     }
133*06c3fb27SDimitry Andric 
134*06c3fb27SDimitry Andric     // Most ABIs only support float, double, and some vector type widths.
135*06c3fb27SDimitry Andric     if (!isHomogeneousAggregateBaseType(Ty))
136*06c3fb27SDimitry Andric       return false;
137*06c3fb27SDimitry Andric 
138*06c3fb27SDimitry Andric     // The base type must be the same for all members.  Types that
139*06c3fb27SDimitry Andric     // agree in both total size and mode (float vs. vector) are
140*06c3fb27SDimitry Andric     // treated as being equivalent here.
141*06c3fb27SDimitry Andric     const Type *TyPtr = Ty.getTypePtr();
142*06c3fb27SDimitry Andric     if (!Base) {
143*06c3fb27SDimitry Andric       Base = TyPtr;
144*06c3fb27SDimitry Andric       // If it's a non-power-of-2 vector, its size is already a power-of-2,
145*06c3fb27SDimitry Andric       // so make sure to widen it explicitly.
146*06c3fb27SDimitry Andric       if (const VectorType *VT = Base->getAs<VectorType>()) {
147*06c3fb27SDimitry Andric         QualType EltTy = VT->getElementType();
148*06c3fb27SDimitry Andric         unsigned NumElements =
149*06c3fb27SDimitry Andric             getContext().getTypeSize(VT) / getContext().getTypeSize(EltTy);
150*06c3fb27SDimitry Andric         Base = getContext()
151*06c3fb27SDimitry Andric                    .getVectorType(EltTy, NumElements, VT->getVectorKind())
152*06c3fb27SDimitry Andric                    .getTypePtr();
153*06c3fb27SDimitry Andric       }
154*06c3fb27SDimitry Andric     }
155*06c3fb27SDimitry Andric 
156*06c3fb27SDimitry Andric     if (Base->isVectorType() != TyPtr->isVectorType() ||
157*06c3fb27SDimitry Andric         getContext().getTypeSize(Base) != getContext().getTypeSize(TyPtr))
158*06c3fb27SDimitry Andric       return false;
159*06c3fb27SDimitry Andric   }
160*06c3fb27SDimitry Andric   return Members > 0 && isHomogeneousAggregateSmallEnough(Base, Members);
161*06c3fb27SDimitry Andric }
162*06c3fb27SDimitry Andric 
163*06c3fb27SDimitry Andric bool ABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
164*06c3fb27SDimitry Andric   if (getContext().isPromotableIntegerType(Ty))
165*06c3fb27SDimitry Andric     return true;
166*06c3fb27SDimitry Andric 
167*06c3fb27SDimitry Andric   if (const auto *EIT = Ty->getAs<BitIntType>())
168*06c3fb27SDimitry Andric     if (EIT->getNumBits() < getContext().getTypeSize(getContext().IntTy))
169*06c3fb27SDimitry Andric       return true;
170*06c3fb27SDimitry Andric 
171*06c3fb27SDimitry Andric   return false;
172*06c3fb27SDimitry Andric }
173*06c3fb27SDimitry Andric 
174*06c3fb27SDimitry Andric ABIArgInfo ABIInfo::getNaturalAlignIndirect(QualType Ty, bool ByVal,
175*06c3fb27SDimitry Andric                                             bool Realign,
176*06c3fb27SDimitry Andric                                             llvm::Type *Padding) const {
177*06c3fb27SDimitry Andric   return ABIArgInfo::getIndirect(getContext().getTypeAlignInChars(Ty), ByVal,
178*06c3fb27SDimitry Andric                                  Realign, Padding);
179*06c3fb27SDimitry Andric }
180*06c3fb27SDimitry Andric 
181*06c3fb27SDimitry Andric ABIArgInfo ABIInfo::getNaturalAlignIndirectInReg(QualType Ty,
182*06c3fb27SDimitry Andric                                                  bool Realign) const {
183*06c3fb27SDimitry Andric   return ABIArgInfo::getIndirectInReg(getContext().getTypeAlignInChars(Ty),
184*06c3fb27SDimitry Andric                                       /*ByVal*/ false, Realign);
185*06c3fb27SDimitry Andric }
186*06c3fb27SDimitry Andric 
187*06c3fb27SDimitry Andric // Pin the vtable to this file.
188*06c3fb27SDimitry Andric SwiftABIInfo::~SwiftABIInfo() = default;
189*06c3fb27SDimitry Andric 
190*06c3fb27SDimitry Andric /// Does the given lowering require more than the given number of
191*06c3fb27SDimitry Andric /// registers when expanded?
192*06c3fb27SDimitry Andric ///
193*06c3fb27SDimitry Andric /// This is intended to be the basis of a reasonable basic implementation
194*06c3fb27SDimitry Andric /// of should{Pass,Return}Indirectly.
195*06c3fb27SDimitry Andric ///
196*06c3fb27SDimitry Andric /// For most targets, a limit of four total registers is reasonable; this
197*06c3fb27SDimitry Andric /// limits the amount of code required in order to move around the value
198*06c3fb27SDimitry Andric /// in case it wasn't produced immediately prior to the call by the caller
199*06c3fb27SDimitry Andric /// (or wasn't produced in exactly the right registers) or isn't used
200*06c3fb27SDimitry Andric /// immediately within the callee.  But some targets may need to further
201*06c3fb27SDimitry Andric /// limit the register count due to an inability to support that many
202*06c3fb27SDimitry Andric /// return registers.
203*06c3fb27SDimitry Andric bool SwiftABIInfo::occupiesMoreThan(ArrayRef<llvm::Type *> scalarTypes,
204*06c3fb27SDimitry Andric                                     unsigned maxAllRegisters) const {
205*06c3fb27SDimitry Andric   unsigned intCount = 0, fpCount = 0;
206*06c3fb27SDimitry Andric   for (llvm::Type *type : scalarTypes) {
207*06c3fb27SDimitry Andric     if (type->isPointerTy()) {
208*06c3fb27SDimitry Andric       intCount++;
209*06c3fb27SDimitry Andric     } else if (auto intTy = dyn_cast<llvm::IntegerType>(type)) {
210*06c3fb27SDimitry Andric       auto ptrWidth = CGT.getTarget().getPointerWidth(LangAS::Default);
211*06c3fb27SDimitry Andric       intCount += (intTy->getBitWidth() + ptrWidth - 1) / ptrWidth;
212*06c3fb27SDimitry Andric     } else {
213*06c3fb27SDimitry Andric       assert(type->isVectorTy() || type->isFloatingPointTy());
214*06c3fb27SDimitry Andric       fpCount++;
215*06c3fb27SDimitry Andric     }
216*06c3fb27SDimitry Andric   }
217*06c3fb27SDimitry Andric 
218*06c3fb27SDimitry Andric   return (intCount + fpCount > maxAllRegisters);
219*06c3fb27SDimitry Andric }
220*06c3fb27SDimitry Andric 
221*06c3fb27SDimitry Andric bool SwiftABIInfo::shouldPassIndirectly(ArrayRef<llvm::Type *> ComponentTys,
222*06c3fb27SDimitry Andric                                         bool AsReturnValue) const {
223*06c3fb27SDimitry Andric   return occupiesMoreThan(ComponentTys, /*total=*/4);
224*06c3fb27SDimitry Andric }
225*06c3fb27SDimitry Andric 
226*06c3fb27SDimitry Andric bool SwiftABIInfo::isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy,
227*06c3fb27SDimitry Andric                                      unsigned NumElts) const {
228*06c3fb27SDimitry Andric   // The default implementation of this assumes that the target guarantees
229*06c3fb27SDimitry Andric   // 128-bit SIMD support but nothing more.
230*06c3fb27SDimitry Andric   return (VectorSize.getQuantity() > 8 && VectorSize.getQuantity() <= 16);
231*06c3fb27SDimitry Andric }
232