1 //===- NativeTypeEnum.cpp - info about enum type ----------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
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"
22 #include "llvm/Support/FormatVariadic.h"
27 using namespace llvm::codeview;
28 using namespace llvm::pdb;
31 // Yea, this is a pretty terrible class name. But if we have an enum:
38 // then A and B are the "enumerators" of the "enum" Foo. And we need
40 class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
42 NativeEnumEnumEnumerators(NativeSession &Session,
43 const NativeTypeEnum &ClassParent,
44 const codeview::EnumRecord &CVEnum);
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;
52 Error visitKnownMember(CVMemberRecord &CVM,
53 EnumeratorRecord &Record) override;
54 Error visitKnownMember(CVMemberRecord &CVM,
55 ListContinuationRecord &Record) override;
57 NativeSession &Session;
58 const NativeTypeEnum &ClassParent;
59 const codeview::EnumRecord &CVEnum;
60 std::vector<EnumeratorRecord> Enumerators;
61 Optional<TypeIndex> ContinuationIndex;
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();
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));
82 Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
83 EnumeratorRecord &Record) {
84 Enumerators.push_back(Record);
85 return Error::success();
88 Error NativeEnumEnumEnumerators::visitKnownMember(
89 CVMemberRecord &CVM, ListContinuationRecord &Record) {
90 ContinuationIndex = Record.ContinuationIndex;
91 return Error::success();
94 uint32_t NativeEnumEnumEnumerators::getChildCount() const {
95 return Enumerators.size();
98 std::unique_ptr<PDBSymbol>
99 NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
100 if (Index >= getChildCount())
104 Session.getSymbolCache()
105 .getOrCreateFieldListMember<NativeSymbolEnumerator>(
106 CVEnum.FieldList, Index, ClassParent, Enumerators[Index]);
107 return Session.getSymbolCache().getSymbolById(Id);
110 std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
111 if (Index >= getChildCount())
114 return getChildAtIndex(Index++);
117 void NativeEnumEnumEnumerators::reset() { Index = 0; }
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)) {}
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)) {}
131 NativeTypeEnum::~NativeTypeEnum() {}
133 void NativeTypeEnum::dump(raw_ostream &OS, int Indent,
134 PdbSymbolIdField ShowIdFields,
135 PdbSymbolIdField RecurseIdFields) const {
136 NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
138 dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()),
140 dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
141 PdbSymbolIdField::LexicalParent, ShowIdFields,
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,
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);
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>>();
173 const NativeTypeEnum *ClassParent = nullptr;
177 NativeRawSymbol &NRS =
178 Session.getSymbolCache().getNativeSymbolById(getUnmodifiedTypeId());
179 assert(NRS.getSymTag() == PDB_SymType::Enum);
180 ClassParent = static_cast<NativeTypeEnum *>(&NRS);
182 return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent,
186 PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
188 PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
189 Session.getSymbolCache().findSymbolByTypeIndex(Record.getUnderlyingType());
191 codeview::TypeIndex Underlying = Record.getUnderlyingType();
193 // This indicates a corrupt record.
194 if (!Underlying.isSimple() ||
195 Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
196 return PDB_BuiltinType::None;
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;
252 return PDB_BuiltinType::None;
254 llvm_unreachable("Unreachable");
257 SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
261 return Session.getSymbolCache().findSymbolByTypeIndex(
262 Modifiers->ModifiedType);
265 bool NativeTypeEnum::hasConstructor() const {
266 return bool(Record.getOptions() &
267 codeview::ClassOptions::HasConstructorOrDestructor);
270 bool NativeTypeEnum::hasAssignmentOperator() const {
271 return bool(Record.getOptions() &
272 codeview::ClassOptions::HasOverloadedAssignmentOperator);
275 bool NativeTypeEnum::hasNestedTypes() const {
276 return bool(Record.getOptions() &
277 codeview::ClassOptions::ContainsNestedClass);
280 bool NativeTypeEnum::isIntrinsic() const {
281 return bool(Record.getOptions() & codeview::ClassOptions::Intrinsic);
284 bool NativeTypeEnum::hasCastOperator() const {
285 return bool(Record.getOptions() &
286 codeview::ClassOptions::HasConversionOperator);
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;
297 std::string NativeTypeEnum::getName() const { return Record.getName(); }
299 bool NativeTypeEnum::isNested() const {
300 return bool(Record.getOptions() & codeview::ClassOptions::Nested);
303 bool NativeTypeEnum::hasOverloadedOperator() const {
304 return bool(Record.getOptions() &
305 codeview::ClassOptions::HasOverloadedOperator);
308 bool NativeTypeEnum::isPacked() const {
309 return bool(Record.getOptions() & codeview::ClassOptions::Packed);
312 bool NativeTypeEnum::isScoped() const {
313 return bool(Record.getOptions() & codeview::ClassOptions::Scoped);
316 SymIndexId NativeTypeEnum::getTypeId() const {
317 return Session.getSymbolCache().findSymbolByTypeIndex(
318 Record.getUnderlyingType());
321 bool NativeTypeEnum::isRefUdt() const { return false; }
323 bool NativeTypeEnum::isValueUdt() const { return false; }
325 bool NativeTypeEnum::isInterfaceUdt() const { return false; }
327 bool NativeTypeEnum::isConstType() const {
330 return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
331 ModifierOptions::None);
334 bool NativeTypeEnum::isVolatileType() const {
337 return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
338 ModifierOptions::None);
341 bool NativeTypeEnum::isUnalignedType() const {
344 return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
345 ModifierOptions::None);
348 const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
349 return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(