LLDB  mainline
UdtRecordCompleter.cpp
Go to the documentation of this file.
1 #include "UdtRecordCompleter.h"
2 
3 #include "PdbAstBuilder.h"
4 #include "PdbIndex.h"
5 #include "PdbSymUid.h"
6 #include "PdbUtil.h"
7 
11 #include "lldb/Symbol/Type.h"
13 #include "lldb/lldb-enumerations.h"
14 #include "lldb/lldb-forward.h"
15 
16 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
17 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
18 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
19 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
20 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
21 #include "llvm/DebugInfo/PDB/PDBTypes.h"
22 
23 using namespace llvm::codeview;
24 using namespace llvm::pdb;
25 using namespace lldb;
26 using namespace lldb_private;
27 using namespace lldb_private::npdb;
28 
30 
31 UdtRecordCompleter::UdtRecordCompleter(PdbTypeSymId id,
32  CompilerType &derived_ct,
33  clang::TagDecl &tag_decl,
34  PdbAstBuilder &ast_builder,
35  PdbIndex &index)
36  : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
37  m_ast_builder(ast_builder), m_index(index) {
38  CVType cvt = m_index.tpi().getType(m_id.index);
39  switch (cvt.kind()) {
40  case LF_ENUM:
41  llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er));
42  break;
43  case LF_UNION:
44  llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur));
45  break;
46  case LF_CLASS:
47  case LF_STRUCTURE:
48  llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr));
49  break;
50  default:
51  llvm_unreachable("unreachable!");
52  }
53 }
54 
56  llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access,
57  llvm::Optional<uint64_t> vtable_idx) {
58  PdbTypeSymId type_id(ti);
59  clang::QualType qt = m_ast_builder.GetOrCreateType(type_id);
60 
61  CVType udt_cvt = m_index.tpi().getType(ti);
62 
63  std::unique_ptr<clang::CXXBaseSpecifier> base_spec =
65  qt.getAsOpaquePtr(), TranslateMemberAccess(access),
66  vtable_idx.hasValue(), udt_cvt.kind() == LF_CLASS);
67  lldbassert(base_spec);
68 
69  m_bases.push_back(
70  std::make_pair(vtable_idx.getValueOr(0), std::move(base_spec)));
71 
72  return qt;
73 }
74 
75 void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx,
76  MemberAccess access, MethodOptions options,
77  MemberAttributes attrs) {
78  clang::QualType method_qt =
80  m_ast_builder.CompleteType(method_qt);
81 
82  lldb::AccessType access_type = TranslateMemberAccess(access);
83  bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
84  MethodOptions::CompilerGenerated;
86  m_derived_ct.GetOpaqueQualType(), name.data(), nullptr,
87  m_ast_builder.ToCompilerType(method_qt), access_type, attrs.isVirtual(),
88  attrs.isStatic(), false, false, false, is_artificial);
89 }
90 
91 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
92  BaseClassRecord &base) {
93  clang::QualType base_qt =
94  AddBaseClassForTypeIndex(base.Type, base.getAccess());
95 
96  auto decl =
97  m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr());
98  lldbassert(decl);
99 
100  auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset());
101  m_layout.base_offsets.insert(std::make_pair(decl, offset));
102 
103  return llvm::Error::success();
104 }
105 
106 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
107  VirtualBaseClassRecord &base) {
108  AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex);
109 
110  return Error::success();
111 }
112 
113 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
114  ListContinuationRecord &cont) {
115  return Error::success();
116 }
117 
118 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
119  VFPtrRecord &vfptr) {
120  return Error::success();
121 }
122 
123 Error UdtRecordCompleter::visitKnownMember(
124  CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) {
125  clang::QualType member_type =
126  m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type));
127 
128  m_ast_builder.CompleteType(member_type);
129 
130  CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
131 
132  lldb::AccessType access =
133  TranslateMemberAccess(static_data_member.getAccess());
135  m_derived_ct, static_data_member.Name, member_ct, access);
136 
137  // Static constant members may be a const[expr] declaration.
138  // Query the symbol's value as the variable initializer if valid.
139  if (member_ct.IsConst()) {
140  std::string qual_name = decl->getQualifiedNameAsString();
141 
142  auto results =
143  m_index.globals().findRecordsByName(qual_name, m_index.symrecords());
144 
145  for (const auto &result : results) {
146  if (result.second.kind() == SymbolKind::S_CONSTANT) {
147  ConstantSym constant(SymbolRecordKind::ConstantSym);
148  cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(result.second,
149  constant));
150 
151  clang::QualType qual_type = decl->getType();
152  unsigned type_width = decl->getASTContext().getIntWidth(qual_type);
153  unsigned constant_width = constant.Value.getBitWidth();
154 
155  if (qual_type->isIntegralOrEnumerationType()) {
156  if (type_width >= constant_width) {
158  decl, constant.Value.extOrTrunc(type_width));
159  } else {
161  "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
162  "which resolves to a wider constant value ({4} bits). "
163  "Ignoring constant.",
164  m_derived_ct.GetTypeName(), static_data_member.Name,
165  member_ct.GetTypeName(), type_width, constant_width);
166  }
167  } else {
168  lldb::BasicType basic_type_enum = member_ct.GetBasicTypeEnumeration();
169  switch (basic_type_enum) {
173  if (type_width == constant_width) {
175  decl, basic_type_enum == lldb::eBasicTypeFloat
176  ? llvm::APFloat(constant.Value.bitsToFloat())
177  : llvm::APFloat(constant.Value.bitsToDouble()));
178  decl->setConstexpr(true);
179  } else {
180  LLDB_LOG(
182  "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
183  "which resolves to a constant value of mismatched width "
184  "({4} bits). Ignoring constant.",
185  m_derived_ct.GetTypeName(), static_data_member.Name,
186  member_ct.GetTypeName(), type_width, constant_width);
187  }
188  break;
189  default:
190  break;
191  }
192  }
193  break;
194  }
195  }
196  }
197 
198  // FIXME: Add a PdbSymUid namespace for field list members and update
199  // the m_uid_to_decl map with this decl.
200  return Error::success();
201 }
202 
203 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
204  NestedTypeRecord &nested) {
205  return Error::success();
206 }
207 
208 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
209  DataMemberRecord &data_member) {
210 
211  uint64_t offset = data_member.FieldOffset * 8;
212  uint32_t bitfield_width = 0;
213 
214  TypeIndex ti(data_member.Type);
215  if (!ti.isSimple()) {
216  CVType cvt = m_index.tpi().getType(ti);
217  if (cvt.kind() == LF_BITFIELD) {
218  BitFieldRecord bfr;
219  llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
220  offset += bfr.BitOffset;
221  bitfield_width = bfr.BitSize;
222  ti = bfr.Type;
223  }
224  }
225 
226  clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
227  m_ast_builder.CompleteType(member_qt);
228 
229  lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
230 
231  clang::FieldDecl *decl = TypeSystemClang::AddFieldToRecordType(
232  m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt),
233  access, bitfield_width);
234  // FIXME: Add a PdbSymUid namespace for field list members and update
235  // the m_uid_to_decl map with this decl.
236 
237  m_layout.field_offsets.insert(std::make_pair(decl, offset));
238 
239  return Error::success();
240 }
241 
242 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
243  OneMethodRecord &one_method) {
244  AddMethod(one_method.Name, one_method.Type, one_method.getAccess(),
245  one_method.getOptions(), one_method.Attrs);
246 
247  return Error::success();
248 }
249 
250 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
251  OverloadedMethodRecord &overloaded) {
252  TypeIndex method_list_idx = overloaded.MethodList;
253 
254  CVType method_list_type = m_index.tpi().getType(method_list_idx);
255  assert(method_list_type.kind() == LF_METHODLIST);
256 
257  MethodOverloadListRecord method_list;
258  llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
259  method_list_type, method_list));
260 
261  for (const OneMethodRecord &method : method_list.Methods)
262  AddMethod(overloaded.Name, method.Type, method.getAccess(),
263  method.getOptions(), method.Attrs);
264 
265  return Error::success();
266 }
267 
268 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
269  EnumeratorRecord &enumerator) {
270  Declaration decl;
271  llvm::StringRef name = DropNameScope(enumerator.getName());
272 
274  m_derived_ct, decl, name.str().c_str(), enumerator.Value);
275  return Error::success();
276 }
277 
279  // Ensure the correct order for virtual bases.
280  std::stable_sort(m_bases.begin(), m_bases.end(),
281  [](const IndexedBase &lhs, const IndexedBase &rhs) {
282  return lhs.first < rhs.first;
283  });
284 
285  std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
286  bases.reserve(m_bases.size());
287  for (auto &ib : m_bases)
288  bases.push_back(std::move(ib.second));
289 
291  clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
292 
293  clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
296 
297  if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
299  }
300 }
lldb_private::ClangASTImporter::LayoutInfo::field_offsets
llvm::DenseMap< const clang::FieldDecl *, uint64_t > field_offsets
Definition: ClangASTImporter.h:73
lldb_private::npdb::UdtRecordCompleter::UdtTagRecord::er
llvm::codeview::EnumRecord er
Definition: UdtRecordCompleter.h:47
lldb_private::npdb::PdbAstBuilder::ToCompilerType
CompilerType ToCompilerType(clang::QualType qt)
Definition: PdbAstBuilder.cpp:1343
lldb_private::TypeSystemClang::SetFloatingInitializerForVariable
static void SetFloatingInitializerForVariable(clang::VarDecl *var, const llvm::APFloat &init_value)
Initializes a variable with a floating point value.
Definition: TypeSystemClang.cpp:7498
lldb_private::npdb::PdbIndex
PdbIndex - Lazy access to the important parts of a PDB file.
Definition: PdbIndex.h:48
lldb_private::npdb::PdbTypeSymId::index
llvm::codeview::TypeIndex index
Definition: PdbSymUid.h:76
lldb_private::npdb::UdtRecordCompleter::UdtTagRecord::cr
llvm::codeview::ClassRecord cr
Definition: UdtRecordCompleter.h:46
lldb_private::npdb::TranslateMemberAccess
lldb::AccessType TranslateMemberAccess(llvm::codeview::MemberAccess access)
lldb_private::npdb
Definition: CodeViewRegisterMapping.h:16
lldb_private::npdb::DropNameScope
llvm::StringRef DropNameScope(llvm::StringRef name)
Definition: PdbUtil.cpp:452
lldb_private::npdb::PdbAstBuilder::clang
TypeSystemClang & clang()
Definition: PdbAstBuilder.h:83
lldb_private::npdb::UdtRecordCompleter::AddBaseClassForTypeIndex
clang::QualType AddBaseClassForTypeIndex(llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access, llvm::Optional< uint64_t > vtable_idx=llvm::Optional< uint64_t >())
Definition: UdtRecordCompleter.cpp:55
lldb_private::CompilerType::GetOpaqueQualType
lldb::opaque_compiler_type_t GetOpaqueQualType() const
Definition: CompilerType.h:173
lldb_private::TypeSystemClang::AddVariableToRecordType
static clang::VarDecl * AddVariableToRecordType(const CompilerType &type, llvm::StringRef name, const CompilerType &var_type, lldb::AccessType access)
Definition: TypeSystemClang.cpp:7443
lldb::BasicType
BasicType
Basic types enumeration for the public API SBType::GetBasicType().
Definition: lldb-enumerations.h:741
lldb_private::npdb::UdtRecordCompleter::IndexedBase
std::pair< uint64_t, std::unique_ptr< clang::CXXBaseSpecifier > > IndexedBase
Definition: UdtRecordCompleter.h:41
PdbIndex.h
ClangUtil.h
lldb_private::CompilerType::IsConst
bool IsConst() const
Definition: CompilerType.cpp:89
lldb_private::npdb::UdtRecordCompleter::complete
void complete()
Definition: UdtRecordCompleter.cpp:278
lldb::eBasicTypeFloat
@ eBasicTypeFloat
Definition: lldb-enumerations.h:764
lldb_private::ClangASTImporter::LayoutInfo::base_offsets
OffsetMap base_offsets
Definition: ClangASTImporter.h:74
LIBLLDB_LOG_AST
#define LIBLLDB_LOG_AST
Definition: Logging.h:45
LLDBAssert.h
lldb_private::TypeSystemClang::GetAsCXXRecordDecl
static clang::CXXRecordDecl * GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type)
Definition: TypeSystemClang.cpp:7217
lldb_private::CompilerType::GetBasicTypeEnumeration
lldb::BasicType GetBasicTypeEnumeration() const
Definition: CompilerType.cpp:523
TypeSystemClang.h
lldb_private::TypeSystemClang::AddFieldToRecordType
static clang::FieldDecl * AddFieldToRecordType(const CompilerType &type, llvm::StringRef name, const CompilerType &field_type, lldb::AccessType access, uint32_t bitfield_bit_size)
Definition: TypeSystemClang.cpp:7231
lldb_private::npdb::PdbIndex::tpi
llvm::pdb::TpiStream & tpi()
Definition: PdbIndex.h:125
lldb_private::npdb::UdtRecordCompleter::m_ast_builder
PdbAstBuilder & m_ast_builder
Definition: UdtRecordCompleter.h:53
Type.h
llvm::pdb
Definition: DWARFLocationExpression.h:21
lldb::eBasicTypeDouble
@ eBasicTypeDouble
Definition: lldb-enumerations.h:765
lldb_private::npdb::PdbTypeSymId
Definition: PdbSymUid.h:70
lldb-enumerations.h
lldb_private::GetLogIfAllCategoriesSet
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
PdbAstBuilder.h
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:39
lldb_private::npdb::UdtRecordCompleter::m_cvr
union lldb_private::npdb::UdtRecordCompleter::UdtTagRecord m_cvr
lldb_private::npdb::PdbAstBuilder::CompleteType
bool CompleteType(clang::QualType qt)
Definition: PdbAstBuilder.cpp:636
PdbUtil.h
lldb_private::ClangASTImporter::SetRecordLayout
void SetRecordLayout(clang::RecordDecl *decl, const LayoutInfo &layout)
Sets the layout for the given RecordDecl.
Definition: ClangASTImporter.cpp:548
lldbassert
#define lldbassert(x)
Definition: LLDBAssert.h:15
lldb::eBasicTypeLongDouble
@ eBasicTypeLongDouble
Definition: lldb-enumerations.h:766
lldb_private::npdb::PdbAstBuilder::importer
ClangASTImporter & importer()
Definition: PdbAstBuilder.h:84
uint32_t
UdtRecordCompleter.h
PdbSymUid.h
id
void * id
Definition: PlatformiOSSimulatorCoreSimulatorSupport.h:20
lldb_private::CompilerType::GetTypeName
ConstString GetTypeName() const
Definition: CompilerType.cpp:277
lldb_private::TypeSystemClang::BuildIndirectFields
static void BuildIndirectFields(const CompilerType &type)
Definition: TypeSystemClang.cpp:7319
LLDB_LOG
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:242
clang
Definition: ASTResultSynthesizer.h:15
lldb_private::npdb::UdtRecordCompleter::m_derived_ct
CompilerType & m_derived_ct
Definition: UdtRecordCompleter.h:51
lldb_private::npdb::PdbAstBuilder::GetOrCreateType
clang::QualType GetOrCreateType(PdbTypeSymId type)
Definition: PdbAstBuilder.cpp:950
lldb_private::CompilerType
Generic representation of a type in a programming language.
Definition: CompilerType.h:33
lldb-forward.h
lldb_private::npdb::UdtRecordCompleter::m_id
PdbTypeSymId m_id
Definition: UdtRecordCompleter.h:50
lldb_private::npdb::PdbIndex::symrecords
llvm::pdb::SymbolStream & symrecords()
Definition: PdbIndex.h:140
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
llvm::codeview
Definition: DWARFLocationExpression.h:18
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
lldb_private::TypeSystemClang::SetIntegerInitializerForVariable
static void SetIntegerInitializerForVariable(clang::VarDecl *var, const llvm::APInt &init_value)
Initializes a variable with an integer value.
Definition: TypeSystemClang.cpp:7480
lldb_private::npdb::UdtRecordCompleter::m_tag_decl
clang::TagDecl & m_tag_decl
Definition: UdtRecordCompleter.h:52
lldb_private::TypeSystemClang
A TypeSystem implementation based on Clang.
Definition: TypeSystemClang.h:106
ClangASTImporter.h
lldb_private::TypeSystemClang::AddEnumerationValueToEnumerationType
clang::EnumConstantDecl * AddEnumerationValueToEnumerationType(const CompilerType &enum_type, const Declaration &decl, const char *name, int64_t enum_value, uint32_t enum_value_bit_size)
Definition: TypeSystemClang.cpp:8317
lldb_private::TypeSystemClang::AddMethodToCXXRecordType
clang::CXXMethodDecl * AddMethodToCXXRecordType(lldb::opaque_compiler_type_t type, llvm::StringRef name, const char *mangled_name, const CompilerType &method_type, lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline, bool is_explicit, bool is_attr_used, bool is_artificial)
Definition: TypeSystemClang.cpp:7509
lldb_private::npdb::PdbIndex::globals
llvm::pdb::GlobalsStream & globals()
Definition: PdbIndex.h:137
lldb_private::npdb::UdtRecordCompleter::m_layout
ClangASTImporter::LayoutInfo m_layout
Definition: UdtRecordCompleter.h:56
lldb_private::Declaration
Definition: Declaration.h:24
lldb_private::npdb::UdtRecordCompleter::UdtTagRecord::ur
llvm::codeview::UnionRecord ur
Definition: UdtRecordCompleter.h:45
lldb_private::TypeSystemClang::CompleteTagDeclarationDefinition
static bool CompleteTagDeclarationDefinition(const CompilerType &type)
Definition: TypeSystemClang.cpp:8190
lldb
Definition: SBAddress.h:15
lldb::AccessType
AccessType
Definition: lldb-enumerations.h:507
lldb_private::TypeSystemClang::CreateBaseClassSpecifier
std::unique_ptr< clang::CXXBaseSpecifier > CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type, lldb::AccessType access, bool is_virtual, bool base_of_class)
Definition: TypeSystemClang.cpp:7710
lldb_private::npdb::UdtRecordCompleter::AddMethod
void AddMethod(llvm::StringRef name, llvm::codeview::TypeIndex type_idx, llvm::codeview::MemberAccess access, llvm::codeview::MethodOptions options, llvm::codeview::MemberAttributes attrs)
Definition: UdtRecordCompleter.cpp:75
lldb_private::npdb::PdbAstBuilder
Definition: PdbAstBuilder.h:51
lldb_private::npdb::UdtRecordCompleter::m_index
PdbIndex & m_index
Definition: UdtRecordCompleter.h:54
lldb_private::npdb::UdtRecordCompleter::m_bases
std::vector< IndexedBase > m_bases
Definition: UdtRecordCompleter.h:55