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/Utility/LLDBLog.h"
14 #include "lldb/lldb-enumerations.h"
15 #include "lldb/lldb-forward.h"
16 
17 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
18 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
19 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
20 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
21 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
22 #include "llvm/DebugInfo/PDB/PDBTypes.h"
23 
24 using namespace llvm::codeview;
25 using namespace llvm::pdb;
26 using namespace lldb;
27 using namespace lldb_private;
28 using namespace lldb_private::npdb;
29 
31 
32 UdtRecordCompleter::UdtRecordCompleter(
33  PdbTypeSymId id, CompilerType &derived_ct, clang::TagDecl &tag_decl,
34  PdbAstBuilder &ast_builder, PdbIndex &index,
35  llvm::DenseMap<lldb::opaque_compiler_type_t,
36  llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>>
37  &cxx_record_map)
38  : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
39  m_ast_builder(ast_builder), m_index(index),
40  m_cxx_record_map(cxx_record_map) {
41  CVType cvt = m_index.tpi().getType(m_id.index);
42  switch (cvt.kind()) {
43  case LF_ENUM:
44  llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er));
45  break;
46  case LF_UNION:
47  llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur));
48  break;
49  case LF_CLASS:
50  case LF_STRUCTURE:
51  llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr));
52  break;
53  default:
54  llvm_unreachable("unreachable!");
55  }
56 }
57 
59  llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access,
60  llvm::Optional<uint64_t> vtable_idx) {
61  PdbTypeSymId type_id(ti);
62  clang::QualType qt = m_ast_builder.GetOrCreateType(type_id);
63 
64  CVType udt_cvt = m_index.tpi().getType(ti);
65 
66  std::unique_ptr<clang::CXXBaseSpecifier> base_spec =
68  qt.getAsOpaquePtr(), TranslateMemberAccess(access),
69  vtable_idx.has_value(), udt_cvt.kind() == LF_CLASS);
70  if (!base_spec)
71  return {};
72 
73  m_bases.push_back(
74  std::make_pair(vtable_idx.value_or(0), std::move(base_spec)));
75 
76  return qt;
77 }
78 
79 void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx,
80  MemberAccess access, MethodOptions options,
81  MemberAttributes attrs) {
82  clang::QualType method_qt =
84  if (method_qt.isNull())
85  return;
86  m_ast_builder.CompleteType(method_qt);
87  CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt);
89  auto iter = m_cxx_record_map.find(derived_opaque_ty);
90  if (iter != m_cxx_record_map.end()) {
91  if (iter->getSecond().contains({name, method_ct})) {
92  return;
93  }
94  }
95 
96  lldb::AccessType access_type = TranslateMemberAccess(access);
97  bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
98  MethodOptions::CompilerGenerated;
100  derived_opaque_ty, name.data(), nullptr, method_ct,
101  access_type, attrs.isVirtual(), attrs.isStatic(), false, false, false,
102  is_artificial);
103 
104  m_cxx_record_map[derived_opaque_ty].insert({name, method_ct});
105 }
106 
107 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
108  BaseClassRecord &base) {
109  clang::QualType base_qt =
110  AddBaseClassForTypeIndex(base.Type, base.getAccess());
111 
112  if (base_qt.isNull())
113  return llvm::Error::success();
114  auto decl =
115  m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr());
116  lldbassert(decl);
117 
118  auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset());
119  m_layout.base_offsets.insert(std::make_pair(decl, offset));
120 
121  return llvm::Error::success();
122 }
123 
124 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
125  VirtualBaseClassRecord &base) {
126  AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex);
127 
128  return Error::success();
129 }
130 
131 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
132  ListContinuationRecord &cont) {
133  return Error::success();
134 }
135 
136 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
137  VFPtrRecord &vfptr) {
138  return Error::success();
139 }
140 
141 Error UdtRecordCompleter::visitKnownMember(
142  CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) {
143  clang::QualType member_type =
144  m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type));
145  if (member_type.isNull())
146  return llvm::Error::success();
147 
148  CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
149 
150  lldb::AccessType access =
151  TranslateMemberAccess(static_data_member.getAccess());
153  m_derived_ct, static_data_member.Name, member_ct, access);
154 
155  // Static constant members may be a const[expr] declaration.
156  // Query the symbol's value as the variable initializer if valid.
157  if (member_ct.IsConst() && member_ct.IsCompleteType()) {
158  std::string qual_name = decl->getQualifiedNameAsString();
159 
160  auto results =
161  m_index.globals().findRecordsByName(qual_name, m_index.symrecords());
162 
163  for (const auto &result : results) {
164  if (result.second.kind() == SymbolKind::S_CONSTANT) {
165  ConstantSym constant(SymbolRecordKind::ConstantSym);
166  cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(result.second,
167  constant));
168 
169  clang::QualType qual_type = decl->getType();
170  unsigned type_width = decl->getASTContext().getIntWidth(qual_type);
171  unsigned constant_width = constant.Value.getBitWidth();
172 
173  if (qual_type->isIntegralOrEnumerationType()) {
174  if (type_width >= constant_width) {
176  decl, constant.Value.extOrTrunc(type_width));
177  } else {
179  "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
180  "which resolves to a wider constant value ({4} bits). "
181  "Ignoring constant.",
182  m_derived_ct.GetTypeName(), static_data_member.Name,
183  member_ct.GetTypeName(), type_width, constant_width);
184  }
185  } else {
186  lldb::BasicType basic_type_enum = member_ct.GetBasicTypeEnumeration();
187  switch (basic_type_enum) {
191  if (type_width == constant_width) {
193  decl, basic_type_enum == lldb::eBasicTypeFloat
194  ? llvm::APFloat(constant.Value.bitsToFloat())
195  : llvm::APFloat(constant.Value.bitsToDouble()));
196  decl->setConstexpr(true);
197  } else {
198  LLDB_LOG(
200  "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
201  "which resolves to a constant value of mismatched width "
202  "({4} bits). Ignoring constant.",
203  m_derived_ct.GetTypeName(), static_data_member.Name,
204  member_ct.GetTypeName(), type_width, constant_width);
205  }
206  break;
207  default:
208  break;
209  }
210  }
211  break;
212  }
213  }
214  }
215 
216  // FIXME: Add a PdbSymUid namespace for field list members and update
217  // the m_uid_to_decl map with this decl.
218  return Error::success();
219 }
220 
221 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
222  NestedTypeRecord &nested) {
223  return Error::success();
224 }
225 
226 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
227  DataMemberRecord &data_member) {
228 
229  uint64_t offset = data_member.FieldOffset * 8;
230  uint32_t bitfield_width = 0;
231 
232  TypeIndex ti(data_member.Type);
233  if (!ti.isSimple()) {
234  CVType cvt = m_index.tpi().getType(ti);
235  if (cvt.kind() == LF_BITFIELD) {
236  BitFieldRecord bfr;
237  llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
238  offset += bfr.BitOffset;
239  bitfield_width = bfr.BitSize;
240  ti = bfr.Type;
241  }
242  }
243 
244  clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
245  if (member_qt.isNull())
246  return Error::success();
247  m_ast_builder.CompleteType(member_qt);
248 
249  lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
250 
251  clang::FieldDecl *decl = TypeSystemClang::AddFieldToRecordType(
252  m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt),
253  access, bitfield_width);
254  // FIXME: Add a PdbSymUid namespace for field list members and update
255  // the m_uid_to_decl map with this decl.
256 
257  m_layout.field_offsets.insert(std::make_pair(decl, offset));
258 
259  return Error::success();
260 }
261 
262 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
263  OneMethodRecord &one_method) {
264  AddMethod(one_method.Name, one_method.Type, one_method.getAccess(),
265  one_method.getOptions(), one_method.Attrs);
266 
267  return Error::success();
268 }
269 
270 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
271  OverloadedMethodRecord &overloaded) {
272  TypeIndex method_list_idx = overloaded.MethodList;
273 
274  CVType method_list_type = m_index.tpi().getType(method_list_idx);
275  assert(method_list_type.kind() == LF_METHODLIST);
276 
277  MethodOverloadListRecord method_list;
278  llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
279  method_list_type, method_list));
280 
281  for (const OneMethodRecord &method : method_list.Methods)
282  AddMethod(overloaded.Name, method.Type, method.getAccess(),
283  method.getOptions(), method.Attrs);
284 
285  return Error::success();
286 }
287 
288 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
289  EnumeratorRecord &enumerator) {
290  Declaration decl;
291  llvm::StringRef name = DropNameScope(enumerator.getName());
292 
294  m_derived_ct, decl, name.str().c_str(), enumerator.Value);
295  return Error::success();
296 }
297 
299  // Ensure the correct order for virtual bases.
300  llvm::stable_sort(m_bases, llvm::less_first());
301 
302  std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
303  bases.reserve(m_bases.size());
304  for (auto &ib : m_bases)
305  bases.push_back(std::move(ib.second));
306 
308  clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
309 
310  clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
313 
314  if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
316  }
317 }
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:1622
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:7549
lldb_private::LLDBLog::AST
@ AST
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::CompilerType::IsCompleteType
bool IsCompleteType() const
Definition: CompilerType.cpp:83
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:473
lldb_private::npdb::PdbAstBuilder::clang
TypeSystemClang & clang()
Definition: PdbAstBuilder.h:85
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:58
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:7494
lldb::BasicType
BasicType
Basic types enumeration for the public API SBType::GetBasicType().
Definition: lldb-enumerations.h:747
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:298
lldb::eBasicTypeFloat
@ eBasicTypeFloat
Definition: lldb-enumerations.h:771
lldb_private::ClangASTImporter::LayoutInfo::base_offsets
OffsetMap base_offsets
Definition: ClangASTImporter.h:74
LLDBAssert.h
lldb_private::TypeSystemClang::GetAsCXXRecordDecl
static clang::CXXRecordDecl * GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type)
Definition: TypeSystemClang.cpp:7260
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:7274
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:23
lldb::eBasicTypeDouble
@ eBasicTypeDouble
Definition: lldb-enumerations.h:772
lldb_private::npdb::PdbTypeSymId
Definition: PdbSymUid.h:70
lldb-enumerations.h
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:713
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:773
lldb_private::npdb::PdbAstBuilder::importer
ClangASTImporter & importer()
Definition: PdbAstBuilder.h:86
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:7370
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:336
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:1050
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:20
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:30
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:7531
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:105
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:8376
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:7560
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::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:308
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:8246
lldb
Definition: SBAddress.h:15
LLDBLog.h
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:7766
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:79
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