1 | //===- NativeTypeUDT.cpp - info about class/struct 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 | |
9 | #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" |
10 | #include "llvm/DebugInfo/CodeView/CodeView.h" |
11 | #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" |
12 | #include "llvm/DebugInfo/PDB/Native/NativeSession.h" |
13 | #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" |
14 | #include "llvm/DebugInfo/PDB/PDBExtras.h" |
15 | |
16 | using namespace llvm; |
17 | using namespace llvm::codeview; |
18 | using namespace llvm::pdb; |
19 | |
20 | NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, |
21 | codeview::TypeIndex TI, codeview::ClassRecord CR) |
22 | : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), |
23 | Class(std::move(CR)), Tag(&*Class) {} |
24 | |
25 | NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, |
26 | codeview::TypeIndex TI, codeview::UnionRecord UR) |
27 | : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), |
28 | Union(std::move(UR)), Tag(&*Union) {} |
29 | |
30 | NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, |
31 | NativeTypeUDT &UnmodifiedType, |
32 | codeview::ModifierRecord Modifier) |
33 | : NativeRawSymbol(Session, PDB_SymType::UDT, Id), |
34 | UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} |
35 | |
36 | NativeTypeUDT::~NativeTypeUDT() = default; |
37 | |
38 | void NativeTypeUDT::dump(raw_ostream &OS, int Indent, |
39 | PdbSymbolIdField ShowIdFields, |
40 | PdbSymbolIdField RecurseIdFields) const { |
41 | |
42 | NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); |
43 | |
44 | dumpSymbolField(OS, Name: "name" , Value: getName(), Indent); |
45 | dumpSymbolIdField(OS, Name: "lexicalParentId" , Value: 0, Indent, Session, |
46 | FieldId: PdbSymbolIdField::LexicalParent, ShowFlags: ShowIdFields, |
47 | RecurseFlags: RecurseIdFields); |
48 | if (Modifiers) |
49 | dumpSymbolIdField(OS, Name: "unmodifiedTypeId" , Value: getUnmodifiedTypeId(), Indent, |
50 | Session, FieldId: PdbSymbolIdField::UnmodifiedType, ShowFlags: ShowIdFields, |
51 | RecurseFlags: RecurseIdFields); |
52 | if (getUdtKind() != PDB_UdtType::Union) |
53 | dumpSymbolField(OS, Name: "virtualTableShapeId" , Value: getVirtualTableShapeId(), |
54 | Indent); |
55 | dumpSymbolField(OS, Name: "length" , Value: getLength(), Indent); |
56 | dumpSymbolField(OS, Name: "udtKind" , Value: getUdtKind(), Indent); |
57 | dumpSymbolField(OS, Name: "constructor" , Value: hasConstructor(), Indent); |
58 | dumpSymbolField(OS, Name: "constType" , Value: isConstType(), Indent); |
59 | dumpSymbolField(OS, Name: "hasAssignmentOperator" , Value: hasAssignmentOperator(), Indent); |
60 | dumpSymbolField(OS, Name: "hasCastOperator" , Value: hasCastOperator(), Indent); |
61 | dumpSymbolField(OS, Name: "hasNestedTypes" , Value: hasNestedTypes(), Indent); |
62 | dumpSymbolField(OS, Name: "overloadedOperator" , Value: hasOverloadedOperator(), Indent); |
63 | dumpSymbolField(OS, Name: "isInterfaceUdt" , Value: isInterfaceUdt(), Indent); |
64 | dumpSymbolField(OS, Name: "intrinsic" , Value: isIntrinsic(), Indent); |
65 | dumpSymbolField(OS, Name: "nested" , Value: isNested(), Indent); |
66 | dumpSymbolField(OS, Name: "packed" , Value: isPacked(), Indent); |
67 | dumpSymbolField(OS, Name: "isRefUdt" , Value: isRefUdt(), Indent); |
68 | dumpSymbolField(OS, Name: "scoped" , Value: isScoped(), Indent); |
69 | dumpSymbolField(OS, Name: "unalignedType" , Value: isUnalignedType(), Indent); |
70 | dumpSymbolField(OS, Name: "isValueUdt" , Value: isValueUdt(), Indent); |
71 | dumpSymbolField(OS, Name: "volatileType" , Value: isVolatileType(), Indent); |
72 | } |
73 | |
74 | std::string NativeTypeUDT::getName() const { |
75 | if (UnmodifiedType) |
76 | return UnmodifiedType->getName(); |
77 | |
78 | return std::string(Tag->getName()); |
79 | } |
80 | |
81 | SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; } |
82 | |
83 | SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const { |
84 | if (UnmodifiedType) |
85 | return UnmodifiedType->getSymIndexId(); |
86 | |
87 | return 0; |
88 | } |
89 | |
90 | SymIndexId NativeTypeUDT::getVirtualTableShapeId() const { |
91 | if (UnmodifiedType) |
92 | return UnmodifiedType->getVirtualTableShapeId(); |
93 | |
94 | if (Class) |
95 | return Session.getSymbolCache().findSymbolByTypeIndex(TI: Class->VTableShape); |
96 | |
97 | return 0; |
98 | } |
99 | |
100 | uint64_t NativeTypeUDT::getLength() const { |
101 | if (UnmodifiedType) |
102 | return UnmodifiedType->getLength(); |
103 | |
104 | if (Class) |
105 | return Class->getSize(); |
106 | |
107 | return Union->getSize(); |
108 | } |
109 | |
110 | PDB_UdtType NativeTypeUDT::getUdtKind() const { |
111 | if (UnmodifiedType) |
112 | return UnmodifiedType->getUdtKind(); |
113 | |
114 | switch (Tag->Kind) { |
115 | case TypeRecordKind::Class: |
116 | return PDB_UdtType::Class; |
117 | case TypeRecordKind::Union: |
118 | return PDB_UdtType::Union; |
119 | case TypeRecordKind::Struct: |
120 | return PDB_UdtType::Struct; |
121 | case TypeRecordKind::Interface: |
122 | return PDB_UdtType::Interface; |
123 | default: |
124 | llvm_unreachable("Unexpected udt kind" ); |
125 | } |
126 | } |
127 | |
128 | bool NativeTypeUDT::hasConstructor() const { |
129 | if (UnmodifiedType) |
130 | return UnmodifiedType->hasConstructor(); |
131 | |
132 | return (Tag->Options & ClassOptions::HasConstructorOrDestructor) != |
133 | ClassOptions::None; |
134 | } |
135 | |
136 | bool NativeTypeUDT::isConstType() const { |
137 | if (!Modifiers) |
138 | return false; |
139 | return (Modifiers->Modifiers & ModifierOptions::Const) != |
140 | ModifierOptions::None; |
141 | } |
142 | |
143 | bool NativeTypeUDT::hasAssignmentOperator() const { |
144 | if (UnmodifiedType) |
145 | return UnmodifiedType->hasAssignmentOperator(); |
146 | |
147 | return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) != |
148 | ClassOptions::None; |
149 | } |
150 | |
151 | bool NativeTypeUDT::hasCastOperator() const { |
152 | if (UnmodifiedType) |
153 | return UnmodifiedType->hasCastOperator(); |
154 | |
155 | return (Tag->Options & ClassOptions::HasConversionOperator) != |
156 | ClassOptions::None; |
157 | } |
158 | |
159 | bool NativeTypeUDT::hasNestedTypes() const { |
160 | if (UnmodifiedType) |
161 | return UnmodifiedType->hasNestedTypes(); |
162 | |
163 | return (Tag->Options & ClassOptions::ContainsNestedClass) != |
164 | ClassOptions::None; |
165 | } |
166 | |
167 | bool NativeTypeUDT::hasOverloadedOperator() const { |
168 | if (UnmodifiedType) |
169 | return UnmodifiedType->hasOverloadedOperator(); |
170 | |
171 | return (Tag->Options & ClassOptions::HasOverloadedOperator) != |
172 | ClassOptions::None; |
173 | } |
174 | |
175 | bool NativeTypeUDT::isInterfaceUdt() const { return false; } |
176 | |
177 | bool NativeTypeUDT::isIntrinsic() const { |
178 | if (UnmodifiedType) |
179 | return UnmodifiedType->isIntrinsic(); |
180 | |
181 | return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None; |
182 | } |
183 | |
184 | bool NativeTypeUDT::isNested() const { |
185 | if (UnmodifiedType) |
186 | return UnmodifiedType->isNested(); |
187 | |
188 | return (Tag->Options & ClassOptions::Nested) != ClassOptions::None; |
189 | } |
190 | |
191 | bool NativeTypeUDT::isPacked() const { |
192 | if (UnmodifiedType) |
193 | return UnmodifiedType->isPacked(); |
194 | |
195 | return (Tag->Options & ClassOptions::Packed) != ClassOptions::None; |
196 | } |
197 | |
198 | bool NativeTypeUDT::isRefUdt() const { return false; } |
199 | |
200 | bool NativeTypeUDT::isScoped() const { |
201 | if (UnmodifiedType) |
202 | return UnmodifiedType->isScoped(); |
203 | |
204 | return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None; |
205 | } |
206 | |
207 | bool NativeTypeUDT::isValueUdt() const { return false; } |
208 | |
209 | bool NativeTypeUDT::isUnalignedType() const { |
210 | if (!Modifiers) |
211 | return false; |
212 | return (Modifiers->Modifiers & ModifierOptions::Unaligned) != |
213 | ModifierOptions::None; |
214 | } |
215 | |
216 | bool NativeTypeUDT::isVolatileType() const { |
217 | if (!Modifiers) |
218 | return false; |
219 | return (Modifiers->Modifiers & ModifierOptions::Volatile) != |
220 | ModifierOptions::None; |
221 | } |
222 | |