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 
10 #include "lldb/Symbol/Type.h"
12 #include "lldb/lldb-enumerations.h"
13 #include "lldb/lldb-forward.h"
14 
15 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
16 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
17 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
18 #include "llvm/DebugInfo/PDB/PDBTypes.h"
19 
20 using namespace llvm::codeview;
21 using namespace llvm::pdb;
22 using namespace lldb;
23 using namespace lldb_private;
24 using namespace lldb_private::npdb;
25 
27 
28 UdtRecordCompleter::UdtRecordCompleter(PdbTypeSymId id,
29  CompilerType &derived_ct,
30  clang::TagDecl &tag_decl,
31  PdbAstBuilder &ast_builder,
32  TpiStream &tpi)
33  : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
34  m_ast_builder(ast_builder), m_tpi(tpi) {
35  CVType cvt = m_tpi.getType(m_id.index);
36  switch (cvt.kind()) {
37  case LF_ENUM:
38  llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er));
39  break;
40  case LF_UNION:
41  llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur));
42  break;
43  case LF_CLASS:
44  case LF_STRUCTURE:
45  llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr));
46  break;
47  default:
48  llvm_unreachable("unreachable!");
49  }
50 }
51 
52 clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex(
53  llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access,
54  llvm::Optional<uint64_t> vtable_idx) {
55  PdbTypeSymId type_id(ti);
56  clang::QualType qt = m_ast_builder.GetOrCreateType(type_id);
57 
58  CVType udt_cvt = m_tpi.getType(ti);
59 
60  std::unique_ptr<clang::CXXBaseSpecifier> base_spec =
61  m_ast_builder.clang().CreateBaseClassSpecifier(
62  qt.getAsOpaquePtr(), TranslateMemberAccess(access),
63  vtable_idx.hasValue(), udt_cvt.kind() == LF_CLASS);
64  lldbassert(base_spec);
65 
66  m_bases.push_back(
67  std::make_pair(vtable_idx.getValueOr(0), std::move(base_spec)));
68 
69  return qt;
70 }
71 
72 void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx,
73  MemberAccess access, MethodOptions options,
74  MemberAttributes attrs) {
75  clang::QualType method_qt =
76  m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx));
77  m_ast_builder.CompleteType(method_qt);
78 
79  lldb::AccessType access_type = TranslateMemberAccess(access);
80  bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
81  MethodOptions::CompilerGenerated;
82  m_ast_builder.clang().AddMethodToCXXRecordType(
83  m_derived_ct.GetOpaqueQualType(), name.data(), nullptr,
84  m_ast_builder.ToCompilerType(method_qt), access_type, attrs.isVirtual(),
85  attrs.isStatic(), false, false, false, is_artificial);
86 }
87 
88 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
89  BaseClassRecord &base) {
90  clang::QualType base_qt =
91  AddBaseClassForTypeIndex(base.Type, base.getAccess());
92 
93  auto decl =
94  m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr());
95  lldbassert(decl);
96 
97  auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset());
98  m_layout.base_offsets.insert(std::make_pair(decl, offset));
99 
100  return llvm::Error::success();
101 }
102 
103 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
104  VirtualBaseClassRecord &base) {
105  AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex);
106 
107  return Error::success();
108 }
109 
110 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
111  ListContinuationRecord &cont) {
112  return Error::success();
113 }
114 
115 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
116  VFPtrRecord &vfptr) {
117  return Error::success();
118 }
119 
120 Error UdtRecordCompleter::visitKnownMember(
121  CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) {
122  clang::QualType member_type =
123  m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type));
124 
125  m_ast_builder.CompleteType(member_type);
126 
127  CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
128 
129  lldb::AccessType access =
130  TranslateMemberAccess(static_data_member.getAccess());
132  m_derived_ct, static_data_member.Name, member_ct, access);
133 
134  // FIXME: Add a PdbSymUid namespace for field list members and update
135  // the m_uid_to_decl map with this decl.
136  return Error::success();
137 }
138 
139 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
140  NestedTypeRecord &nested) {
141  return Error::success();
142 }
143 
144 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
145  DataMemberRecord &data_member) {
146 
147  uint64_t offset = data_member.FieldOffset * 8;
148  uint32_t bitfield_width = 0;
149 
150  TypeIndex ti(data_member.Type);
151  if (!ti.isSimple()) {
152  CVType cvt = m_tpi.getType(ti);
153  if (cvt.kind() == LF_BITFIELD) {
154  BitFieldRecord bfr;
155  llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
156  offset += bfr.BitOffset;
157  bitfield_width = bfr.BitSize;
158  ti = bfr.Type;
159  }
160  }
161 
162  clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
163  m_ast_builder.CompleteType(member_qt);
164 
165  lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
166 
167  clang::FieldDecl *decl = ClangASTContext::AddFieldToRecordType(
168  m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt),
169  access, bitfield_width);
170  // FIXME: Add a PdbSymUid namespace for field list members and update
171  // the m_uid_to_decl map with this decl.
172 
173  m_layout.field_offsets.insert(std::make_pair(decl, offset));
174 
175  return Error::success();
176 }
177 
178 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
179  OneMethodRecord &one_method) {
180  AddMethod(one_method.Name, one_method.Type, one_method.getAccess(),
181  one_method.getOptions(), one_method.Attrs);
182 
183  return Error::success();
184 }
185 
186 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
187  OverloadedMethodRecord &overloaded) {
188  TypeIndex method_list_idx = overloaded.MethodList;
189 
190  CVType method_list_type = m_tpi.getType(method_list_idx);
191  assert(method_list_type.kind() == LF_METHODLIST);
192 
193  MethodOverloadListRecord method_list;
194  llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
195  method_list_type, method_list));
196 
197  for (const OneMethodRecord &method : method_list.Methods)
198  AddMethod(overloaded.Name, method.Type, method.getAccess(),
199  method.getOptions(), method.Attrs);
200 
201  return Error::success();
202 }
203 
204 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
205  EnumeratorRecord &enumerator) {
206  Declaration decl;
207  llvm::StringRef name = DropNameScope(enumerator.getName());
208 
210  m_derived_ct, decl, name.str().c_str(), enumerator.Value);
211  return Error::success();
212 }
213 
215  // Ensure the correct order for virtual bases.
216  std::stable_sort(m_bases.begin(), m_bases.end(),
217  [](const IndexedBase &lhs, const IndexedBase &rhs) {
218  return lhs.first < rhs.first;
219  });
220 
221  std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
222  bases.reserve(m_bases.size());
223  for (auto &ib : m_bases)
224  bases.push_back(std::move(ib.second));
225 
226  ClangASTContext &clang = m_ast_builder.clang();
227  clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
228 
232 
233  if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
234  m_ast_builder.importer().InsertRecordDecl(record_decl, m_layout);
235  }
236 }
static bool CompleteTagDeclarationDefinition(const CompilerType &type)
void InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout)
std::unique_ptr< clang::CXXBaseSpecifier > CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type, lldb::AccessType access, bool is_virtual, bool base_of_class)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
#define lldbassert(x)
Definition: LLDBAssert.h:15
llvm::codeview::TypeIndex index
Definition: PdbSymUid.h:76
llvm::Error Error
lldb::AccessType TranslateMemberAccess(llvm::codeview::MemberAccess access)
clang::EnumConstantDecl * AddEnumerationValueToEnumerationType(const CompilerType &enum_type, const Declaration &decl, const char *name, int64_t enum_value, uint32_t enum_value_bit_size)
static clang::VarDecl * AddVariableToRecordType(const CompilerType &type, llvm::StringRef name, const CompilerType &var_type, lldb::AccessType access)
bool TransferBaseClasses(lldb::opaque_compiler_type_t type, std::vector< std::unique_ptr< clang::CXXBaseSpecifier >> bases)
llvm::StringRef DropNameScope(llvm::StringRef name)
Definition: PdbUtil.cpp:452
ClangASTImporter & importer()
Definition: PdbAstBuilder.h:82
lldb::opaque_compiler_type_t GetOpaqueQualType() const
Definition: CompilerType.h:165
llvm::DenseMap< const clang::CXXRecordDecl *, clang::CharUnits > base_offsets
clang::CXXRecordDecl * GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type)
static clang::FieldDecl * AddFieldToRecordType(const CompilerType &type, llvm::StringRef name, const CompilerType &field_type, lldb::AccessType access, uint32_t bitfield_bit_size)
bool CompleteType(clang::QualType qt)
llvm::DenseMap< const clang::FieldDecl *, uint64_t > field_offsets
void AddMethodOverridesForCXXRecordType(lldb::opaque_compiler_type_t type)
static void BuildIndirectFields(const CompilerType &type)
Definition: SBAddress.h:15
clang::QualType GetOrCreateType(PdbTypeSymId type)
A class that describes the declaration location of a lldb object.
Definition: Declaration.h:24
CompilerType ToCompilerType(clang::QualType qt)
clang::CXXMethodDecl * AddMethodToCXXRecordType(lldb::opaque_compiler_type_t type, const char *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)