1//===- TargetInfo.cpp - Target ABI information ----------------------------===//
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 "llvm/ABI/TargetInfo.h"
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/SmallVector.h"
12#include "llvm/Support/Casting.h"
13#include "llvm/Support/MathExtras.h"
14#include <algorithm>
15#include <cstdint>
16
17using namespace llvm::abi;
18using llvm::dyn_cast;
19
20bool TargetInfo::isAggregateTypeForABI(const Type *Ty) const {
21 // Atomic values use the evaluation kind of their underlying value type.
22 if (const auto *AT = dyn_cast<AtomicType>(Val: Ty))
23 return isAggregateTypeForABI(Ty: AT->getValueType());
24
25 // Check for fundamental scalar types.
26 if (Ty->isInteger() || Ty->isFloat() || Ty->isPointer() || Ty->isVector() ||
27 Ty->isTuple())
28 return false;
29
30 // A matrix type is modeled as an array but lowers to a single flattened
31 // vector and has scalar evaluation kind in classic CodeGen, so it is not an
32 // aggregate for ABI purposes.
33 if (const auto *AT = dyn_cast<ArrayType>(Val: Ty))
34 if (AT->isMatrixType())
35 return false;
36
37 // Everything else is treated as aggregate.
38 return true;
39}
40
41bool TargetInfo::isPromotableInteger(const IntegerType *IT) const {
42 // TODO: The threshold should be the target's int size rather than a
43 // hardcoded 32.
44 unsigned BitWidth = IT->getSizeInBits().getFixedValue();
45 return BitWidth < 32;
46}
47
48ArgInfo TargetInfo::getNaturalAlignIndirect(const Type *Ty, unsigned AddrSpace,
49 bool ByVal) const {
50 return ArgInfo::getIndirect(Align: Ty->getAlignment(), ByVal, AddrSpace);
51}
52
53const Type *TargetInfo::getI8Array(uint64_t NumBytes) const {
54 assert(NumBytes != 0 && "empty padding");
55 const Type *I8 = TB.getIntegerType(BitWidth: 8, Align: llvm::Align(1), /*Signed=*/false);
56 return TB.getArrayType(ElementType: I8, NumElements: NumBytes, SizeInBits: NumBytes * 8);
57}
58
59const Type *TargetInfo::getStructOfTypes(llvm::ArrayRef<const Type *> Elems,
60 bool Packed) const {
61 assert(!Elems.empty() && "empty coerce sequence");
62 llvm::SmallVector<FieldInfo, 8> Fields;
63 Fields.reserve(N: Elems.size());
64 for (const Type *Elt : Elems)
65 Fields.emplace_back(Args&: Elt, /*OffsetInBits=*/Args: 0);
66
67 StructPacking Pack = Packed ? StructPacking::Packed : StructPacking::Default;
68 return TB.getRecordType(Fields, Size: llvm::TypeSize::getFixed(ExactSize: 0), ABIAlign: llvm::Align(1),
69 /*UnadjustedAlign=*/llvm::Align(1), Pack);
70}
71
72// Returns the alignment of Ty, a type returned by convertTypeForMem, as a
73// member of the struct built there. A packed record has alignment 1. A record
74// that is not packed has the alignment of its most-aligned member. An array has
75// the alignment of its element type. A fixed-length vector is aligned to its
76// size rounded up to a power of two, which for an AArch64 fixed-length SVE type
77// is wider than the 2 or 16 bytes the source language gives it.
78static llvm::Align getConvertedAlign(const Type *Ty) {
79 if (const auto *AT = dyn_cast<ArrayType>(Val: Ty))
80 return getConvertedAlign(Ty: AT->getElementType());
81
82 if (const auto *VT = dyn_cast<VectorType>(Val: Ty); VT && VT->isFixedLength())
83 return llvm::Align(VT->getABISizeInBits() / 8);
84
85 const auto *RT = dyn_cast<RecordType>(Val: Ty);
86 if (!RT)
87 return Ty->getAlignment();
88 if (RT->getPacking() == StructPacking::Packed)
89 return llvm::Align(1);
90
91 llvm::Align MaxAlign(1);
92 for (llvm::ArrayRef<FieldInfo> Members :
93 {RT->getFields(), RT->getBaseClasses()}) {
94 for (const FieldInfo &Member : Members) {
95 if (!Member.isEmpty())
96 MaxAlign = std::max(a: MaxAlign, b: getConvertedAlign(Ty: Member.FieldType));
97 }
98 }
99 return MaxAlign;
100}
101
102const Type *TargetInfo::convertTypeForMem(const Type *Ty) const {
103 if (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
104 if (AT->isMatrixType())
105 return Ty;
106 const Type *Elt = convertTypeForMem(Ty: AT->getElementType());
107 if (Elt == AT->getElementType())
108 return Ty;
109 assert(AT->getSizeInBits().isFixed() &&
110 "converted array element changes a scalable size");
111 return TB.getArrayType(ElementType: Elt, NumElements: AT->getNumElements(),
112 SizeInBits: AT->getSizeInBits().getFixedValue());
113 }
114
115 const auto *RT = dyn_cast<RecordType>(Val: Ty);
116 if (!RT || RT->isUnion())
117 return Ty;
118
119 // Current callers can't get here with virtual bases. If we need to handle
120 // virtual bases in the future, we'll need explicit handling for that below.
121 assert(RT->getNumVirtualBaseClasses() == 0 && "record has a virtual base");
122
123 struct ConvertedMember {
124 const Type *Ty;
125 uint64_t Offset;
126 llvm::Align Alignment;
127 };
128 llvm::SmallVector<ConvertedMember, 8> Members;
129 // The record is packed when a member offset or the record size is not a
130 // multiple of the converted alignment.
131 bool Packed = false;
132 llvm::Align MaxAlign(1);
133 auto addMember = [&](const Type *MemberTy, uint64_t Offset) {
134 const Type *ConvertedTy = convertTypeForMem(Ty: MemberTy);
135 assert(!ConvertedTy->getSizeInBits().isScalable() &&
136 "scalable member has no fixed offset");
137 llvm::Align Alignment = getConvertedAlign(Ty: ConvertedTy);
138 if (Offset % (Alignment.value() * 8) != 0)
139 Packed = true;
140 MaxAlign = std::max(a: MaxAlign, b: Alignment);
141 Members.push_back(Elt: {.Ty: ConvertedTy, .Offset: Offset, .Alignment: Alignment});
142 };
143 for (const FieldInfo &Base : RT->getBaseClasses()) {
144 if (!Base.FieldType->isEmptyRecord())
145 addMember(Base.FieldType, Base.OffsetInBits);
146 }
147 for (const FieldInfo &Field : RT->getFields()) {
148 if (!Field.isEmpty())
149 addMember(Field.FieldType, Field.OffsetInBits);
150 }
151 llvm::stable_sort(Range&: Members,
152 C: [](const ConvertedMember &A, const ConvertedMember &B) {
153 return A.Offset < B.Offset;
154 });
155
156 llvm::TypeSize RecordSize = RT->getSizeInBits();
157 if (RecordSize.isFixed() &&
158 RecordSize.getFixedValue() % (MaxAlign.value() * 8) != 0)
159 Packed = true;
160
161 llvm::SmallVector<FieldInfo, 8> Fields;
162 uint64_t Current = 0;
163 // Padding in a packed record is explicit for every gap. Padding in any
164 // other record is explicit only where the converted alignment does not place
165 // the next member.
166 auto needsPadding = [&](uint64_t Offset, llvm::Align Alignment) {
167 uint64_t AlignBits = Packed ? 8 : Alignment.value() * 8;
168 return Offset != llvm::alignTo(Value: Current, Align: AlignBits);
169 };
170 for (const ConvertedMember &Member : Members) {
171 if (Member.Offset > Current &&
172 needsPadding(Member.Offset, Member.Alignment)) {
173 uint64_t PadBits = Member.Offset - Current;
174 assert(PadBits % 8 == 0 && "padding is not a whole number of bytes");
175 Fields.emplace_back(Args: getI8Array(NumBytes: PadBits / 8), Args&: Current);
176 }
177 Fields.emplace_back(Args: Member.Ty, Args: Member.Offset);
178 Current = std::max(a: Current, b: Member.Offset +
179 Member.Ty->getSizeInBits().getFixedValue());
180 }
181
182 // The tail is placed by an integer as wide as the most aligned member, so
183 // the alignment that reaches it is capped at the widest integer's.
184 if (RecordSize.isFixed()) {
185 uint64_t Size = RecordSize.getFixedValue();
186 llvm::Align TailAlign = std::min(a: MaxAlign, b: getMaxIntegerAlign());
187 if (Size > Current && needsPadding(Size, TailAlign)) {
188 uint64_t PadBits = Size - Current;
189 assert(PadBits % 8 == 0 && "tail padding is not a whole number of bytes");
190 Fields.emplace_back(Args: getI8Array(NumBytes: PadBits / 8), Args&: Current);
191 }
192 }
193
194 StructPacking Pack = Packed ? StructPacking::Packed : StructPacking::Default;
195 return TB.getRecordType(Fields, Size: RecordSize, ABIAlign: RT->getAlignment(),
196 UnadjustedAlign: RT->getUnadjustedAlignment(), Pack);
197}
198
199RecordArgABI TargetInfo::getRecordArgABI(const RecordType *RT) const {
200 if (RT && !RT->canPassInRegisters())
201 return RAA_Indirect;
202 return RAA_Default;
203}
204
205RecordArgABI TargetInfo::getRecordArgABI(const Type *Ty) const {
206 // TODO: When Microsoft ABI is supported, CXX records may need different
207 // handling here (see MicrosoftCXXABI::getRecordArgABI in Clang).
208 const RecordType *RT = dyn_cast<RecordType>(Val: Ty);
209 if (!RT)
210 return RAA_Default;
211 return getRecordArgABI(RT);
212}
213
214const Type *TargetInfo::useFirstFieldIfTransparentUnion(const Type *Ty) const {
215 if (const auto *RT = dyn_cast<RecordType>(Val: Ty)) {
216 if (RT->isUnion() && RT->isTransparentUnion()) {
217 auto Fields = RT->getFields();
218 assert(!Fields.empty() && "transparent union cannot be empty");
219 return Fields.front().FieldType;
220 }
221 }
222 return Ty;
223}
224
225const Type *TargetInfo::isSingleElementStruct(const Type *Ty) const {
226 const auto *RT = dyn_cast<RecordType>(Val: Ty);
227 if (!RT)
228 return nullptr;
229
230 if (RT->hasFlexibleArrayMember())
231 return nullptr;
232
233 const Type *Found = nullptr;
234
235 for (const auto &Base : RT->getBaseClasses()) {
236 const Type *BaseTy = Base.FieldType;
237 const auto *BaseRT = dyn_cast<RecordType>(Val: BaseTy);
238
239 if (!BaseRT || BaseRT->isEmpty())
240 continue;
241
242 const Type *Elem = isSingleElementStruct(Ty: BaseTy);
243 if (!Elem || Found)
244 return nullptr;
245 Found = Elem;
246 }
247
248 for (const auto &FI : RT->getFields()) {
249 if (FI.isEmpty())
250 continue;
251
252 const Type *FTy = FI.FieldType;
253
254 // Treat single element arrays as the element.
255 while (const auto *AT = dyn_cast<ArrayType>(Val: FTy)) {
256 if (AT->getNumElements() != 1)
257 break;
258 FTy = AT->getElementType();
259 }
260
261 const Type *Elem;
262 if (!isAggregateTypeForABI(Ty: FTy))
263 Elem = FTy;
264 else
265 Elem = isSingleElementStruct(Ty: FTy);
266 if (!Elem || Found)
267 return nullptr;
268 Found = Elem;
269 }
270
271 if (!Found)
272 return nullptr;
273
274 // We don't consider a struct a single-element struct if it has padding
275 // beyond the element type.
276 if (Found->getABISizeInBits() != Ty->getABISizeInBits())
277 return nullptr;
278
279 return Found;
280}
281
282bool TargetInfo::maybeCommonClassifyReturnType(FunctionInfo &FI) const {
283 const abi::Type *Ty = FI.getReturnType();
284
285 // TODO: When Microsoft ABI is supported, CXX records may need different
286 // handling here (see MicrosoftCXXABI::classifyReturnType in Clang).
287 if (const auto *RT = llvm::dyn_cast<abi::RecordType>(Val: Ty)) {
288 if (!RT->canPassInRegisters()) {
289 // A record that cannot pass in registers (e.g. a non-trivial copy/dtor)
290 // is returned indirectly with ByVal=false. This is the RAA path and is
291 // distinct from getIndirectReturnResult (plain aggregates), which uses
292 // ByVal=true.
293 FI.getReturnInfo() =
294 ArgInfo::getIndirect(Align: RT->getAlignment(), /*ByVal=*/false);
295 return true;
296 }
297 }
298
299 return false;
300}
301
302bool TargetInfo::isHomogeneousAggregate(const Type *Ty, const Type *&Base,
303 uint64_t &Members) const {
304 bool isMatrixHA = getABICompatInfo().IsMatrixHA;
305 if (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
306 if (!isMatrixHA && AT->isMatrixType())
307 return false;
308 uint64_t NElements = AT->getNumElements();
309 if (NElements == 0)
310 return false;
311 if (!isHomogeneousAggregate(Ty: AT->getElementType(), Base, Members))
312 return false;
313 Members *= NElements;
314 } else if (const auto *RT = dyn_cast<RecordType>(Val: Ty)) {
315 if (RT->hasFlexibleArrayMember())
316 return false;
317
318 Members = 0;
319
320 // If this is a C++ record, check bases and ABI-specific restrictions.
321 if (RT->isCXXRecord()) {
322 if (!isPermittedToBeHomogeneousAggregate(RT))
323 return false;
324
325 for (const FieldInfo &BaseField : RT->getBaseClasses()) {
326 if (BaseField.FieldType->isEmptyRecord())
327 continue;
328
329 uint64_t FldMembers = 0;
330 if (!isHomogeneousAggregate(Ty: BaseField.FieldType, Base, Members&: FldMembers))
331 return false;
332
333 Members += FldMembers;
334 }
335 }
336
337 for (const FieldInfo &FD : RT->getFields()) {
338 // Ignore (non-zero arrays of) empty records.
339 const Type *FT = FD.FieldType;
340 while (const auto *AT = dyn_cast<ArrayType>(Val: FT)) {
341 // Don't drill down to the element type of a matrix type here.
342 // That should fall through to the element isHomogeneousAggregate check.
343 if (AT->isMatrixType())
344 break;
345 if (AT->getNumElements() == 0)
346 return false;
347 FT = AT->getElementType();
348 }
349 if (FT->isEmptyRecord())
350 continue;
351
352 if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() &&
353 FD.IsBitField && FD.BitFieldWidth == 0)
354 continue;
355
356 uint64_t FldMembers = 0;
357 if (!isHomogeneousAggregate(Ty: FD.FieldType, Base, Members&: FldMembers))
358 return false;
359
360 Members =
361 RT->isUnion() ? std::max(a: Members, b: FldMembers) : Members + FldMembers;
362 }
363
364 if (!Base)
365 return false;
366
367 // Ensure there is no padding.
368 if (Base->getTypeAllocSize() * Members != Ty->getTypeAllocSize())
369 return false;
370 } else {
371 Members = 1;
372 const Type *ElemTy = Ty;
373 if (const auto *CT = dyn_cast<ComplexType>(Val: Ty)) {
374 Members = 2;
375 ElemTy = CT->getElementType();
376 }
377
378 // Most ABIs only support float, double, and some vector type widths.
379 if (!isHomogeneousAggregateBaseType(Ty: ElemTy))
380 return false;
381
382 // The base type must be the same for all members. Types that agree in both
383 // total size and mode (float vs. vector) are treated as equivalent here.
384 if (!Base) {
385 Base = ElemTy;
386 // If it's a non-power-of-2 vector, its ABI size is already a power-of-2,
387 // so widen it explicitly to match Clang.
388 if (const auto *VT = dyn_cast<VectorType>(Val: Base)) {
389 assert(VT->isFixedLength() &&
390 "scalable vectors are never homogeneous aggregates");
391 uint64_t EltSize =
392 VT->getElementType()->getSizeInBits().getFixedValue();
393 unsigned NumElements =
394 VT->getTypeAllocSize().getFixedValue() * 8 / EltSize;
395 if (NumElements != VT->getNumElements().getKnownMinValue())
396 Base = TB.getVectorType(ElementType: VT->getElementType(),
397 NumElements: ElementCount::getFixed(MinVal: NumElements),
398 Align: VT->getAlignment());
399 }
400 }
401
402 if (Base->isVector() != ElemTy->isVector() ||
403 Base->getTypeAllocSize() != ElemTy->getTypeAllocSize())
404 return false;
405 }
406 return Members > 0 && isHomogeneousAggregateSmallEnough(Base, Members);
407}
408