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 // Direct virtual bases are revisited by the virtual base loop below, which
43 // also covers the indirect ones.
44 if (Base.IsVirtualBase)
45 continue;
46 const auto *BaseRT = dyn_cast<RecordType>(Val: Base.FieldType);
47 if ((!BaseRT || !BaseRT->isEmpty()) && Contains(Base))
48 return &Base;
49 }
50
51 for (const FieldInfo &VBase : getVirtualBaseClasses()) {
52 const auto *VBaseRT = dyn_cast<RecordType>(Val: VBase.FieldType);
53 if ((!VBaseRT || !VBaseRT->isEmpty()) && Contains(VBase))
54 return &VBase;
55 }
56
57 for (const FieldInfo &Field : getFields()) {
58 if (Field.IsUnnamedBitfield)
59 continue;
60 if (Contains(Field))
61 return &Field;
62 }
63
64 return nullptr;
65}
66
67bool FieldInfo::isEmpty() const {
68 if (IsUnnamedBitfield)
69 return true;
70 if (IsBitField && BitFieldWidth == 0)
71 return true;
72
73 const Type *Ty = FieldType;
74 while (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
75 if (AT->getNumElements() != 1)
76 break;
77 Ty = AT->getElementType();
78 }
79
80 if (const auto *RT = dyn_cast<RecordType>(Val: Ty))
81 return RT->isEmpty();
82
83 return Ty->isZeroSize();
84}
85