LLVM  8.0.1
NativeTypeEnum.cpp
Go to the documentation of this file.
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 
11 
21 
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:
52  EnumeratorRecord &Record) override;
54  ListContinuationRecord &Record) override;
55 
56  NativeSession &Session;
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());
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 
81  Enumerators.push_back(Record);
82  return Error::success();
83 }
84 
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()
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 
117  TypeIndex Index, EnumRecord Record)
118  : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
119  Record(std::move(Record)) {}
120 
123  codeview::ModifierRecord Modifier)
124  : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
125  UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
126 
128 
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,
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>
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 
178 
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:
206  case SimpleTypeKind::Character16:
208  case SimpleTypeKind::Character32:
210  case SimpleTypeKind::Int128:
211  case SimpleTypeKind::Int128Oct:
213  case SimpleTypeKind::Int16Short:
215  case SimpleTypeKind::Int32Long:
217  case SimpleTypeKind::Int64Quad:
218  return PDB_BuiltinType::Int;
219  case SimpleTypeKind::UInt128:
220  case SimpleTypeKind::UInt128Oct:
222  case SimpleTypeKind::UInt16Short:
224  case SimpleTypeKind::UInt32Long:
226  case SimpleTypeKind::UInt64Quad:
227  return PDB_BuiltinType::UInt;
230  case SimpleTypeKind::Complex16:
231  case SimpleTypeKind::Complex32:
232  case SimpleTypeKind::Complex32PartialPrecision:
233  case SimpleTypeKind::Complex64:
234  case SimpleTypeKind::Complex80:
235  case SimpleTypeKind::Complex128:
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 
253 }
254 
256  if (UnmodifiedType)
257  return UnmodifiedType->hasConstructor();
258 
259  return bool(Record->getOptions() &
261 }
262 
264  if (UnmodifiedType)
266 
267  return bool(Record->getOptions() &
269 }
270 
272  if (UnmodifiedType)
273  return UnmodifiedType->hasNestedTypes();
274 
275  return bool(Record->getOptions() &
277 }
278 
280  if (UnmodifiedType)
281  return UnmodifiedType->isIntrinsic();
282 
283  return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
284 }
285 
287  if (UnmodifiedType)
289 
290  return bool(Record->getOptions() &
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 =
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 
313  if (UnmodifiedType)
314  return UnmodifiedType->isNested();
315 
316  return bool(Record->getOptions() & codeview::ClassOptions::Nested);
317 }
318 
320  if (UnmodifiedType)
322 
323  return bool(Record->getOptions() &
325 }
326 
328  if (UnmodifiedType)
329  return UnmodifiedType->isPacked();
330 
331  return bool(Record->getOptions() & codeview::ClassOptions::Packed);
332 }
333 
335  if (UnmodifiedType)
336  return UnmodifiedType->isScoped();
337 
338  return bool(Record->getOptions() & codeview::ClassOptions::Scoped);
339 }
340 
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 
356  if (!Modifiers)
357  return false;
358  return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
360 }
361 
363  if (!Modifiers)
364  return false;
365  return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
367 }
368 
370  if (!Modifiers)
371  return false;
372  return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
374 }
375 
377  if (UnmodifiedType)
379 
381  getTypeId());
382 }
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:704
Kind kind() const
Definition: CVRecord.h:37
This class represents lattice values for constants.
Definition: AllocatorList.h:24
std::string getName() const override
SimpleTypeKind getSimpleKind() const
Definition: TypeIndex.h:127
NativeTypeEnum(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, codeview::EnumRecord Record)
codeview::LazyRandomTypeCollection & typeCollection()
Definition: TpiStream.h:59
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:300
PDB_SymType getSymTag() const override
PDB_BuiltinType getBuiltinType() const override
SimpleTypeMode getSimpleMode() const
Definition: TypeIndex.h:132
SymIndexId getUnmodifiedTypeId() const override
SymIndexId getTypeId() const override
Definition: BitVector.h:938
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:96
bool isScoped() const override
ArrayRef< uint8_t > data() const
Definition: CVRecord.h:38
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:183
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:46
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
Definition: TypeRecord.h:921
void dumpSymbolField(raw_ostream &OS, StringRef Name, T Value, int Indent)
Definition: PDBExtras.h:49
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:91
void dumpSymbolIdField(raw_ostream &OS, StringRef Name, SymIndexId Value, int Indent, const IPDBSession &Session, PdbSymbolIdField FieldId, PdbSymbolIdField ShowFlags, PdbSymbolIdField RecurseFlags)
Definition: PDBSymbol.cpp:186
std::unique_ptr< T > getConcreteSymbolById(SymIndexId SymbolId) const
Definition: IPDBSession.h:42
#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:327
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)
uint32_t SymIndexId
Definition: PDBTypes.h:26
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:275
bool isPacked() const override
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Definition: JSON.cpp:598
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
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:46
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:116