Line data Source code
1 : //===- NativeTypeEnum.cpp - info about enum type ----------------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
11 :
12 : #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
13 : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
14 : #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
15 : #include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
16 : #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
17 : #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
18 : #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
19 : #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
20 : #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
21 :
22 : #include "llvm/Support/FormatVariadic.h"
23 :
24 : #include <cassert>
25 :
26 : using namespace llvm;
27 : using namespace llvm::codeview;
28 : using namespace llvm::pdb;
29 :
30 : namespace {
31 : // Yea, this is a pretty terrible class name. But if we have an enum:
32 : //
33 : // enum Foo {
34 : // A,
35 : // B
36 : // };
37 : //
38 : // then A and B are the "enumerators" of the "enum" Foo. And we need
39 : // to enumerate them.
40 0 : class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
41 : public:
42 : NativeEnumEnumEnumerators(NativeSession &Session,
43 : const NativeTypeEnum &ClassParent);
44 :
45 : uint32_t getChildCount() const override;
46 : std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
47 : std::unique_ptr<PDBSymbol> getNext() override;
48 : void reset() override;
49 :
50 : private:
51 : Error visitKnownMember(CVMemberRecord &CVM,
52 : EnumeratorRecord &Record) override;
53 : Error visitKnownMember(CVMemberRecord &CVM,
54 : ListContinuationRecord &Record) override;
55 :
56 : NativeSession &Session;
57 : const NativeTypeEnum &ClassParent;
58 : std::vector<EnumeratorRecord> Enumerators;
59 : Optional<TypeIndex> ContinuationIndex;
60 : uint32_t Index = 0;
61 : };
62 : } // namespace
63 :
64 45 : NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
65 45 : NativeSession &Session, const NativeTypeEnum &ClassParent)
66 90 : : Session(Session), ClassParent(ClassParent) {
67 90 : TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
68 : LazyRandomTypeCollection &Types = Tpi.typeCollection();
69 :
70 45 : ContinuationIndex = ClassParent.getEnumRecord().FieldList;
71 90 : while (ContinuationIndex) {
72 90 : CVType FieldList = Types.getType(*ContinuationIndex);
73 : assert(FieldList.kind() == LF_FIELDLIST);
74 : ContinuationIndex.reset();
75 90 : cantFail(visitMemberRecordStream(FieldList.data(), *this));
76 : }
77 45 : }
78 :
79 178 : Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
80 : EnumeratorRecord &Record) {
81 178 : Enumerators.push_back(Record);
82 178 : return Error::success();
83 : }
84 :
85 0 : Error NativeEnumEnumEnumerators::visitKnownMember(
86 : CVMemberRecord &CVM, ListContinuationRecord &Record) {
87 0 : ContinuationIndex = Record.ContinuationIndex;
88 0 : return Error::success();
89 : }
90 :
91 22 : uint32_t NativeEnumEnumEnumerators::getChildCount() const {
92 846 : return Enumerators.size();
93 : }
94 :
95 : std::unique_ptr<PDBSymbol>
96 178 : NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
97 178 : if (Index >= getChildCount())
98 : return nullptr;
99 :
100 356 : SymIndexId Id = Session.getSymbolCache()
101 356 : .getOrCreateFieldListMember<NativeSymbolEnumerator>(
102 : ClassParent.getEnumRecord().FieldList, Index,
103 178 : ClassParent, Enumerators[Index]);
104 356 : return Session.getSymbolCache().getSymbolById(Id);
105 : }
106 :
107 223 : std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
108 446 : if (Index >= getChildCount())
109 : return nullptr;
110 :
111 178 : return getChildAtIndex(Index++);
112 : }
113 :
114 0 : void NativeEnumEnumEnumerators::reset() { Index = 0; }
115 :
116 50 : NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
117 50 : TypeIndex Index, EnumRecord Record)
118 : : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
119 50 : Record(std::move(Record)) {}
120 :
121 2 : NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
122 : NativeTypeEnum &UnmodifiedType,
123 2 : codeview::ModifierRecord Modifier)
124 : : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
125 2 : UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
126 :
127 104 : NativeTypeEnum::~NativeTypeEnum() {}
128 :
129 23 : void NativeTypeEnum::dump(raw_ostream &OS, int Indent,
130 : PdbSymbolIdField ShowIdFields,
131 : PdbSymbolIdField RecurseIdFields) const {
132 23 : NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
133 :
134 23 : dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()),
135 : Indent);
136 46 : dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
137 : PdbSymbolIdField::LexicalParent, ShowIdFields,
138 : RecurseIdFields);
139 23 : dumpSymbolField(OS, "name", getName(), Indent);
140 23 : dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
141 : PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
142 23 : if (Modifiers.hasValue())
143 1 : dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
144 1 : Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
145 : RecurseIdFields);
146 23 : dumpSymbolField(OS, "length", getLength(), Indent);
147 23 : dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
148 23 : dumpSymbolField(OS, "constType", isConstType(), Indent);
149 23 : dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
150 23 : dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
151 23 : dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
152 23 : dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
153 23 : dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
154 23 : dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
155 23 : dumpSymbolField(OS, "nested", isNested(), Indent);
156 23 : dumpSymbolField(OS, "packed", isPacked(), Indent);
157 23 : dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
158 23 : dumpSymbolField(OS, "scoped", isScoped(), Indent);
159 23 : dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
160 23 : dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
161 23 : dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
162 23 : }
163 :
164 : std::unique_ptr<IPDBEnumSymbols>
165 45 : NativeTypeEnum::findChildren(PDB_SymType Type) const {
166 45 : if (Type != PDB_SymType::Data)
167 : return llvm::make_unique<NullEnumerator<PDBSymbol>>();
168 :
169 : const NativeTypeEnum *ClassParent = nullptr;
170 45 : if (!Modifiers)
171 : ClassParent = this;
172 : else
173 1 : ClassParent = UnmodifiedType;
174 45 : return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent);
175 : }
176 :
177 110 : PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
178 :
179 24 : PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
180 24 : if (UnmodifiedType)
181 1 : return UnmodifiedType->getBuiltinType();
182 :
183 46 : Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType());
184 :
185 23 : codeview::TypeIndex Underlying = Record->getUnderlyingType();
186 :
187 : // This indicates a corrupt record.
188 23 : if (!Underlying.isSimple() ||
189 : Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
190 : return PDB_BuiltinType::None;
191 : }
192 :
193 : switch (Underlying.getSimpleKind()) {
194 : case SimpleTypeKind::Boolean128:
195 : case SimpleTypeKind::Boolean64:
196 : case SimpleTypeKind::Boolean32:
197 : case SimpleTypeKind::Boolean16:
198 : case SimpleTypeKind::Boolean8:
199 : return PDB_BuiltinType::Bool;
200 : case SimpleTypeKind::NarrowCharacter:
201 : case SimpleTypeKind::UnsignedCharacter:
202 : case SimpleTypeKind::SignedCharacter:
203 : return PDB_BuiltinType::Char;
204 : case SimpleTypeKind::WideCharacter:
205 : return PDB_BuiltinType::WCharT;
206 : case SimpleTypeKind::Character16:
207 : return PDB_BuiltinType::Char16;
208 : case SimpleTypeKind::Character32:
209 : return PDB_BuiltinType::Char32;
210 : case SimpleTypeKind::Int128:
211 : case SimpleTypeKind::Int128Oct:
212 : case SimpleTypeKind::Int16:
213 : case SimpleTypeKind::Int16Short:
214 : case SimpleTypeKind::Int32:
215 : case SimpleTypeKind::Int32Long:
216 : case SimpleTypeKind::Int64:
217 : case SimpleTypeKind::Int64Quad:
218 : return PDB_BuiltinType::Int;
219 : case SimpleTypeKind::UInt128:
220 : case SimpleTypeKind::UInt128Oct:
221 : case SimpleTypeKind::UInt16:
222 : case SimpleTypeKind::UInt16Short:
223 : case SimpleTypeKind::UInt32:
224 : case SimpleTypeKind::UInt32Long:
225 : case SimpleTypeKind::UInt64:
226 : case SimpleTypeKind::UInt64Quad:
227 : return PDB_BuiltinType::UInt;
228 : case SimpleTypeKind::HResult:
229 : return PDB_BuiltinType::HResult;
230 : case SimpleTypeKind::Complex16:
231 : case SimpleTypeKind::Complex32:
232 : case SimpleTypeKind::Complex32PartialPrecision:
233 : case SimpleTypeKind::Complex64:
234 : case SimpleTypeKind::Complex80:
235 : case SimpleTypeKind::Complex128:
236 : return PDB_BuiltinType::Complex;
237 : case SimpleTypeKind::Float16:
238 : case SimpleTypeKind::Float32:
239 : case SimpleTypeKind::Float32PartialPrecision:
240 : case SimpleTypeKind::Float48:
241 : case SimpleTypeKind::Float64:
242 : case SimpleTypeKind::Float80:
243 : case SimpleTypeKind::Float128:
244 : return PDB_BuiltinType::Float;
245 : default:
246 : return PDB_BuiltinType::None;
247 : }
248 : llvm_unreachable("Unreachable");
249 : }
250 :
251 24 : SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
252 24 : return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0;
253 : }
254 :
255 24 : bool NativeTypeEnum::hasConstructor() const {
256 24 : if (UnmodifiedType)
257 1 : return UnmodifiedType->hasConstructor();
258 :
259 23 : return bool(Record->getOptions() &
260 23 : codeview::ClassOptions::HasConstructorOrDestructor);
261 : }
262 :
263 24 : bool NativeTypeEnum::hasAssignmentOperator() const {
264 24 : if (UnmodifiedType)
265 1 : return UnmodifiedType->hasAssignmentOperator();
266 :
267 23 : return bool(Record->getOptions() &
268 23 : codeview::ClassOptions::HasOverloadedAssignmentOperator);
269 : }
270 :
271 24 : bool NativeTypeEnum::hasNestedTypes() const {
272 24 : if (UnmodifiedType)
273 1 : return UnmodifiedType->hasNestedTypes();
274 :
275 23 : return bool(Record->getOptions() &
276 23 : codeview::ClassOptions::ContainsNestedClass);
277 : }
278 :
279 24 : bool NativeTypeEnum::isIntrinsic() const {
280 24 : if (UnmodifiedType)
281 1 : return UnmodifiedType->isIntrinsic();
282 :
283 46 : return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
284 : }
285 :
286 24 : bool NativeTypeEnum::hasCastOperator() const {
287 24 : if (UnmodifiedType)
288 1 : return UnmodifiedType->hasCastOperator();
289 :
290 23 : return bool(Record->getOptions() &
291 23 : codeview::ClassOptions::HasConversionOperator);
292 : }
293 :
294 48 : uint64_t NativeTypeEnum::getLength() const {
295 48 : if (UnmodifiedType)
296 2 : return UnmodifiedType->getLength();
297 :
298 92 : const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
299 : Record->getUnderlyingType());
300 : const auto UnderlyingType =
301 46 : Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
302 46 : return UnderlyingType ? UnderlyingType->getLength() : 0;
303 : }
304 :
305 80 : std::string NativeTypeEnum::getName() const {
306 80 : if (UnmodifiedType)
307 3 : return UnmodifiedType->getName();
308 :
309 : return Record->getName();
310 : }
311 :
312 24 : bool NativeTypeEnum::isNested() const {
313 24 : if (UnmodifiedType)
314 1 : return UnmodifiedType->isNested();
315 :
316 46 : return bool(Record->getOptions() & codeview::ClassOptions::Nested);
317 : }
318 :
319 24 : bool NativeTypeEnum::hasOverloadedOperator() const {
320 24 : if (UnmodifiedType)
321 1 : return UnmodifiedType->hasOverloadedOperator();
322 :
323 23 : return bool(Record->getOptions() &
324 23 : codeview::ClassOptions::HasOverloadedOperator);
325 : }
326 :
327 24 : bool NativeTypeEnum::isPacked() const {
328 24 : if (UnmodifiedType)
329 1 : return UnmodifiedType->isPacked();
330 :
331 46 : return bool(Record->getOptions() & codeview::ClassOptions::Packed);
332 : }
333 :
334 24 : bool NativeTypeEnum::isScoped() const {
335 24 : if (UnmodifiedType)
336 1 : return UnmodifiedType->isScoped();
337 :
338 46 : return bool(Record->getOptions() & codeview::ClassOptions::Scoped);
339 : }
340 :
341 314 : SymIndexId NativeTypeEnum::getTypeId() const {
342 314 : if (UnmodifiedType)
343 1 : return UnmodifiedType->getTypeId();
344 :
345 626 : return Session.getSymbolCache().findSymbolByTypeIndex(
346 313 : Record->getUnderlyingType());
347 : }
348 :
349 23 : bool NativeTypeEnum::isRefUdt() const { return false; }
350 :
351 23 : bool NativeTypeEnum::isValueUdt() const { return false; }
352 :
353 23 : bool NativeTypeEnum::isInterfaceUdt() const { return false; }
354 :
355 24 : bool NativeTypeEnum::isConstType() const {
356 24 : if (!Modifiers)
357 : return false;
358 2 : return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
359 2 : ModifierOptions::None);
360 : }
361 :
362 24 : bool NativeTypeEnum::isVolatileType() const {
363 24 : if (!Modifiers)
364 : return false;
365 2 : return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
366 2 : ModifierOptions::None);
367 : }
368 :
369 24 : bool NativeTypeEnum::isUnalignedType() const {
370 24 : if (!Modifiers)
371 : return false;
372 2 : return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
373 2 : ModifierOptions::None);
374 : }
375 :
376 178 : const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
377 178 : if (UnmodifiedType)
378 : return UnmodifiedType->getUnderlyingBuiltinType();
379 :
380 178 : return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
381 178 : getTypeId());
382 : }
|