LLVM 24.0.0git
TargetInfo.cpp
Go to the documentation of this file.
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
10#include "llvm/ADT/STLExtras.h"
14#include <algorithm>
15#include <cstdint>
16
17using namespace llvm::abi;
18using llvm::dyn_cast;
19
21 // Atomic values use the evaluation kind of their underlying value type.
22 if (const auto *AT = dyn_cast<AtomicType>(Ty))
23 return isAggregateTypeForABI(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>(Ty))
34 if (AT->isMatrixType())
35 return false;
36
37 // Everything else is treated as aggregate.
38 return true;
39}
40
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(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(8, llvm::Align(1), /*Signed=*/false);
56 return TB.getArrayType(I8, NumBytes, NumBytes * 8);
57}
58
60 bool Packed) const {
61 assert(!Elems.empty() && "empty coerce sequence");
63 Fields.reserve(Elems.size());
64 for (const Type *Elt : Elems)
65 Fields.emplace_back(Elt, /*OffsetInBits=*/0);
66
68 return TB.getRecordType(Fields, llvm::TypeSize::getFixed(0), 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.
79 if (const auto *AT = dyn_cast<ArrayType>(Ty))
80 return getConvertedAlign(AT->getElementType());
81
82 if (const auto *VT = dyn_cast<VectorType>(Ty); VT && VT->isFixedLength())
83 return llvm::Align(VT->getABISizeInBits() / 8);
84
85 const auto *RT = dyn_cast<RecordType>(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(MaxAlign, getConvertedAlign(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>(Ty)) {
104 if (AT->isMatrixType())
105 return Ty;
106 const Type *Elt = convertTypeForMem(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(Elt, AT->getNumElements(),
113 }
114
115 const auto *RT = dyn_cast<RecordType>(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 };
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(MemberTy);
135 assert(!ConvertedTy->getSizeInBits().isScalable() &&
136 "scalable member has no fixed offset");
137 llvm::Align Alignment = getConvertedAlign(ConvertedTy);
138 if (Offset % (Alignment.value() * 8) != 0)
139 Packed = true;
140 MaxAlign = std::max(MaxAlign, Alignment);
141 Members.push_back({ConvertedTy, Offset, 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(Members,
152 [](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
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(Current, 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(getI8Array(PadBits / 8), Current);
176 }
177 Fields.emplace_back(Member.Ty, Member.Offset);
178 Current = std::max(Current, 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(MaxAlign, 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(getI8Array(PadBits / 8), Current);
191 }
192 }
193
195 return TB.getRecordType(Fields, RecordSize, RT->getAlignment(),
196 RT->getUnadjustedAlignment(), Pack);
197}
198
200 if (RT && !RT->canPassInRegisters())
201 return RAA_Indirect;
202 return RAA_Default;
203}
204
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>(Ty);
209 if (!RT)
210 return RAA_Default;
211 return getRecordArgABI(RT);
212}
213
215 if (const auto *RT = dyn_cast<RecordType>(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
226 const auto *RT = dyn_cast<RecordType>(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>(BaseTy);
238
239 if (!BaseRT || BaseRT->isEmpty())
240 continue;
241
242 const Type *Elem = isSingleElementStruct(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>(FTy)) {
256 if (AT->getNumElements() != 1)
257 break;
258 FTy = AT->getElementType();
259 }
260
261 const Type *Elem;
262 if (!isAggregateTypeForABI(FTy))
263 Elem = FTy;
264 else
265 Elem = isSingleElementStruct(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
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>(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(RT->getAlignment(), /*ByVal=*/false);
295 return true;
296 }
297 }
298
299 return false;
300}
301
303 uint64_t &Members) const {
304 bool isMatrixHA = getABICompatInfo().IsMatrixHA;
305 if (const auto *AT = dyn_cast<ArrayType>(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(AT->getElementType(), Base, Members))
312 return false;
313 Members *= NElements;
314 } else if (const auto *RT = dyn_cast<RecordType>(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()) {
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(BaseField.FieldType, Base, 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>(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
353 FD.IsBitField && FD.BitFieldWidth == 0)
354 continue;
355
356 uint64_t FldMembers = 0;
357 if (!isHomogeneousAggregate(FD.FieldType, Base, FldMembers))
358 return false;
359
360 Members =
361 RT->isUnion() ? std::max(Members, 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>(Ty)) {
374 Members = 2;
375 ElemTy = CT->getElementType();
376 }
377
378 // Most ABIs only support float, double, and some vector type widths.
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>(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(VT->getElementType(),
397 ElementCount::getFixed(NumElements),
398 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}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
OptimizedStructLayoutField Field
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
static llvm::Align getConvertedAlign(const Type *Ty)
Target-specific ABI information and factory functions.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:305
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:339
Helper class to encapsulate information about how a specific type should be passed to or returned fro...
static ArgInfo getIndirect(Align Align, bool ByVal, unsigned AddrSpace=0, bool Realign=false)
Realign: the caller couldn't guarantee sufficient alignment - the callee must copy the argument to a ...
const Type * getReturnType() const
bool canPassInRegisters() const
Definition Types.h:419
LLVM_ABI const Type * isSingleElementStruct(const Type *Ty) const
Returns the scalar a single-element struct reduces to, else null.
virtual bool isPermittedToBeHomogeneousAggregate(const RecordType *RT) const
Return true if the C++ ABI permits RT to be a homogeneous aggregate.
Definition TargetInfo.h:162
virtual const ABICompatInfo & getABICompatInfo() const =0
Return this target's ABI compatibility flags.
virtual bool isHomogeneousAggregateSmallEnough(const Type *Base, uint64_t Members) const
Return true if a homogeneous aggregate with Members copies of Base is small enough to be passed in re...
Definition TargetInfo.h:150
LLVM_ABI bool isHomogeneousAggregate(const Type *Ty, const Type *&Base, uint64_t &Members) const
Return true if Ty is an ELFv2-style homogeneous aggregate.
LLVM_ABI bool isPromotableInteger(const IntegerType *IT) const
virtual bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const
Return true if zero-length bitfields should be ignored when deciding whether an aggregate is homogene...
Definition TargetInfo.h:157
virtual bool isHomogeneousAggregateBaseType(const Type *Ty) const
Return true if Ty is a valid base type for a homogeneous aggregate.
Definition TargetInfo.h:144
LLVM_ABI const Type * getStructOfTypes(ArrayRef< const Type * > Elems, bool Packed) const
A record with one field per element of Elems, each at offset 0.
LLVM_ABI bool maybeCommonClassifyReturnType(FunctionInfo &FI) const
Apply rules for classifying return types that are common to all targets.
LLVM_ABI bool isAggregateTypeForABI(const Type *Ty) const
TypeBuilder & TB
Definition TargetInfo.h:67
LLVM_ABI const Type * useFirstFieldIfTransparentUnion(const Type *Ty) const
If Ty is a transparent union, return its first field type; otherwise return Ty unchanged.
LLVM_ABI ArgInfo getNaturalAlignIndirect(const Type *Ty, unsigned AddrSpace, bool ByVal=true) const
LLVM_ABI RecordArgABI getRecordArgABI(const RecordType *RT) const
LLVM_ABI const Type * convertTypeForMem(const Type *Ty) const
In-memory form of Ty.
virtual llvm::Align getMaxIntegerAlign() const
Alignment of the widest integer the target's data layout gives an alignment to.
Definition TargetInfo.h:96
LLVM_ABI const Type * getI8Array(uint64_t NumBytes) const
An array of NumBytes i8 elements, the padding element of a coerce-and-expand type.
Represents the ABI-specific view of a type in LLVM.
Definition Types.h:47
LLVM_ABI bool isEmptyRecord() const
True if this type is a record that is empty for ABI purposes.
Definition Types.cpp:64
TypeSize getSizeInBits() const
Definition Types.h:75
LLVM_ABI uint64_t getABISizeInBits() const
Returns the size in bits that the source language gives this type, including any padding.
Definition Types.cpp:18
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
StructPacking
Definition Types.h:378
@ RAA_Indirect
Pass it as a pointer to temporary memory.
Definition TargetInfo.h:37
@ RAA_Default
Pass it using the normal C aggregate rules for the ABI, potentially introducing extra copies and pass...
Definition TargetInfo.h:29
@ Offset
Definition DWP.cpp:577
void stable_sort(R &&Range)
Definition STLExtras.h:2132
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
constexpr unsigned BitWidth
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:82
bool IsMatrixHA
Whether a matrix type may be the base type of a homogeneous aggregate.
Definition TargetInfo.h:45