1 #include "UdtRecordCompleter.h"
2 
3 #include "PdbAstBuilder.h"
4 #include "PdbIndex.h"
5 #include "PdbSymUid.h"
6 #include "PdbUtil.h"
7 
8 #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
9 #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
10 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
11 #include "lldb/Symbol/Type.h"
12 #include "lldb/Utility/LLDBAssert.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 
29 using Error = llvm::Error;
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 
57 clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex(
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 =
66       m_ast_builder.clang().CreateBaseClassSpecifier(
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 =
81       m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx));
82   m_ast_builder.CompleteType(method_qt);
83   CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt);
84   lldb::opaque_compiler_type_t derived_opaque_ty = m_derived_ct.GetOpaqueQualType();
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;
95   m_ast_builder.clang().AddMethodToCXXRecordType(
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());
146   auto decl = TypeSystemClang::AddVariableToRecordType(
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) {
169             TypeSystemClang::SetIntegerInitializerForVariable(
170                 decl, constant.Value.extOrTrunc(type_width));
171           } else {
172             LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_AST),
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) {
182           case lldb::eBasicTypeFloat:
183           case lldb::eBasicTypeDouble:
184           case lldb::eBasicTypeLongDouble:
185             if (type_width == constant_width) {
186               TypeSystemClang::SetFloatingInitializerForVariable(
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(
193                   GetLogIfAllCategoriesSet(LIBLLDB_LOG_AST),
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 
285   m_ast_builder.clang().AddEnumerationValueToEnumerationType(
286       m_derived_ct, decl, name.str().c_str(), enumerator.Value);
287   return Error::success();
288 }
289 
290 void UdtRecordCompleter::complete() {
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 
302   TypeSystemClang &clang = m_ast_builder.clang();
303   clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
304 
305   clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
306   TypeSystemClang::BuildIndirectFields(m_derived_ct);
307   TypeSystemClang::CompleteTagDeclarationDefinition(m_derived_ct);
308 
309   if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
310     m_ast_builder.importer().SetRecordLayout(record_decl, m_layout);
311   }
312 }
313