1//===- NativeTypeUDT.cpp - info about class/struct type ---------*- C++ -*-===//
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/DebugInfo/PDB/Native/NativeTypeUDT.h"
10#include "llvm/DebugInfo/CodeView/CodeView.h"
11#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
12#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
13#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
14#include "llvm/DebugInfo/PDB/PDBExtras.h"
15
16using namespace llvm;
17using namespace llvm::codeview;
18using namespace llvm::pdb;
19
20NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
21                             codeview::TypeIndex TI, codeview::ClassRecord CR)
22    : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
23      Class(std::move(CR)), Tag(&*Class) {}
24
25NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
26                             codeview::TypeIndex TI, codeview::UnionRecord UR)
27    : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
28      Union(std::move(UR)), Tag(&*Union) {}
29
30NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
31                             NativeTypeUDT &UnmodifiedType,
32                             codeview::ModifierRecord Modifier)
33    : NativeRawSymbol(Session, PDB_SymType::UDT, Id),
34      UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
35
36NativeTypeUDT::~NativeTypeUDT() = default;
37
38void NativeTypeUDT::dump(raw_ostream &OS, int Indent,
39                         PdbSymbolIdField ShowIdFields,
40                         PdbSymbolIdField RecurseIdFields) const {
41
42  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
43
44  dumpSymbolField(OS, "name", getName(), Indent);
45  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
46                    PdbSymbolIdField::LexicalParent, ShowIdFields,
47                    RecurseIdFields);
48  if (Modifiers)
49    dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
50                      Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
51                      RecurseIdFields);
52  if (getUdtKind() != PDB_UdtType::Union)
53    dumpSymbolField(OS, "virtualTableShapeId", getVirtualTableShapeId(),
54                    Indent);
55  dumpSymbolField(OS, "length", getLength(), Indent);
56  dumpSymbolField(OS, "udtKind", getUdtKind(), Indent);
57  dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
58  dumpSymbolField(OS, "constType", isConstType(), Indent);
59  dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
60  dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
61  dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
62  dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
63  dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
64  dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
65  dumpSymbolField(OS, "nested", isNested(), Indent);
66  dumpSymbolField(OS, "packed", isPacked(), Indent);
67  dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
68  dumpSymbolField(OS, "scoped", isScoped(), Indent);
69  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
70  dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
71  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
72}
73
74std::string NativeTypeUDT::getName() const {
75  if (UnmodifiedType)
76    return UnmodifiedType->getName();
77
78  return std::string(Tag->getName());
79}
80
81SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; }
82
83SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const {
84  if (UnmodifiedType)
85    return UnmodifiedType->getSymIndexId();
86
87  return 0;
88}
89
90SymIndexId NativeTypeUDT::getVirtualTableShapeId() const {
91  if (UnmodifiedType)
92    return UnmodifiedType->getVirtualTableShapeId();
93
94  if (Class)
95    return Session.getSymbolCache().findSymbolByTypeIndex(Class->VTableShape);
96
97  return 0;
98}
99
100uint64_t NativeTypeUDT::getLength() const {
101  if (UnmodifiedType)
102    return UnmodifiedType->getLength();
103
104  if (Class)
105    return Class->getSize();
106
107  return Union->getSize();
108}
109
110PDB_UdtType NativeTypeUDT::getUdtKind() const {
111  if (UnmodifiedType)
112    return UnmodifiedType->getUdtKind();
113
114  switch (Tag->Kind) {
115  case TypeRecordKind::Class:
116    return PDB_UdtType::Class;
117  case TypeRecordKind::Union:
118    return PDB_UdtType::Union;
119  case TypeRecordKind::Struct:
120    return PDB_UdtType::Struct;
121  case TypeRecordKind::Interface:
122    return PDB_UdtType::Interface;
123  default:
124    llvm_unreachable("Unexpected udt kind");
125  }
126}
127
128bool NativeTypeUDT::hasConstructor() const {
129  if (UnmodifiedType)
130    return UnmodifiedType->hasConstructor();
131
132  return (Tag->Options & ClassOptions::HasConstructorOrDestructor) !=
133         ClassOptions::None;
134}
135
136bool NativeTypeUDT::isConstType() const {
137  if (!Modifiers)
138    return false;
139  return (Modifiers->Modifiers & ModifierOptions::Const) !=
140         ModifierOptions::None;
141}
142
143bool NativeTypeUDT::hasAssignmentOperator() const {
144  if (UnmodifiedType)
145    return UnmodifiedType->hasAssignmentOperator();
146
147  return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) !=
148         ClassOptions::None;
149}
150
151bool NativeTypeUDT::hasCastOperator() const {
152  if (UnmodifiedType)
153    return UnmodifiedType->hasCastOperator();
154
155  return (Tag->Options & ClassOptions::HasConversionOperator) !=
156         ClassOptions::None;
157}
158
159bool NativeTypeUDT::hasNestedTypes() const {
160  if (UnmodifiedType)
161    return UnmodifiedType->hasNestedTypes();
162
163  return (Tag->Options & ClassOptions::ContainsNestedClass) !=
164         ClassOptions::None;
165}
166
167bool NativeTypeUDT::hasOverloadedOperator() const {
168  if (UnmodifiedType)
169    return UnmodifiedType->hasOverloadedOperator();
170
171  return (Tag->Options & ClassOptions::HasOverloadedOperator) !=
172         ClassOptions::None;
173}
174
175bool NativeTypeUDT::isInterfaceUdt() const { return false; }
176
177bool NativeTypeUDT::isIntrinsic() const {
178  if (UnmodifiedType)
179    return UnmodifiedType->isIntrinsic();
180
181  return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None;
182}
183
184bool NativeTypeUDT::isNested() const {
185  if (UnmodifiedType)
186    return UnmodifiedType->isNested();
187
188  return (Tag->Options & ClassOptions::Nested) != ClassOptions::None;
189}
190
191bool NativeTypeUDT::isPacked() const {
192  if (UnmodifiedType)
193    return UnmodifiedType->isPacked();
194
195  return (Tag->Options & ClassOptions::Packed) != ClassOptions::None;
196}
197
198bool NativeTypeUDT::isRefUdt() const { return false; }
199
200bool NativeTypeUDT::isScoped() const {
201  if (UnmodifiedType)
202    return UnmodifiedType->isScoped();
203
204  return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None;
205}
206
207bool NativeTypeUDT::isValueUdt() const { return false; }
208
209bool NativeTypeUDT::isUnalignedType() const {
210  if (!Modifiers)
211    return false;
212  return (Modifiers->Modifiers & ModifierOptions::Unaligned) !=
213         ModifierOptions::None;
214}
215
216bool NativeTypeUDT::isVolatileType() const {
217  if (!Modifiers)
218    return false;
219  return (Modifiers->Modifiers & ModifierOptions::Volatile) !=
220         ModifierOptions::None;
221}
222