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/ADT/bit.h"
11#include "llvm/Support/Casting.h"
12#include "llvm/Support/ErrorHandling.h"
13#include <algorithm>
14
15using namespace llvm;
16using namespace llvm::abi;
17
18uint64_t llvm::abi::Type::getABISizeInBits() const {
19 switch (getKind()) {
20 case TypeKind::Integer:
21 if (cast<IntegerType>(Val: this)->isBitInt())
22 return getTypeAllocSize().getFixedValue() * 8;
23 return getTypeStoreSizeInBits().getFixedValue();
24 case TypeKind::Float:
25 return getTypeAllocSize().getFixedValue() * 8;
26 case TypeKind::Complex:
27 return 2 * cast<ComplexType>(Val: this)->getElementType()->getABISizeInBits();
28 case TypeKind::Vector: {
29 const auto *VT = cast<VectorType>(Val: this);
30 if (VT->isScalable())
31 return 0;
32 const Type *EltTy = VT->getElementType();
33 const auto *IT = dyn_cast<IntegerType>(Val: EltTy);
34 uint64_t EltWidth = IT && !IT->isBitInt() ? IT->getFixedSizeInBitsOrZero()
35 : EltTy->getABISizeInBits();
36 uint64_t Width = EltWidth * VT->getNumElements().getFixedValue();
37 return bit_ceil(Value: std::max<uint64_t>(a: Width, b: 8));
38 }
39 case TypeKind::Void:
40 case TypeKind::Atomic:
41 case TypeKind::MemberPointer:
42 case TypeKind::Pointer:
43 case TypeKind::Array:
44 case TypeKind::Tuple:
45 case TypeKind::Record:
46 return getFixedSizeInBitsOrZero();
47 }
48 llvm_unreachable("unknown ABI type kind");
49}
50
51bool llvm::abi::Type::isSVESizelessType() const {
52 if (getKind() == TypeKind::Vector) {
53 const VectorType *VT = static_cast<const VectorType *>(this);
54 return VT->isSVEType() && VT->isScalable();
55 }
56 if (getKind() == TypeKind::Tuple) {
57 const VectorType *VT =
58 static_cast<const TupleType *>(this)->getVectorType();
59 return VT->isSVEType() && VT->isScalable();
60 }
61 return false;
62}
63
64bool llvm::abi::Type::isEmptyRecord() const {
65 const auto *RT = dyn_cast<RecordType>(Val: this);
66 return RT && RT->isEmpty();
67}
68
69bool RecordType::isEmpty() const {
70 if (hasFlexibleArrayMember())
71 return false;
72
73 // We shouldn't need to check for emptiness if the record has virtual bases
74 // because it can't be passed in registers. This assertion is here to enforce
75 // that assumption.
76 assert(getNumVirtualBaseClasses() == 0 || !canPassInRegisters());
77
78 if (getNumVirtualBaseClasses() > 0)
79 return false;
80
81 for (const FieldInfo &Base : getBaseClasses()) {
82 if (!Base.FieldType->isEmptyRecord())
83 return false;
84 }
85
86 for (const FieldInfo &FI : getFields())
87 if (!FI.isEmpty())
88 return false;
89
90 return true;
91}
92
93const FieldInfo *
94RecordType::getElementContainingOffset(unsigned OffsetInBits) const {
95 auto Contains = [&](const FieldInfo &Element) {
96 unsigned Start = Element.OffsetInBits;
97 unsigned Size = Element.FieldType->getSizeInBits().getFixedValue();
98 return OffsetInBits >= Start && OffsetInBits < Start + Size;
99 };
100
101 for (const FieldInfo &Base : getBaseClasses())
102 if (!Base.FieldType->isEmptyRecord() && Contains(Base))
103 return &Base;
104
105 for (const FieldInfo &VBase : getVirtualBaseClasses())
106 if (!VBase.FieldType->isEmptyRecord() && Contains(VBase))
107 return &VBase;
108
109 for (const FieldInfo &Field : getFields()) {
110 if (Field.IsUnnamedBitfield)
111 continue;
112 if (Contains(Field))
113 return &Field;
114 }
115
116 return nullptr;
117}
118
119bool FieldInfo::isEmpty() const {
120 if (IsUnnamedBitfield)
121 return true;
122
123 const Type *Ty = FieldType;
124 bool WasArray = false;
125 while (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
126 // Constant arrays of zero length always count as empty.
127 if (AT->getNumElements() == 0)
128 return true;
129 Ty = AT->getElementType();
130 WasArray = true;
131 }
132
133 const auto *RT = dyn_cast<RecordType>(Val: Ty);
134 if (!RT)
135 return false;
136
137 // C++ record fields are never empty unless [[no_unique_address]] applies.
138 // That exception does not apply to arrays of C++ empty records.
139 if (RT->isCXXRecord() && (WasArray || !HasNoUniqueAddress))
140 return false;
141
142 return RT->isEmpty();
143}
144