LLVM  9.0.0svn
NativeTypeEnum.cpp
Go to the documentation of this file.
1 //===- NativeTypeEnum.cpp - info about enum 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 
10 
20 
22 
23 #include <cassert>
24 
25 using namespace llvm;
26 using namespace llvm::codeview;
27 using namespace llvm::pdb;
28 
29 namespace {
30 // Yea, this is a pretty terrible class name. But if we have an enum:
31 //
32 // enum Foo {
33 // A,
34 // B
35 // };
36 //
37 // then A and B are the "enumerators" of the "enum" Foo. And we need
38 // to enumerate them.
39 class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
40 public:
41  NativeEnumEnumEnumerators(NativeSession &Session,
42  const NativeTypeEnum &ClassParent);
43 
44  uint32_t getChildCount() const override;
45  std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
46  std::unique_ptr<PDBSymbol> getNext() override;
47  void reset() override;
48 
49 private:
51  EnumeratorRecord &Record) override;
53  ListContinuationRecord &Record) override;
54 
55  NativeSession &Session;
57  std::vector<EnumeratorRecord> Enumerators;
58  Optional<TypeIndex> ContinuationIndex;
59  uint32_t Index = 0;
60 };
61 } // namespace
62 
63 NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
64  NativeSession &Session, const NativeTypeEnum &ClassParent)
65  : Session(Session), ClassParent(ClassParent) {
66  TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
68 
69  ContinuationIndex = ClassParent.getEnumRecord().FieldList;
70  while (ContinuationIndex) {
71  CVType FieldList = Types.getType(*ContinuationIndex);
72  assert(FieldList.kind() == LF_FIELDLIST);
73  ContinuationIndex.reset();
74  cantFail(visitMemberRecordStream(FieldList.data(), *this));
75  }
76 }
77 
80  Enumerators.push_back(Record);
81  return Error::success();
82 }
83 
85  CVMemberRecord &CVM, ListContinuationRecord &Record) {
86  ContinuationIndex = Record.ContinuationIndex;
87  return Error::success();
88 }
89 
90 uint32_t NativeEnumEnumEnumerators::getChildCount() const {
91  return Enumerators.size();
92 }
93 
94 std::unique_ptr<PDBSymbol>
95 NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
96  if (Index >= getChildCount())
97  return nullptr;
98 
99  SymIndexId Id = Session.getSymbolCache()
101  ClassParent.getEnumRecord().FieldList, Index,
102  ClassParent, Enumerators[Index]);
103  return Session.getSymbolCache().getSymbolById(Id);
104 }
105 
106 std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
107  if (Index >= getChildCount())
108  return nullptr;
109 
110  return getChildAtIndex(Index++);
111 }
112 
113 void NativeEnumEnumEnumerators::reset() { Index = 0; }
114 
116  TypeIndex Index, EnumRecord Record)
117  : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
118  Record(std::move(Record)) {}
119 
122  codeview::ModifierRecord Modifier)
123  : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
124  UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
125 
127 
129  PdbSymbolIdField ShowIdFields,
130  PdbSymbolIdField RecurseIdFields) const {
131  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
132 
133  dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()),
134  Indent);
135  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
136  PdbSymbolIdField::LexicalParent, ShowIdFields,
137  RecurseIdFields);
138  dumpSymbolField(OS, "name", getName(), Indent);
139  dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
140  PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
141  if (Modifiers.hasValue())
142  dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
144  RecurseIdFields);
145  dumpSymbolField(OS, "length", getLength(), Indent);
146  dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
147  dumpSymbolField(OS, "constType", isConstType(), Indent);
148  dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
149  dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
150  dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
151  dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
152  dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
153  dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
154  dumpSymbolField(OS, "nested", isNested(), Indent);
155  dumpSymbolField(OS, "packed", isPacked(), Indent);
156  dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
157  dumpSymbolField(OS, "scoped", isScoped(), Indent);
158  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
159  dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
160  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
161 }
162 
163 std::unique_ptr<IPDBEnumSymbols>
165  if (Type != PDB_SymType::Data)
166  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
167 
168  const NativeTypeEnum *ClassParent = nullptr;
169  if (!Modifiers)
170  ClassParent = this;
171  else
172  ClassParent = UnmodifiedType;
173  return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent);
174 }
175 
177 
179  if (UnmodifiedType)
180  return UnmodifiedType->getBuiltinType();
181 
182  Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType());
183 
184  codeview::TypeIndex Underlying = Record->getUnderlyingType();
185 
186  // This indicates a corrupt record.
187  if (!Underlying.isSimple() ||
188  Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
189  return PDB_BuiltinType::None;
190  }
191 
192  switch (Underlying.getSimpleKind()) {
193  case SimpleTypeKind::Boolean128:
194  case SimpleTypeKind::Boolean64:
195  case SimpleTypeKind::Boolean32:
196  case SimpleTypeKind::Boolean16:
197  case SimpleTypeKind::Boolean8:
198  return PDB_BuiltinType::Bool;
199  case SimpleTypeKind::NarrowCharacter:
200  case SimpleTypeKind::UnsignedCharacter:
201  case SimpleTypeKind::SignedCharacter:
202  return PDB_BuiltinType::Char;
203  case SimpleTypeKind::WideCharacter:
205  case SimpleTypeKind::Character16:
207  case SimpleTypeKind::Character32:
209  case SimpleTypeKind::Int128:
210  case SimpleTypeKind::Int128Oct:
212  case SimpleTypeKind::Int16Short:
214  case SimpleTypeKind::Int32Long:
216  case SimpleTypeKind::Int64Quad:
217  return PDB_BuiltinType::Int;
218  case SimpleTypeKind::UInt128:
219  case SimpleTypeKind::UInt128Oct:
221  case SimpleTypeKind::UInt16Short:
223  case SimpleTypeKind::UInt32Long:
225  case SimpleTypeKind::UInt64Quad:
226  return PDB_BuiltinType::UInt;
229  case SimpleTypeKind::Complex16:
230  case SimpleTypeKind::Complex32:
231  case SimpleTypeKind::Complex32PartialPrecision:
232  case SimpleTypeKind::Complex64:
233  case SimpleTypeKind::Complex80:
234  case SimpleTypeKind::Complex128:
236  case SimpleTypeKind::Float16:
237  case SimpleTypeKind::Float32:
238  case SimpleTypeKind::Float32PartialPrecision:
239  case SimpleTypeKind::Float48:
240  case SimpleTypeKind::Float64:
241  case SimpleTypeKind::Float80:
242  case SimpleTypeKind::Float128:
243  return PDB_BuiltinType::Float;
244  default:
245  return PDB_BuiltinType::None;
246  }
247  llvm_unreachable("Unreachable");
248 }
249 
252 }
253 
255  if (UnmodifiedType)
256  return UnmodifiedType->hasConstructor();
257 
258  return bool(Record->getOptions() &
260 }
261 
263  if (UnmodifiedType)
265 
266  return bool(Record->getOptions() &
268 }
269 
271  if (UnmodifiedType)
272  return UnmodifiedType->hasNestedTypes();
273 
274  return bool(Record->getOptions() &
276 }
277 
279  if (UnmodifiedType)
280  return UnmodifiedType->isIntrinsic();
281 
282  return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
283 }
284 
286  if (UnmodifiedType)
288 
289  return bool(Record->getOptions() &
291 }
292 
293 uint64_t NativeTypeEnum::getLength() const {
294  if (UnmodifiedType)
295  return UnmodifiedType->getLength();
296 
297  const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
298  Record->getUnderlyingType());
299  const auto UnderlyingType =
301  return UnderlyingType ? UnderlyingType->getLength() : 0;
302 }
303 
304 std::string NativeTypeEnum::getName() const {
305  if (UnmodifiedType)
306  return UnmodifiedType->getName();
307 
308  return Record->getName();
309 }
310 
312  if (UnmodifiedType)
313  return UnmodifiedType->isNested();
314 
315  return bool(Record->getOptions() & codeview::ClassOptions::Nested);
316 }
317 
319  if (UnmodifiedType)
321 
322  return bool(Record->getOptions() &
324 }
325 
327  if (UnmodifiedType)
328  return UnmodifiedType->isPacked();
329 
330  return bool(Record->getOptions() & codeview::ClassOptions::Packed);
331 }
332 
334  if (UnmodifiedType)
335  return UnmodifiedType->isScoped();
336 
337  return bool(Record->getOptions() & codeview::ClassOptions::Scoped);
338 }
339 
341  if (UnmodifiedType)
342  return UnmodifiedType->getTypeId();
343 
344  return Session.getSymbolCache().findSymbolByTypeIndex(
345  Record->getUnderlyingType());
346 }
347 
348 bool NativeTypeEnum::isRefUdt() const { return false; }
349 
350 bool NativeTypeEnum::isValueUdt() const { return false; }
351 
352 bool NativeTypeEnum::isInterfaceUdt() const { return false; }
353 
355  if (!Modifiers)
356  return false;
357  return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
359 }
360 
362  if (!Modifiers)
363  return false;
364  return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
366 }
367 
369  if (!Modifiers)
370  return false;
371  return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
373 }
374 
376  if (UnmodifiedType)
378 
380  getTypeId());
381 }
bool isVolatileType() const override
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:703
Kind kind() const
Definition: CVRecord.h:36
This class represents lattice values for constants.
Definition: AllocatorList.h:23
std::string getName() const override
SimpleTypeKind getSimpleKind() const
Definition: TypeIndex.h:126
NativeTypeEnum(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, codeview::EnumRecord Record)
codeview::LazyRandomTypeCollection & typeCollection()
Definition: TpiStream.h:58
const codeview::EnumRecord & getEnumRecord() const
NativeTypeEnum * UnmodifiedType
Error visitMemberRecordStream(ArrayRef< uint8_t > FieldList, TypeVisitorCallbacks &Callbacks)
bool hasConstructor() const override
void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, PdbSymbolIdField RecurseIdFields) const override
const NativeTypeBuiltin & getUnderlyingBuiltinType() const
Expected< TpiStream & > getPDBTpiStream()
Definition: PDBFile.cpp:299
PDB_SymType getSymTag() const override
PDB_BuiltinType getBuiltinType() const override
SimpleTypeMode getSimpleMode() const
Definition: TypeIndex.h:131
SymIndexId getUnmodifiedTypeId() const override
SymIndexId getTypeId() const override
Definition: BitVector.h:937
std::unique_ptr< PDBSymbol > getSymbolById(SymIndexId SymbolId) const
Optional< codeview::ModifierRecord > Modifiers
void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, PdbSymbolIdField RecurseIdFields) const override
A 32-bit type reference.
Definition: TypeIndex.h:95
bool isScoped() const override
ArrayRef< uint8_t > data() const
Definition: CVRecord.h:37
std::unique_ptr< IPDBEnumSymbols > findChildren(PDB_SymType Type) const override
PDB_SymType
These values correspond to the SymTagEnum enumeration, and are documented here: https://msdn.microsoft.com/en-us/library/bkedss5f.aspx.
Definition: PDBTypes.h:182
SymIndexId getSymIndexId() const override
bool isInterfaceUdt() const override
bool isConstType() const override
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
Definition: TypeRecord.h:920
void dumpSymbolField(raw_ostream &OS, StringRef Name, T Value, int Indent)
Definition: PDBExtras.h:48
std::underlying_type< E >::type Underlying(E Val)
Check that Val is in range for E, and return Val cast to E&#39;s underlying type.
Definition: BitmaskEnum.h:90
void dumpSymbolIdField(raw_ostream &OS, StringRef Name, SymIndexId Value, int Indent, const IPDBSession &Session, PdbSymbolIdField FieldId, PdbSymbolIdField ShowFlags, PdbSymbolIdField RecurseFlags)
Definition: PDBSymbol.cpp:185
std::unique_ptr< T > getConcreteSymbolById(SymIndexId SymbolId) const
Definition: IPDBSession.h:41
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
bool isValueUdt() const override
bool hasAssignmentOperator() const override
bool isNested() const override
bool hasNestedTypes() const override
bool hasOverloadedOperator() const override
NativeRawSymbol & getNativeSymbolById(SymIndexId SymbolId) const
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI)
bool hasCastOperator() const override
SymbolCache & getSymbolCache()
PDB_BuiltinType
These values correspond to the Basictype enumeration, and are documented here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx.
Definition: PDBTypes.h:274
bool isPacked() const override
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Definition: JSON.cpp:597
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
uint64_t getLength() const override
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
bool isIntrinsic() const override
bool isRefUdt() const override
bool isUnalignedType() const override
Provides amortized O(1) random access to a CodeView type stream.
SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI, uint32_t Index, Args &&... ConstructorArgs)
Definition: SymbolCache.h:115