1//===----------------------------------------------------------------------===//
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/Types.h"
10#include "llvm/Support/Casting.h"
11
12using namespace llvm;
13using namespace llvm::abi;
14
15bool llvm::abi::Type::isSVESizelessType() const {
16 if (getKind() == TypeKind::Vector) {
17 const VectorType *VT = static_cast<const VectorType *>(this);
18 return VT->isSVEType() && VT->isScalable();
19 }
20 if (getKind() == TypeKind::Tuple) {
21 const VectorType *VT =
22 static_cast<const TupleType *>(this)->getVectorType();
23 return VT->isSVEType() && VT->isScalable();
24 }
25 return false;
26}
27
28bool RecordType::isEmpty() const {
29 if (hasFlexibleArrayMember())
30 return false;
31
32 // We shouldn't need to check for emptiness if the record has virtual bases
33 // because it can't be passed in registers. This assertion is here to enforce
34 // that assumption.
35 assert(getNumVirtualBaseClasses() == 0 || !canPassInRegisters());
36
37 if (getNumVirtualBaseClasses() > 0)
38 return false;
39
40 for (const FieldInfo &Base : getBaseClasses()) {
41 const auto *BaseRT = dyn_cast<RecordType>(Val: Base.FieldType);
42 if (!BaseRT || !BaseRT->isEmpty())
43 return false;
44 }
45
46 for (const FieldInfo &FI : getFields())
47 if (!FI.isEmpty())
48 return false;
49
50 return true;
51}
52
53const FieldInfo *
54RecordType::getElementContainingOffset(unsigned OffsetInBits) const {
55 auto Contains = [&](const FieldInfo &Element) {
56 unsigned Start = Element.OffsetInBits;
57 unsigned Size = Element.FieldType->getSizeInBits().getFixedValue();
58 return OffsetInBits >= Start && OffsetInBits < Start + Size;
59 };
60
61 for (const FieldInfo &Base : getBaseClasses()) {
62 const auto *BaseRT = dyn_cast<RecordType>(Val: Base.FieldType);
63 if ((!BaseRT || !BaseRT->isEmpty()) && Contains(Base))
64 return &Base;
65 }
66
67 for (const FieldInfo &VBase : getVirtualBaseClasses()) {
68 const auto *VBaseRT = dyn_cast<RecordType>(Val: VBase.FieldType);
69 if ((!VBaseRT || !VBaseRT->isEmpty()) && Contains(VBase))
70 return &VBase;
71 }
72
73 for (const FieldInfo &Field : getFields()) {
74 if (Field.IsUnnamedBitfield)
75 continue;
76 if (Contains(Field))
77 return &Field;
78 }
79
80 return nullptr;
81}
82
83bool FieldInfo::isEmpty() const {
84 if (IsUnnamedBitfield)
85 return true;
86
87 const Type *Ty = FieldType;
88 bool WasArray = false;
89 while (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
90 // Constant arrays of zero length always count as empty.
91 if (AT->getNumElements() == 0)
92 return true;
93 Ty = AT->getElementType();
94 WasArray = true;
95 }
96
97 const auto *RT = dyn_cast<RecordType>(Val: Ty);
98 if (!RT)
99 return false;
100
101 // C++ record fields are never empty unless [[no_unique_address]] applies.
102 // That exception does not apply to arrays of C++ empty records.
103 if (RT->isCXXRecord() && (WasArray || !HasNoUniqueAddress))
104 return false;
105
106 return RT->isEmpty();
107}
108