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