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(
32  PdbTypeSymId id, CompilerType &derived_ct, clang::TagDecl &tag_decl,
33  PdbAstBuilder &ast_builder, PdbIndex &index,
34  llvm::DenseMap<lldb::opaque_compiler_type_t,
35  llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>>
36  &cxx_record_map)
37  : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
38  m_ast_builder(ast_builder), m_index(index),
39  m_cxx_record_map(cxx_record_map) {
40  CVType cvt = m_index.tpi().getType(m_id.index);
41  switch (cvt.kind()) {
42  case LF_ENUM:
43  llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er));
44  break;
45  case LF_UNION:
46  llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur));
47  break;
48  case LF_CLASS:
49  case LF_STRUCTURE:
50  llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr));
51  break;
52  default:
53  llvm_unreachable("unreachable!");
54  }
55 }
56 
58  llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access,
59  llvm::Optional<uint64_t> vtable_idx) {
60  PdbTypeSymId type_id(ti);
61  clang::QualType qt = m_ast_builder.GetOrCreateType(type_id);
62 
63  CVType udt_cvt = m_index.tpi().getType(ti);
64 
65  std::unique_ptr<clang::CXXBaseSpecifier> base_spec =
67  qt.getAsOpaquePtr(), TranslateMemberAccess(access),
68  vtable_idx.hasValue(), udt_cvt.kind() == LF_CLASS);
69  lldbassert(base_spec);
70 
71  m_bases.push_back(
72  std::make_pair(vtable_idx.getValueOr(0), std::move(base_spec)));
73 
74  return qt;
75 }
76 
77 void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx,
78  MemberAccess access, MethodOptions options,
79  MemberAttributes attrs) {
80  clang::QualType method_qt =
82  m_ast_builder.CompleteType(method_qt);
83  CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt);
85  auto iter = m_cxx_record_map.find(derived_opaque_ty);
86  if (iter != m_cxx_record_map.end()) {
87  if (iter->getSecond().contains({name, method_ct})) {
88  return;
89  }
90  }
91 
92  lldb::AccessType access_type = TranslateMemberAccess(access);
93  bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
94  MethodOptions::CompilerGenerated;
96  derived_opaque_ty, name.data(), nullptr, method_ct,
97  access_type, attrs.isVirtual(), attrs.isStatic(), false, false, false,
98  is_artificial);
99 
100  m_cxx_record_map[derived_opaque_ty].insert({name, method_ct});
101 }
102 
103 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
104  BaseClassRecord &base) {
105  clang::QualType base_qt =
106  AddBaseClassForTypeIndex(base.Type, base.getAccess());
107 
108  auto decl =
109  m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr());
110  lldbassert(decl);
111 
112  auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset());
113  m_layout.base_offsets.insert(std::make_pair(decl, offset));
114 
115  return llvm::Error::success();
116 }
117 
118 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
119  VirtualBaseClassRecord &base) {
120  AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex);
121 
122  return Error::success();
123 }
124 
125 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
126  ListContinuationRecord &cont) {
127  return Error::success();
128 }
129 
130 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
131  VFPtrRecord &vfptr) {
132  return Error::success();
133 }
134 
135 Error UdtRecordCompleter::visitKnownMember(
136  CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) {
137  clang::QualType member_type =
138  m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type));
139 
140  m_ast_builder.CompleteType(member_type);
141 
142  CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
143 
144  lldb::AccessType access =
145  TranslateMemberAccess(static_data_member.getAccess());
147  m_derived_ct, static_data_member.Name, member_ct, access);
148 
149  // Static constant members may be a const[expr] declaration.
150  // Query the symbol's value as the variable initializer if valid.
151  if (member_ct.IsConst()) {
152  std::string qual_name = decl->getQualifiedNameAsString();
153 
154  auto results =
155  m_index.globals().findRecordsByName(qual_name, m_index.symrecords());
156 
157  for (const auto &result : results) {
158  if (result.second.kind() == SymbolKind::S_CONSTANT) {
159  ConstantSym constant(SymbolRecordKind::ConstantSym);
160  cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(result.second,
161  constant));
162 
163  clang::QualType qual_type = decl->getType();
164  unsigned type_width = decl->getASTContext().getIntWidth(qual_type);
165  unsigned constant_width = constant.Value.getBitWidth();
166 
167  if (qual_type->isIntegralOrEnumerationType()) {
168  if (type_width >= constant_width) {
170  decl, constant.Value.extOrTrunc(type_width));
171  } else {
173  "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
174  "which resolves to a wider constant value ({4} bits). "
175  "Ignoring constant.",
176  m_derived_ct.GetTypeName(), static_data_member.Name,
177  member_ct.GetTypeName(), type_width, constant_width);
178  }
179  } else {
180  lldb::BasicType basic_type_enum = member_ct.GetBasicTypeEnumeration();
181  switch (basic_type_enum) {
185  if (type_width == constant_width) {
187  decl, basic_type_enum == lldb::eBasicTypeFloat
188  ? llvm::APFloat(constant.Value.bitsToFloat())
189  : llvm::APFloat(constant.Value.bitsToDouble()));
190  decl->setConstexpr(true);
191  } else {
192  LLDB_LOG(
194  "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
195  "which resolves to a constant value of mismatched width "
196  "({4} bits). Ignoring constant.",
197  m_derived_ct.GetTypeName(), static_data_member.Name,
198  member_ct.GetTypeName(), type_width, constant_width);
199  }
200  break;
201  default:
202  break;
203  }
204  }
205  break;
206  }
207  }
208  }
209 
210  // FIXME: Add a PdbSymUid namespace for field list members and update
211  // the m_uid_to_decl map with this decl.
212  return Error::success();
213 }
214 
215 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
216  NestedTypeRecord &nested) {
217  return Error::success();
218 }
219 
220 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
221  DataMemberRecord &data_member) {
222 
223  uint64_t offset = data_member.FieldOffset * 8;
224  uint32_t bitfield_width = 0;
225 
226  TypeIndex ti(data_member.Type);
227  if (!ti.isSimple()) {
228  CVType cvt = m_index.tpi().getType(ti);
229  if (cvt.kind() == LF_BITFIELD) {
230  BitFieldRecord bfr;
231  llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
232  offset += bfr.BitOffset;
233  bitfield_width = bfr.BitSize;
234  ti = bfr.Type;
235  }
236  }
237 
238  clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
239  m_ast_builder.CompleteType(member_qt);
240 
241  lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
242 
243  clang::FieldDecl *decl = TypeSystemClang::AddFieldToRecordType(
244  m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt),
245  access, bitfield_width);
246  // FIXME: Add a PdbSymUid namespace for field list members and update
247  // the m_uid_to_decl map with this decl.
248 
249  m_layout.field_offsets.insert(std::make_pair(decl, offset));
250 
251  return Error::success();
252 }
253 
254 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
255  OneMethodRecord &one_method) {
256  AddMethod(one_method.Name, one_method.Type, one_method.getAccess(),
257  one_method.getOptions(), one_method.Attrs);
258 
259  return Error::success();
260 }
261 
262 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
263  OverloadedMethodRecord &overloaded) {
264  TypeIndex method_list_idx = overloaded.MethodList;
265 
266  CVType method_list_type = m_index.tpi().getType(method_list_idx);
267  assert(method_list_type.kind() == LF_METHODLIST);
268 
269  MethodOverloadListRecord method_list;
270  llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
271  method_list_type, method_list));
272 
273  for (const OneMethodRecord &method : method_list.Methods)
274  AddMethod(overloaded.Name, method.Type, method.getAccess(),
275  method.getOptions(), method.Attrs);
276 
277  return Error::success();
278 }
279 
280 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
281  EnumeratorRecord &enumerator) {
282  Declaration decl;
283  llvm::StringRef name = DropNameScope(enumerator.getName());
284 
286  m_derived_ct, decl, name.str().c_str(), enumerator.Value);
287  return Error::success();
288 }
289 
291  // Ensure the correct order for virtual bases.
292  std::stable_sort(m_bases.begin(), m_bases.end(),
293  [](const IndexedBase &lhs, const IndexedBase &rhs) {
294  return lhs.first < rhs.first;
295  });
296 
297  std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
298  bases.reserve(m_bases.size());
299  for (auto &ib : m_bases)
300  bases.push_back(std::move(ib.second));
301 
303  clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
304 
305  clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
308 
309  if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
311  }
312 }
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:1460
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:7542
lldb_private::npdb::PdbIndex
PdbIndex - Lazy access to the important parts of a PDB file.
Definition: PdbIndex.h:47
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:57
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:7487
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:290
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:7253
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:7267
lldb_private::npdb::PdbIndex::tpi
llvm::pdb::TpiStream & tpi()
Definition: PdbIndex.h:124
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:40
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:700
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:7363
lldb_private::npdb::UdtRecordCompleter::m_cxx_record_map
llvm::DenseMap< lldb::opaque_compiler_type_t, llvm::SmallSet< std::pair< llvm::StringRef, CompilerType >, 8 > > & m_cxx_record_map
Definition: UdtRecordCompleter.h:59
LLDB_LOG
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:240
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:1015
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:139
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:7524
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:8369
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:7553
lldb_private::npdb::PdbIndex::globals
llvm::pdb::GlobalsStream & globals()
Definition: PdbIndex.h:136
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:8239
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:7759
lldb::opaque_compiler_type_t
void * opaque_compiler_type_t
Definition: lldb-types.h:90
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:77
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