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
15using namespace llvm;
16using namespace llvm::codeview;
17using namespace llvm::pdb;
18
19NativeTypeUDT::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
24NativeTypeUDT::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
29NativeTypeUDT::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
35NativeTypeUDT::~NativeTypeUDT() {}
36
37void 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
73std::string NativeTypeUDT::getName() const {
74  if (UnmodifiedType)
75    return UnmodifiedType->getName();
76
77  return Tag->getName();
78}
79
80SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; }
81
82SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const {
83  if (UnmodifiedType)
84    return UnmodifiedType->getSymIndexId();
85
86  return 0;
87}
88
89SymIndexId 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
99uint64_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
109PDB_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
127bool NativeTypeUDT::hasConstructor() const {
128  if (UnmodifiedType)
129    return UnmodifiedType->hasConstructor();
130
131  return (Tag->Options & ClassOptions::HasConstructorOrDestructor) !=
132         ClassOptions::None;
133}
134
135bool NativeTypeUDT::isConstType() const {
136  if (!Modifiers)
137    return false;
138  return (Modifiers->Modifiers & ModifierOptions::Const) !=
139         ModifierOptions::None;
140}
141
142bool NativeTypeUDT::hasAssignmentOperator() const {
143  if (UnmodifiedType)
144    return UnmodifiedType->hasAssignmentOperator();
145
146  return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) !=
147         ClassOptions::None;
148}
149
150bool NativeTypeUDT::hasCastOperator() const {
151  if (UnmodifiedType)
152    return UnmodifiedType->hasCastOperator();
153
154  return (Tag->Options & ClassOptions::HasConversionOperator) !=
155         ClassOptions::None;
156}
157
158bool NativeTypeUDT::hasNestedTypes() const {
159  if (UnmodifiedType)
160    return UnmodifiedType->hasNestedTypes();
161
162  return (Tag->Options & ClassOptions::ContainsNestedClass) !=
163         ClassOptions::None;
164}
165
166bool NativeTypeUDT::hasOverloadedOperator() const {
167  if (UnmodifiedType)
168    return UnmodifiedType->hasOverloadedOperator();
169
170  return (Tag->Options & ClassOptions::HasOverloadedOperator) !=
171         ClassOptions::None;
172}
173
174bool NativeTypeUDT::isInterfaceUdt() const { return false; }
175
176bool NativeTypeUDT::isIntrinsic() const {
177  if (UnmodifiedType)
178    return UnmodifiedType->isIntrinsic();
179
180  return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None;
181}
182
183bool NativeTypeUDT::isNested() const {
184  if (UnmodifiedType)
185    return UnmodifiedType->isNested();
186
187  return (Tag->Options & ClassOptions::Nested) != ClassOptions::None;
188}
189
190bool NativeTypeUDT::isPacked() const {
191  if (UnmodifiedType)
192    return UnmodifiedType->isPacked();
193
194  return (Tag->Options & ClassOptions::Packed) != ClassOptions::None;
195}
196
197bool NativeTypeUDT::isRefUdt() const { return false; }
198
199bool NativeTypeUDT::isScoped() const {
200  if (UnmodifiedType)
201    return UnmodifiedType->isScoped();
202
203  return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None;
204}
205
206bool NativeTypeUDT::isValueUdt() const { return false; }
207
208bool NativeTypeUDT::isUnalignedType() const {
209  if (!Modifiers)
210    return false;
211  return (Modifiers->Modifiers & ModifierOptions::Unaligned) !=
212         ModifierOptions::None;
213}
214
215bool NativeTypeUDT::isVolatileType() const {
216  if (!Modifiers)
217    return false;
218  return (Modifiers->Modifiers & ModifierOptions::Volatile) !=
219         ModifierOptions::None;
220}
221