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