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/Support/Casting.h"
11#include <algorithm>
12#include <cstdint>
13
14using namespace llvm::abi;
15using llvm::dyn_cast;
16
17bool TargetInfo::isAggregateTypeForABI(const Type *Ty) const {
18 // Atomic values use the evaluation kind of their underlying value type.
19 if (const auto *AT = dyn_cast<AtomicType>(Val: Ty))
20 return isAggregateTypeForABI(Ty: AT->getValueType());
21
22 // Check for fundamental scalar types.
23 if (Ty->isInteger() || Ty->isFloat() || Ty->isPointer() || Ty->isVector())
24 return false;
25
26 // A matrix type is modeled as an array but lowers to a single flattened
27 // vector and has scalar evaluation kind in classic CodeGen, so it is not an
28 // aggregate for ABI purposes.
29 if (const auto *AT = dyn_cast<ArrayType>(Val: Ty))
30 if (AT->isMatrixType())
31 return false;
32
33 // Everything else is treated as aggregate.
34 return true;
35}
36
37bool TargetInfo::isPromotableInteger(const IntegerType *IT) const {
38 // TODO: The threshold should be the target's int size rather than a
39 // hardcoded 32.
40 unsigned BitWidth = IT->getSizeInBits().getFixedValue();
41 return BitWidth < 32;
42}
43
44ArgInfo TargetInfo::getNaturalAlignIndirect(const Type *Ty, bool ByVal) const {
45 return ArgInfo::getIndirect(Align: Ty->getAlignment(), ByVal);
46}
47
48RecordArgABI TargetInfo::getRecordArgABI(const RecordType *RT) const {
49 if (RT && !RT->canPassInRegisters())
50 return RAA_Indirect;
51 return RAA_Default;
52}
53
54RecordArgABI TargetInfo::getRecordArgABI(const Type *Ty) const {
55 // TODO: When Microsoft ABI is supported, CXX records may need different
56 // handling here (see MicrosoftCXXABI::getRecordArgABI in Clang).
57 const RecordType *RT = dyn_cast<RecordType>(Val: Ty);
58 if (!RT)
59 return RAA_Default;
60 return getRecordArgABI(RT);
61}
62
63const Type *TargetInfo::useFirstFieldIfTransparentUnion(const Type *Ty) const {
64 if (const auto *RT = dyn_cast<RecordType>(Val: Ty)) {
65 if (RT->isUnion() && RT->isTransparentUnion()) {
66 auto Fields = RT->getFields();
67 assert(!Fields.empty() && "transparent union cannot be empty");
68 return Fields.front().FieldType;
69 }
70 }
71 return Ty;
72}
73
74bool TargetInfo::maybeCommonClassifyReturnType(FunctionInfo &FI) const {
75 const abi::Type *Ty = FI.getReturnType();
76
77 // TODO: When Microsoft ABI is supported, CXX records may need different
78 // handling here (see MicrosoftCXXABI::classifyReturnType in Clang).
79 if (const auto *RT = llvm::dyn_cast<abi::RecordType>(Val: Ty)) {
80 if (!RT->canPassInRegisters()) {
81 // A record that cannot pass in registers (e.g. a non-trivial copy/dtor)
82 // is returned indirectly with ByVal=false. This is the RAA path and is
83 // distinct from getIndirectReturnResult (plain aggregates), which uses
84 // ByVal=true.
85 FI.getReturnInfo() =
86 ArgInfo::getIndirect(Align: RT->getAlignment(), /*ByVal=*/false);
87 return true;
88 }
89 }
90
91 return false;
92}
93
94namespace {
95
96bool isEmptyRecordForHA(const Type *Ty) {
97 const auto *RT = dyn_cast<RecordType>(Val: Ty);
98 return RT && RT->isEmpty();
99}
100
101} // namespace
102
103bool TargetInfo::isHomogeneousAggregate(const Type *Ty, const Type *&Base,
104 uint64_t &Members) const {
105 bool isMatrixHA = getABICompatInfo().IsMatrixHA;
106 if (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
107 if (!isMatrixHA && AT->isMatrixType())
108 return false;
109 uint64_t NElements = AT->getNumElements();
110 if (NElements == 0)
111 return false;
112 if (!isHomogeneousAggregate(Ty: AT->getElementType(), Base, Members))
113 return false;
114 Members *= NElements;
115 } else if (const auto *RT = dyn_cast<RecordType>(Val: Ty)) {
116 if (RT->hasFlexibleArrayMember())
117 return false;
118
119 Members = 0;
120
121 // If this is a C++ record, check bases and ABI-specific restrictions.
122 if (RT->isCXXRecord()) {
123 if (!isPermittedToBeHomogeneousAggregate(RT))
124 return false;
125
126 for (const FieldInfo &BaseField : RT->getBaseClasses()) {
127 if (isEmptyRecordForHA(Ty: BaseField.FieldType))
128 continue;
129
130 uint64_t FldMembers = 0;
131 if (!isHomogeneousAggregate(Ty: BaseField.FieldType, Base, Members&: FldMembers))
132 return false;
133
134 Members += FldMembers;
135 }
136 }
137
138 for (const FieldInfo &FD : RT->getFields()) {
139 // Ignore (non-zero arrays of) empty records.
140 const Type *FT = FD.FieldType;
141 while (const auto *AT = dyn_cast<ArrayType>(Val: FT)) {
142 // Don't drill down to the element type of a matrix type here.
143 // That should fall through to the element isHomogeneousAggregate check.
144 if (AT->isMatrixType())
145 break;
146 if (AT->getNumElements() == 0)
147 return false;
148 FT = AT->getElementType();
149 }
150 if (isEmptyRecordForHA(Ty: FT))
151 continue;
152
153 if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() &&
154 FD.IsBitField && FD.BitFieldWidth == 0)
155 continue;
156
157 uint64_t FldMembers = 0;
158 if (!isHomogeneousAggregate(Ty: FD.FieldType, Base, Members&: FldMembers))
159 return false;
160
161 Members =
162 RT->isUnion() ? std::max(a: Members, b: FldMembers) : Members + FldMembers;
163 }
164
165 if (!Base)
166 return false;
167
168 // Ensure there is no padding.
169 if (Base->getTypeAllocSize() * Members != Ty->getTypeAllocSize())
170 return false;
171 } else {
172 Members = 1;
173 const Type *ElemTy = Ty;
174 if (const auto *CT = dyn_cast<ComplexType>(Val: Ty)) {
175 Members = 2;
176 ElemTy = CT->getElementType();
177 }
178
179 // Most ABIs only support float, double, and some vector type widths.
180 if (!isHomogeneousAggregateBaseType(Ty: ElemTy))
181 return false;
182
183 // The base type must be the same for all members. Types that agree in both
184 // total size and mode (float vs. vector) are treated as equivalent here.
185 if (!Base) {
186 Base = ElemTy;
187 // If it's a non-power-of-2 vector, its ABI size is already a power-of-2,
188 // so widen it explicitly to match Clang.
189 if (const auto *VT = dyn_cast<VectorType>(Val: Base)) {
190 assert(VT->isFixedLength() &&
191 "scalable vectors are never homogeneous aggregates");
192 uint64_t EltSize =
193 VT->getElementType()->getSizeInBits().getFixedValue();
194 unsigned NumElements =
195 VT->getTypeAllocSize().getFixedValue() * 8 / EltSize;
196 if (NumElements != VT->getNumElements().getKnownMinValue())
197 Base = TB.getVectorType(ElementType: VT->getElementType(),
198 NumElements: ElementCount::getFixed(MinVal: NumElements),
199 Align: VT->getAlignment());
200 }
201 }
202
203 if (Base->isVector() != ElemTy->isVector() ||
204 Base->getTypeAllocSize() != ElemTy->getTypeAllocSize())
205 return false;
206 }
207 return Members > 0 && isHomogeneousAggregateSmallEnough(Base, Members);
208}
209