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/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 
30 using Error = llvm::Error;
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 
58 clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex(
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 =
67       m_ast_builder.clang().CreateBaseClassSpecifier(
68           qt.getAsOpaquePtr(), TranslateMemberAccess(access),
69           vtable_idx.hasValue(), udt_cvt.kind() == LF_CLASS);
70   lldbassert(base_spec);
71 
72   m_bases.push_back(
73       std::make_pair(vtable_idx.getValueOr(0), std::move(base_spec)));
74 
75   return qt;
76 }
77 
78 void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx,
79                                    MemberAccess access, MethodOptions options,
80                                    MemberAttributes attrs) {
81   clang::QualType method_qt =
82       m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx));
83   m_ast_builder.CompleteType(method_qt);
84   CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt);
85   lldb::opaque_compiler_type_t derived_opaque_ty = m_derived_ct.GetOpaqueQualType();
86   auto iter = m_cxx_record_map.find(derived_opaque_ty);
87   if (iter != m_cxx_record_map.end()) {
88     if (iter->getSecond().contains({name, method_ct})) {
89       return;
90     }
91   }
92 
93   lldb::AccessType access_type = TranslateMemberAccess(access);
94   bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
95                        MethodOptions::CompilerGenerated;
96   m_ast_builder.clang().AddMethodToCXXRecordType(
97       derived_opaque_ty, name.data(), nullptr, method_ct,
98       access_type, attrs.isVirtual(), attrs.isStatic(), false, false, false,
99       is_artificial);
100 
101   m_cxx_record_map[derived_opaque_ty].insert({name, method_ct});
102 }
103 
104 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
105                                            BaseClassRecord &base) {
106   clang::QualType base_qt =
107       AddBaseClassForTypeIndex(base.Type, base.getAccess());
108 
109   auto decl =
110       m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr());
111   lldbassert(decl);
112 
113   auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset());
114   m_layout.base_offsets.insert(std::make_pair(decl, offset));
115 
116   return llvm::Error::success();
117 }
118 
119 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
120                                            VirtualBaseClassRecord &base) {
121   AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex);
122 
123   return Error::success();
124 }
125 
126 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
127                                            ListContinuationRecord &cont) {
128   return Error::success();
129 }
130 
131 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
132                                            VFPtrRecord &vfptr) {
133   return Error::success();
134 }
135 
136 Error UdtRecordCompleter::visitKnownMember(
137     CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) {
138   clang::QualType member_type =
139       m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type));
140 
141   CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
142 
143   lldb::AccessType access =
144       TranslateMemberAccess(static_data_member.getAccess());
145   auto decl = TypeSystemClang::AddVariableToRecordType(
146       m_derived_ct, static_data_member.Name, member_ct, access);
147 
148   // Static constant members may be a const[expr] declaration.
149   // Query the symbol's value as the variable initializer if valid.
150   if (member_ct.IsConst() && member_ct.IsCompleteType()) {
151     std::string qual_name = decl->getQualifiedNameAsString();
152 
153     auto results =
154         m_index.globals().findRecordsByName(qual_name, m_index.symrecords());
155 
156     for (const auto &result : results) {
157       if (result.second.kind() == SymbolKind::S_CONSTANT) {
158         ConstantSym constant(SymbolRecordKind::ConstantSym);
159         cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(result.second,
160                                                                 constant));
161 
162         clang::QualType qual_type = decl->getType();
163         unsigned type_width = decl->getASTContext().getIntWidth(qual_type);
164         unsigned constant_width = constant.Value.getBitWidth();
165 
166         if (qual_type->isIntegralOrEnumerationType()) {
167           if (type_width >= constant_width) {
168             TypeSystemClang::SetIntegerInitializerForVariable(
169                 decl, constant.Value.extOrTrunc(type_width));
170           } else {
171             LLDB_LOG(GetLog(LLDBLog::AST),
172                      "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
173                      "which resolves to a wider constant value ({4} bits). "
174                      "Ignoring constant.",
175                      m_derived_ct.GetTypeName(), static_data_member.Name,
176                      member_ct.GetTypeName(), type_width, constant_width);
177           }
178         } else {
179           lldb::BasicType basic_type_enum = member_ct.GetBasicTypeEnumeration();
180           switch (basic_type_enum) {
181           case lldb::eBasicTypeFloat:
182           case lldb::eBasicTypeDouble:
183           case lldb::eBasicTypeLongDouble:
184             if (type_width == constant_width) {
185               TypeSystemClang::SetFloatingInitializerForVariable(
186                   decl, basic_type_enum == lldb::eBasicTypeFloat
187                             ? llvm::APFloat(constant.Value.bitsToFloat())
188                             : llvm::APFloat(constant.Value.bitsToDouble()));
189               decl->setConstexpr(true);
190             } else {
191               LLDB_LOG(
192                   GetLog(LLDBLog::AST),
193                   "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
194                   "which resolves to a constant value of mismatched width "
195                   "({4} bits). Ignoring constant.",
196                   m_derived_ct.GetTypeName(), static_data_member.Name,
197                   member_ct.GetTypeName(), type_width, constant_width);
198             }
199             break;
200           default:
201             break;
202           }
203         }
204         break;
205       }
206     }
207   }
208 
209   // FIXME: Add a PdbSymUid namespace for field list members and update
210   // the m_uid_to_decl map with this decl.
211   return Error::success();
212 }
213 
214 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
215                                            NestedTypeRecord &nested) {
216   return Error::success();
217 }
218 
219 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
220                                            DataMemberRecord &data_member) {
221 
222   uint64_t offset = data_member.FieldOffset * 8;
223   uint32_t bitfield_width = 0;
224 
225   TypeIndex ti(data_member.Type);
226   if (!ti.isSimple()) {
227     CVType cvt = m_index.tpi().getType(ti);
228     if (cvt.kind() == LF_BITFIELD) {
229       BitFieldRecord bfr;
230       llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
231       offset += bfr.BitOffset;
232       bitfield_width = bfr.BitSize;
233       ti = bfr.Type;
234     }
235   }
236 
237   clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
238   m_ast_builder.CompleteType(member_qt);
239 
240   lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
241 
242   clang::FieldDecl *decl = TypeSystemClang::AddFieldToRecordType(
243       m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt),
244       access, bitfield_width);
245   // FIXME: Add a PdbSymUid namespace for field list members and update
246   // the m_uid_to_decl map with this decl.
247 
248   m_layout.field_offsets.insert(std::make_pair(decl, offset));
249 
250   return Error::success();
251 }
252 
253 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
254                                            OneMethodRecord &one_method) {
255   AddMethod(one_method.Name, one_method.Type, one_method.getAccess(),
256             one_method.getOptions(), one_method.Attrs);
257 
258   return Error::success();
259 }
260 
261 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
262                                            OverloadedMethodRecord &overloaded) {
263   TypeIndex method_list_idx = overloaded.MethodList;
264 
265   CVType method_list_type = m_index.tpi().getType(method_list_idx);
266   assert(method_list_type.kind() == LF_METHODLIST);
267 
268   MethodOverloadListRecord method_list;
269   llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
270       method_list_type, method_list));
271 
272   for (const OneMethodRecord &method : method_list.Methods)
273     AddMethod(overloaded.Name, method.Type, method.getAccess(),
274               method.getOptions(), method.Attrs);
275 
276   return Error::success();
277 }
278 
279 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
280                                            EnumeratorRecord &enumerator) {
281   Declaration decl;
282   llvm::StringRef name = DropNameScope(enumerator.getName());
283 
284   m_ast_builder.clang().AddEnumerationValueToEnumerationType(
285       m_derived_ct, decl, name.str().c_str(), enumerator.Value);
286   return Error::success();
287 }
288 
289 void UdtRecordCompleter::complete() {
290   // Ensure the correct order for virtual bases.
291   std::stable_sort(m_bases.begin(), m_bases.end(),
292                    [](const IndexedBase &lhs, const IndexedBase &rhs) {
293                      return lhs.first < rhs.first;
294                    });
295 
296   std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
297   bases.reserve(m_bases.size());
298   for (auto &ib : m_bases)
299     bases.push_back(std::move(ib.second));
300 
301   TypeSystemClang &clang = m_ast_builder.clang();
302   clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
303 
304   clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
305   TypeSystemClang::BuildIndirectFields(m_derived_ct);
306   TypeSystemClang::CompleteTagDeclarationDefinition(m_derived_ct);
307 
308   if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
309     m_ast_builder.importer().SetRecordLayout(record_decl, m_layout);
310   }
311 }
312