]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
MFV r350080:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / PDB / Native / NativeTypeEnum.cpp
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 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 NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
65     NativeSession &Session, const NativeTypeEnum &ClassParent)
66     : Session(Session), ClassParent(ClassParent) {
67   TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
68   LazyRandomTypeCollection &Types = Tpi.typeCollection();
69
70   ContinuationIndex = ClassParent.getEnumRecord().FieldList;
71   while (ContinuationIndex) {
72     CVType FieldList = Types.getType(*ContinuationIndex);
73     assert(FieldList.kind() == LF_FIELDLIST);
74     ContinuationIndex.reset();
75     cantFail(visitMemberRecordStream(FieldList.data(), *this));
76   }
77 }
78
79 Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
80                                                   EnumeratorRecord &Record) {
81   Enumerators.push_back(Record);
82   return Error::success();
83 }
84
85 Error NativeEnumEnumEnumerators::visitKnownMember(
86     CVMemberRecord &CVM, ListContinuationRecord &Record) {
87   ContinuationIndex = Record.ContinuationIndex;
88   return Error::success();
89 }
90
91 uint32_t NativeEnumEnumEnumerators::getChildCount() const {
92   return Enumerators.size();
93 }
94
95 std::unique_ptr<PDBSymbol>
96 NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
97   if (Index >= getChildCount())
98     return nullptr;
99
100   SymIndexId Id = Session.getSymbolCache()
101                       .getOrCreateFieldListMember<NativeSymbolEnumerator>(
102                           ClassParent.getEnumRecord().FieldList, Index,
103                           ClassParent, Enumerators[Index]);
104   return Session.getSymbolCache().getSymbolById(Id);
105 }
106
107 std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
108   if (Index >= getChildCount())
109     return nullptr;
110
111   return getChildAtIndex(Index++);
112 }
113
114 void NativeEnumEnumEnumerators::reset() { Index = 0; }
115
116 NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
117                                TypeIndex Index, EnumRecord Record)
118     : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
119       Record(std::move(Record)) {}
120
121 NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
122                                NativeTypeEnum &UnmodifiedType,
123                                codeview::ModifierRecord Modifier)
124     : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
125       UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
126
127 NativeTypeEnum::~NativeTypeEnum() {}
128
129 void NativeTypeEnum::dump(raw_ostream &OS, int Indent,
130                           PdbSymbolIdField ShowIdFields,
131                           PdbSymbolIdField RecurseIdFields) const {
132   NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
133
134   dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()),
135                   Indent);
136   dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
137                     PdbSymbolIdField::LexicalParent, ShowIdFields,
138                     RecurseIdFields);
139   dumpSymbolField(OS, "name", getName(), Indent);
140   dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
141                     PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
142   if (Modifiers.hasValue())
143     dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
144                       Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
145                       RecurseIdFields);
146   dumpSymbolField(OS, "length", getLength(), Indent);
147   dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
148   dumpSymbolField(OS, "constType", isConstType(), Indent);
149   dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
150   dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
151   dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
152   dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
153   dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
154   dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
155   dumpSymbolField(OS, "nested", isNested(), Indent);
156   dumpSymbolField(OS, "packed", isPacked(), Indent);
157   dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
158   dumpSymbolField(OS, "scoped", isScoped(), Indent);
159   dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
160   dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
161   dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
162 }
163
164 std::unique_ptr<IPDBEnumSymbols>
165 NativeTypeEnum::findChildren(PDB_SymType Type) const {
166   if (Type != PDB_SymType::Data)
167     return llvm::make_unique<NullEnumerator<PDBSymbol>>();
168
169   const NativeTypeEnum *ClassParent = nullptr;
170   if (!Modifiers)
171     ClassParent = this;
172   else
173     ClassParent = UnmodifiedType;
174   return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent);
175 }
176
177 PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
178
179 PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
180   if (UnmodifiedType)
181     return UnmodifiedType->getBuiltinType();
182
183   Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType());
184
185   codeview::TypeIndex Underlying = Record->getUnderlyingType();
186
187   // This indicates a corrupt record.
188   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 SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
252   return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0;
253 }
254
255 bool NativeTypeEnum::hasConstructor() const {
256   if (UnmodifiedType)
257     return UnmodifiedType->hasConstructor();
258
259   return bool(Record->getOptions() &
260               codeview::ClassOptions::HasConstructorOrDestructor);
261 }
262
263 bool NativeTypeEnum::hasAssignmentOperator() const {
264   if (UnmodifiedType)
265     return UnmodifiedType->hasAssignmentOperator();
266
267   return bool(Record->getOptions() &
268               codeview::ClassOptions::HasOverloadedAssignmentOperator);
269 }
270
271 bool NativeTypeEnum::hasNestedTypes() const {
272   if (UnmodifiedType)
273     return UnmodifiedType->hasNestedTypes();
274
275   return bool(Record->getOptions() &
276               codeview::ClassOptions::ContainsNestedClass);
277 }
278
279 bool NativeTypeEnum::isIntrinsic() const {
280   if (UnmodifiedType)
281     return UnmodifiedType->isIntrinsic();
282
283   return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
284 }
285
286 bool NativeTypeEnum::hasCastOperator() const {
287   if (UnmodifiedType)
288     return UnmodifiedType->hasCastOperator();
289
290   return bool(Record->getOptions() &
291               codeview::ClassOptions::HasConversionOperator);
292 }
293
294 uint64_t NativeTypeEnum::getLength() const {
295   if (UnmodifiedType)
296     return UnmodifiedType->getLength();
297
298   const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
299       Record->getUnderlyingType());
300   const auto UnderlyingType =
301       Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
302   return UnderlyingType ? UnderlyingType->getLength() : 0;
303 }
304
305 std::string NativeTypeEnum::getName() const {
306   if (UnmodifiedType)
307     return UnmodifiedType->getName();
308
309   return Record->getName();
310 }
311
312 bool NativeTypeEnum::isNested() const {
313   if (UnmodifiedType)
314     return UnmodifiedType->isNested();
315
316   return bool(Record->getOptions() & codeview::ClassOptions::Nested);
317 }
318
319 bool NativeTypeEnum::hasOverloadedOperator() const {
320   if (UnmodifiedType)
321     return UnmodifiedType->hasOverloadedOperator();
322
323   return bool(Record->getOptions() &
324               codeview::ClassOptions::HasOverloadedOperator);
325 }
326
327 bool NativeTypeEnum::isPacked() const {
328   if (UnmodifiedType)
329     return UnmodifiedType->isPacked();
330
331   return bool(Record->getOptions() & codeview::ClassOptions::Packed);
332 }
333
334 bool NativeTypeEnum::isScoped() const {
335   if (UnmodifiedType)
336     return UnmodifiedType->isScoped();
337
338   return bool(Record->getOptions() & codeview::ClassOptions::Scoped);
339 }
340
341 SymIndexId NativeTypeEnum::getTypeId() const {
342   if (UnmodifiedType)
343     return UnmodifiedType->getTypeId();
344
345   return Session.getSymbolCache().findSymbolByTypeIndex(
346       Record->getUnderlyingType());
347 }
348
349 bool NativeTypeEnum::isRefUdt() const { return false; }
350
351 bool NativeTypeEnum::isValueUdt() const { return false; }
352
353 bool NativeTypeEnum::isInterfaceUdt() const { return false; }
354
355 bool NativeTypeEnum::isConstType() const {
356   if (!Modifiers)
357     return false;
358   return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
359           ModifierOptions::None);
360 }
361
362 bool NativeTypeEnum::isVolatileType() const {
363   if (!Modifiers)
364     return false;
365   return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
366           ModifierOptions::None);
367 }
368
369 bool NativeTypeEnum::isUnalignedType() const {
370   if (!Modifiers)
371     return false;
372   return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
373           ModifierOptions::None);
374 }
375
376 const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
377   if (UnmodifiedType)
378     return UnmodifiedType->getUnderlyingBuiltinType();
379
380   return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
381       getTypeId());
382 }