OSDN Git Service

[PDB] Better support for enumerating pointer types.
[android-x86/external-llvm.git] / 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                             const codeview::EnumRecord &CVEnum);
45
46   uint32_t getChildCount() const override;
47   std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
48   std::unique_ptr<PDBSymbol> getNext() override;
49   void reset() override;
50
51 private:
52   Error visitKnownMember(CVMemberRecord &CVM,
53                          EnumeratorRecord &Record) override;
54   Error visitKnownMember(CVMemberRecord &CVM,
55                          ListContinuationRecord &Record) override;
56
57   NativeSession &Session;
58   const NativeTypeEnum &ClassParent;
59   const codeview::EnumRecord &CVEnum;
60   std::vector<EnumeratorRecord> Enumerators;
61   Optional<TypeIndex> ContinuationIndex;
62   uint32_t Index = 0;
63 };
64 } // namespace
65
66 NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
67     NativeSession &Session, const NativeTypeEnum &ClassParent,
68     const codeview::EnumRecord &CVEnum)
69     : Session(Session), ClassParent(ClassParent), CVEnum(CVEnum) {
70   TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
71   LazyRandomTypeCollection &Types = Tpi.typeCollection();
72
73   ContinuationIndex = CVEnum.FieldList;
74   while (ContinuationIndex) {
75     CVType FieldList = Types.getType(*ContinuationIndex);
76     assert(FieldList.kind() == LF_FIELDLIST);
77     ContinuationIndex.reset();
78     cantFail(visitMemberRecordStream(FieldList.data(), *this));
79   }
80 }
81
82 Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
83                                                   EnumeratorRecord &Record) {
84   Enumerators.push_back(Record);
85   return Error::success();
86 }
87
88 Error NativeEnumEnumEnumerators::visitKnownMember(
89     CVMemberRecord &CVM, ListContinuationRecord &Record) {
90   ContinuationIndex = Record.ContinuationIndex;
91   return Error::success();
92 }
93
94 uint32_t NativeEnumEnumEnumerators::getChildCount() const {
95   return Enumerators.size();
96 }
97
98 std::unique_ptr<PDBSymbol>
99 NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
100   if (Index >= getChildCount())
101     return nullptr;
102
103   SymIndexId Id =
104       Session.getSymbolCache()
105           .getOrCreateFieldListMember<NativeSymbolEnumerator>(
106               CVEnum.FieldList, Index, ClassParent, Enumerators[Index]);
107   return Session.getSymbolCache().getSymbolById(Id);
108 }
109
110 std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
111   if (Index >= getChildCount())
112     return nullptr;
113
114   return getChildAtIndex(Index++);
115 }
116
117 void NativeEnumEnumEnumerators::reset() { Index = 0; }
118
119 NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
120                                TypeIndex Index, EnumRecord Record)
121     : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
122       Record(std::move(Record)) {}
123
124 NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
125                                codeview::TypeIndex ModifierTI,
126                                codeview::ModifierRecord Modifier,
127                                codeview::EnumRecord EnumRecord)
128     : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(ModifierTI),
129       Record(std::move(EnumRecord)), Modifiers(std::move(Modifier)) {}
130
131 NativeTypeEnum::~NativeTypeEnum() {}
132
133 void NativeTypeEnum::dump(raw_ostream &OS, int Indent,
134                           PdbSymbolIdField ShowIdFields,
135                           PdbSymbolIdField RecurseIdFields) const {
136   NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
137
138   dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()),
139                   Indent);
140   dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
141                     PdbSymbolIdField::LexicalParent, ShowIdFields,
142                     RecurseIdFields);
143   dumpSymbolField(OS, "name", getName(), Indent);
144   dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
145                     PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
146   if (Modifiers.hasValue())
147     dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
148                       Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
149                       RecurseIdFields);
150   dumpSymbolField(OS, "length", getLength(), Indent);
151   dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
152   dumpSymbolField(OS, "constType", isConstType(), Indent);
153   dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
154   dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
155   dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
156   dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
157   dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
158   dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
159   dumpSymbolField(OS, "nested", isNested(), Indent);
160   dumpSymbolField(OS, "packed", isPacked(), Indent);
161   dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
162   dumpSymbolField(OS, "scoped", isScoped(), Indent);
163   dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
164   dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
165   dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
166 }
167
168 std::unique_ptr<IPDBEnumSymbols>
169 NativeTypeEnum::findChildren(PDB_SymType Type) const {
170   if (Type != PDB_SymType::Data)
171     return llvm::make_unique<NullEnumerator<PDBSymbol>>();
172
173   const NativeTypeEnum *ClassParent = nullptr;
174   if (!Modifiers)
175     ClassParent = this;
176   else {
177     NativeRawSymbol &NRS =
178         Session.getSymbolCache().getNativeSymbolById(getUnmodifiedTypeId());
179     assert(NRS.getSymTag() == PDB_SymType::Enum);
180     ClassParent = static_cast<NativeTypeEnum *>(&NRS);
181   }
182   return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent,
183                                                       Record);
184 }
185
186 PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
187
188 PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
189   Session.getSymbolCache().findSymbolByTypeIndex(Record.getUnderlyingType());
190
191   codeview::TypeIndex Underlying = Record.getUnderlyingType();
192
193   // This indicates a corrupt record.
194   if (!Underlying.isSimple() ||
195       Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
196     return PDB_BuiltinType::None;
197   }
198
199   switch (Underlying.getSimpleKind()) {
200   case SimpleTypeKind::Boolean128:
201   case SimpleTypeKind::Boolean64:
202   case SimpleTypeKind::Boolean32:
203   case SimpleTypeKind::Boolean16:
204   case SimpleTypeKind::Boolean8:
205     return PDB_BuiltinType::Bool;
206   case SimpleTypeKind::NarrowCharacter:
207   case SimpleTypeKind::UnsignedCharacter:
208   case SimpleTypeKind::SignedCharacter:
209     return PDB_BuiltinType::Char;
210   case SimpleTypeKind::WideCharacter:
211     return PDB_BuiltinType::WCharT;
212   case SimpleTypeKind::Character16:
213     return PDB_BuiltinType::Char16;
214   case SimpleTypeKind::Character32:
215     return PDB_BuiltinType::Char32;
216   case SimpleTypeKind::Int128:
217   case SimpleTypeKind::Int128Oct:
218   case SimpleTypeKind::Int16:
219   case SimpleTypeKind::Int16Short:
220   case SimpleTypeKind::Int32:
221   case SimpleTypeKind::Int32Long:
222   case SimpleTypeKind::Int64:
223   case SimpleTypeKind::Int64Quad:
224     return PDB_BuiltinType::Int;
225   case SimpleTypeKind::UInt128:
226   case SimpleTypeKind::UInt128Oct:
227   case SimpleTypeKind::UInt16:
228   case SimpleTypeKind::UInt16Short:
229   case SimpleTypeKind::UInt32:
230   case SimpleTypeKind::UInt32Long:
231   case SimpleTypeKind::UInt64:
232   case SimpleTypeKind::UInt64Quad:
233     return PDB_BuiltinType::UInt;
234   case SimpleTypeKind::HResult:
235     return PDB_BuiltinType::HResult;
236   case SimpleTypeKind::Complex16:
237   case SimpleTypeKind::Complex32:
238   case SimpleTypeKind::Complex32PartialPrecision:
239   case SimpleTypeKind::Complex64:
240   case SimpleTypeKind::Complex80:
241   case SimpleTypeKind::Complex128:
242     return PDB_BuiltinType::Complex;
243   case SimpleTypeKind::Float16:
244   case SimpleTypeKind::Float32:
245   case SimpleTypeKind::Float32PartialPrecision:
246   case SimpleTypeKind::Float48:
247   case SimpleTypeKind::Float64:
248   case SimpleTypeKind::Float80:
249   case SimpleTypeKind::Float128:
250     return PDB_BuiltinType::Float;
251   default:
252     return PDB_BuiltinType::None;
253   }
254   llvm_unreachable("Unreachable");
255 }
256
257 SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
258   if (!Modifiers)
259     return 0;
260
261   return Session.getSymbolCache().findSymbolByTypeIndex(
262       Modifiers->ModifiedType);
263 }
264
265 bool NativeTypeEnum::hasConstructor() const {
266   return bool(Record.getOptions() &
267               codeview::ClassOptions::HasConstructorOrDestructor);
268 }
269
270 bool NativeTypeEnum::hasAssignmentOperator() const {
271   return bool(Record.getOptions() &
272               codeview::ClassOptions::HasOverloadedAssignmentOperator);
273 }
274
275 bool NativeTypeEnum::hasNestedTypes() const {
276   return bool(Record.getOptions() &
277               codeview::ClassOptions::ContainsNestedClass);
278 }
279
280 bool NativeTypeEnum::isIntrinsic() const {
281   return bool(Record.getOptions() & codeview::ClassOptions::Intrinsic);
282 }
283
284 bool NativeTypeEnum::hasCastOperator() const {
285   return bool(Record.getOptions() &
286               codeview::ClassOptions::HasConversionOperator);
287 }
288
289 uint64_t NativeTypeEnum::getLength() const {
290   const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
291       Record.getUnderlyingType());
292   const auto UnderlyingType =
293       Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
294   return UnderlyingType ? UnderlyingType->getLength() : 0;
295 }
296
297 std::string NativeTypeEnum::getName() const { return Record.getName(); }
298
299 bool NativeTypeEnum::isNested() const {
300   return bool(Record.getOptions() & codeview::ClassOptions::Nested);
301 }
302
303 bool NativeTypeEnum::hasOverloadedOperator() const {
304   return bool(Record.getOptions() &
305               codeview::ClassOptions::HasOverloadedOperator);
306 }
307
308 bool NativeTypeEnum::isPacked() const {
309   return bool(Record.getOptions() & codeview::ClassOptions::Packed);
310 }
311
312 bool NativeTypeEnum::isScoped() const {
313   return bool(Record.getOptions() & codeview::ClassOptions::Scoped);
314 }
315
316 SymIndexId NativeTypeEnum::getTypeId() const {
317   return Session.getSymbolCache().findSymbolByTypeIndex(
318       Record.getUnderlyingType());
319 }
320
321 bool NativeTypeEnum::isRefUdt() const { return false; }
322
323 bool NativeTypeEnum::isValueUdt() const { return false; }
324
325 bool NativeTypeEnum::isInterfaceUdt() const { return false; }
326
327 bool NativeTypeEnum::isConstType() const {
328   if (!Modifiers)
329     return false;
330   return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
331           ModifierOptions::None);
332 }
333
334 bool NativeTypeEnum::isVolatileType() const {
335   if (!Modifiers)
336     return false;
337   return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
338           ModifierOptions::None);
339 }
340
341 bool NativeTypeEnum::isUnalignedType() const {
342   if (!Modifiers)
343     return false;
344   return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
345           ModifierOptions::None);
346 }
347
348 const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
349   return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
350       getTypeId());
351 }