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 RecordType::isEmpty() const {
16 if (hasFlexibleArrayMember() || isPolymorphic() ||
17 getNumVirtualBaseClasses() != 0)
18 return false;
19
20 for (const FieldInfo &Base : getBaseClasses()) {
21 const auto *BaseRT = dyn_cast<RecordType>(Val: Base.FieldType);
22 if (!BaseRT || !BaseRT->isEmpty())
23 return false;
24 }
25
26 for (const FieldInfo &FI : getFields()) {
27 if (!FI.isEmpty())
28 return false;
29 }
30 return true;
31}
32
33const FieldInfo *
34RecordType::getElementContainingOffset(unsigned OffsetInBits) const {
35 auto Contains = [&](const FieldInfo &Element) {
36 unsigned Start = Element.OffsetInBits;
37 unsigned Size = Element.FieldType->getSizeInBits().getFixedValue();
38 return OffsetInBits >= Start && OffsetInBits < Start + Size;
39 };
40
41 for (const FieldInfo &Base : getBaseClasses()) {
42 const auto *BaseRT = dyn_cast<RecordType>(Val: Base.FieldType);
43 if ((!BaseRT || !BaseRT->isEmpty()) && Contains(Base))
44 return &Base;
45 }
46
47 for (const FieldInfo &VBase : getVirtualBaseClasses()) {
48 const auto *VBaseRT = dyn_cast<RecordType>(Val: VBase.FieldType);
49 if ((!VBaseRT || !VBaseRT->isEmpty()) && Contains(VBase))
50 return &VBase;
51 }
52
53 for (const FieldInfo &Field : getFields()) {
54 if (Field.IsUnnamedBitfield)
55 continue;
56 if (Contains(Field))
57 return &Field;
58 }
59
60 return nullptr;
61}
62
63bool FieldInfo::isEmpty() const {
64 if (IsUnnamedBitfield)
65 return true;
66 if (IsBitField && BitFieldWidth == 0)
67 return true;
68
69 const Type *Ty = FieldType;
70 while (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
71 if (AT->getNumElements() != 1)
72 break;
73 Ty = AT->getElementType();
74 }
75
76 if (const auto *RT = dyn_cast<RecordType>(Val: Ty))
77 return RT->isEmpty();
78
79 return Ty->isZeroSize();
80}
81