1//===- ABIInfo.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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "ABIInfo.h"
10#include "ABIInfoImpl.h"
11
12using namespace clang;
13using namespace clang::CodeGen;
14
15// Pin the vtable to this file.
16ABIInfo::~ABIInfo() = default;
17
18CGCXXABI &ABIInfo::getCXXABI() const { return CGT.getCXXABI(); }
19
20ASTContext &ABIInfo::getContext() const { return CGT.getContext(); }
21
22llvm::LLVMContext &ABIInfo::getVMContext() const {
23 return CGT.getLLVMContext();
24}
25
26const llvm::DataLayout &ABIInfo::getDataLayout() const {
27 return CGT.getDataLayout();
28}
29
30const TargetInfo &ABIInfo::getTarget() const { return CGT.getTarget(); }
31
32const CodeGenOptions &ABIInfo::getCodeGenOpts() const {
33 return CGT.getCodeGenOpts();
34}
35
36bool ABIInfo::isAndroid() const { return getTarget().getTriple().isAndroid(); }
37
38bool ABIInfo::isOHOSFamily() const {
39 return getTarget().getTriple().isOHOSFamily();
40}
41
42RValue ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
43 QualType Ty, AggValueSlot Slot) const {
44 return RValue::getIgnored();
45}
46
47RValue ABIInfo::EmitZOSVAArg(CodeGenFunction &CGF, Address VAListAddr,
48 QualType Ty, AggValueSlot Slot) const {
49 return RValue::getIgnored();
50}
51
52bool ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
53 return false;
54}
55
56bool ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
57 uint64_t Members) const {
58 return false;
59}
60
61bool ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const {
62 // For compatibility with GCC, ignore empty bitfields in C++ mode.
63 return getContext().getLangOpts().CPlusPlus;
64}
65
66bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base,
67 uint64_t &Members) const {
68 if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(T: Ty)) {
69 uint64_t NElements = AT->getZExtSize();
70 if (NElements == 0)
71 return false;
72 if (!isHomogeneousAggregate(Ty: AT->getElementType(), Base, Members))
73 return false;
74 Members *= NElements;
75 } else if (const auto *RD = Ty->getAsRecordDecl()) {
76 if (RD->hasFlexibleArrayMember())
77 return false;
78
79 Members = 0;
80
81 // If this is a C++ record, check the properties of the record such as
82 // bases and ABI specific restrictions
83 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD)) {
84 if (!getCXXABI().isPermittedToBeHomogeneousAggregate(RD: CXXRD))
85 return false;
86
87 for (const auto &I : CXXRD->bases()) {
88 // Ignore empty records.
89 if (isEmptyRecord(Context&: getContext(), T: I.getType(), AllowArrays: true))
90 continue;
91
92 uint64_t FldMembers;
93 if (!isHomogeneousAggregate(Ty: I.getType(), Base, Members&: FldMembers))
94 return false;
95
96 Members += FldMembers;
97 }
98 }
99
100 for (const auto *FD : RD->fields()) {
101 // Ignore (non-zero arrays of) empty records.
102 QualType FT = FD->getType();
103 while (const ConstantArrayType *AT =
104 getContext().getAsConstantArrayType(T: FT)) {
105 if (AT->isZeroSize())
106 return false;
107 FT = AT->getElementType();
108 }
109 if (isEmptyRecord(Context&: getContext(), T: FT, AllowArrays: true))
110 continue;
111
112 if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() &&
113 FD->isZeroLengthBitField())
114 continue;
115
116 uint64_t FldMembers;
117 if (!isHomogeneousAggregate(Ty: FD->getType(), Base, Members&: FldMembers))
118 return false;
119
120 Members = (RD->isUnion() ?
121 std::max(a: Members, b: FldMembers) : Members + FldMembers);
122 }
123
124 if (!Base)
125 return false;
126
127 // Ensure there is no padding.
128 if (getContext().getTypeSize(T: Base) * Members !=
129 getContext().getTypeSize(T: Ty))
130 return false;
131 } else {
132 Members = 1;
133 if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
134 Members = 2;
135 Ty = CT->getElementType();
136 }
137
138 // Most ABIs only support float, double, and some vector type widths.
139 if (!isHomogeneousAggregateBaseType(Ty))
140 return false;
141
142 // The base type must be the same for all members. Types that
143 // agree in both total size and mode (float vs. vector) are
144 // treated as being equivalent here.
145 const Type *TyPtr = Ty.getTypePtr();
146 if (!Base) {
147 Base = TyPtr;
148 // If it's a non-power-of-2 vector, its size is already a power-of-2,
149 // so make sure to widen it explicitly.
150 if (const VectorType *VT = Base->getAs<VectorType>()) {
151 QualType EltTy = VT->getElementType();
152 unsigned NumElements =
153 getContext().getTypeSize(T: VT) / getContext().getTypeSize(T: EltTy);
154 Base = getContext()
155 .getVectorType(VectorType: EltTy, NumElts: NumElements, VecKind: VT->getVectorKind())
156 .getTypePtr();
157 }
158 }
159
160 if (Base->isVectorType() != TyPtr->isVectorType() ||
161 getContext().getTypeSize(T: Base) != getContext().getTypeSize(T: TyPtr))
162 return false;
163 }
164 return Members > 0 && isHomogeneousAggregateSmallEnough(Base, Members);
165}
166
167bool ABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
168 if (getContext().isPromotableIntegerType(T: Ty))
169 return true;
170
171 if (const auto *EIT = Ty->getAs<BitIntType>())
172 if (EIT->getNumBits() < getContext().getTypeSize(T: getContext().IntTy))
173 return true;
174
175 return false;
176}
177
178ABIArgInfo ABIInfo::getNaturalAlignIndirect(QualType Ty, unsigned AddrSpace,
179 bool ByVal, bool Realign,
180 llvm::Type *Padding) const {
181 return ABIArgInfo::getIndirect(Alignment: getContext().getTypeAlignInChars(T: Ty),
182 AddrSpace, ByVal, Realign, Padding);
183}
184
185ABIArgInfo ABIInfo::getNaturalAlignIndirectInReg(QualType Ty,
186 bool Realign) const {
187 return ABIArgInfo::getIndirectInReg(Alignment: getContext().getTypeAlignInChars(T: Ty),
188 /*ByVal*/ false, Realign);
189}
190
191void ABIInfo::appendAttributeMangling(TargetAttr *Attr,
192 raw_ostream &Out) const {
193 if (Attr->isDefaultVersion())
194 return;
195 appendAttributeMangling(AttrStr: Attr->getFeaturesStr(), Out);
196}
197
198void ABIInfo::appendAttributeMangling(TargetVersionAttr *Attr,
199 raw_ostream &Out) const {
200 appendAttributeMangling(AttrStr: Attr->getNamesStr(), Out);
201}
202
203void ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
204 raw_ostream &Out) const {
205 appendAttributeMangling(AttrStr: Attr->getFeatureStr(Index), Out);
206 Out << '.' << Attr->getMangledIndex(Index);
207}
208
209void ABIInfo::appendAttributeMangling(StringRef AttrStr,
210 raw_ostream &Out) const {
211 if (AttrStr == "default") {
212 Out << ".default";
213 return;
214 }
215
216 Out << '.';
217 const TargetInfo &TI = CGT.getTarget();
218 ParsedTargetAttr Info = TI.parseTargetAttr(Str: AttrStr);
219
220 llvm::sort(C&: Info.Features, Comp: [&TI](StringRef LHS, StringRef RHS) {
221 // Multiversioning doesn't allow "no-${feature}", so we can
222 // only have "+" prefixes here.
223 assert(LHS.starts_with("+") && RHS.starts_with("+") &&
224 "Features should always have a prefix.");
225 return TI.getFMVPriority(Features: {LHS.substr(Start: 1)})
226 .ugt(RHS: TI.getFMVPriority(Features: {RHS.substr(Start: 1)}));
227 });
228
229 bool IsFirst = true;
230 if (!Info.CPU.empty()) {
231 IsFirst = false;
232 Out << "arch_" << Info.CPU;
233 }
234
235 for (StringRef Feat : Info.Features) {
236 if (!IsFirst)
237 Out << '_';
238 IsFirst = false;
239 Out << Feat.substr(Start: 1);
240 }
241}
242
243llvm::FixedVectorType *
244ABIInfo::getOptimalVectorMemoryType(llvm::FixedVectorType *T,
245 const LangOptions &Opt) const {
246 if (T->getNumElements() == 3 && !Opt.PreserveVec3Type)
247 return llvm::FixedVectorType::get(ElementType: T->getElementType(), NumElts: 4);
248 return T;
249}
250
251llvm::Value *ABIInfo::createCoercedLoad(Address SrcAddr, const ABIArgInfo &AI,
252 CodeGenFunction &CGF) const {
253 return nullptr;
254}
255
256void ABIInfo::createCoercedStore(llvm::Value *Val, Address DstAddr,
257 const ABIArgInfo &AI, bool DestIsVolatile,
258 CodeGenFunction &CGF) const {}
259
260ABIArgInfo ABIInfo::classifyArgForArm64ECVarArg(QualType Ty) const {
261 llvm_unreachable("Only implemented for x86");
262}
263
264// Pin the vtable to this file.
265SwiftABIInfo::~SwiftABIInfo() = default;
266
267/// Does the given lowering require more than the given number of
268/// registers when expanded?
269///
270/// This is intended to be the basis of a reasonable basic implementation
271/// of should{Pass,Return}Indirectly.
272///
273/// For most targets, a limit of four total registers is reasonable; this
274/// limits the amount of code required in order to move around the value
275/// in case it wasn't produced immediately prior to the call by the caller
276/// (or wasn't produced in exactly the right registers) or isn't used
277/// immediately within the callee. But some targets may need to further
278/// limit the register count due to an inability to support that many
279/// return registers.
280bool SwiftABIInfo::occupiesMoreThan(ArrayRef<llvm::Type *> scalarTypes,
281 unsigned maxAllRegisters) const {
282 unsigned intCount = 0, fpCount = 0;
283 for (llvm::Type *type : scalarTypes) {
284 if (type->isPointerTy()) {
285 intCount++;
286 } else if (auto intTy = dyn_cast<llvm::IntegerType>(Val: type)) {
287 auto ptrWidth = CGT.getTarget().getPointerWidth(AddrSpace: LangAS::Default);
288 intCount += (intTy->getBitWidth() + ptrWidth - 1) / ptrWidth;
289 } else {
290 assert(type->isVectorTy() || type->isFloatingPointTy());
291 fpCount++;
292 }
293 }
294
295 return (intCount + fpCount > maxAllRegisters);
296}
297
298bool SwiftABIInfo::shouldPassIndirectly(ArrayRef<llvm::Type *> ComponentTys,
299 bool AsReturnValue) const {
300 return occupiesMoreThan(scalarTypes: ComponentTys, /*total=*/maxAllRegisters: 4);
301}
302
303bool SwiftABIInfo::isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy,
304 unsigned NumElts) const {
305 // The default implementation of this assumes that the target guarantees
306 // 128-bit SIMD support but nothing more.
307 return (VectorSize.getQuantity() > 8 && VectorSize.getQuantity() <= 16);
308}
309