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   m_ast_builder.CompleteType(member_type);
142 
143   CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
144 
145   lldb::AccessType access =
146       TranslateMemberAccess(static_data_member.getAccess());
147   auto decl = TypeSystemClang::AddVariableToRecordType(
148       m_derived_ct, static_data_member.Name, member_ct, access);
149 
150   // Static constant members may be a const[expr] declaration.
151   // Query the symbol's value as the variable initializer if valid.
152   if (member_ct.IsConst()) {
153     std::string qual_name = decl->getQualifiedNameAsString();
154 
155     auto results =
156         m_index.globals().findRecordsByName(qual_name, m_index.symrecords());
157 
158     for (const auto &result : results) {
159       if (result.second.kind() == SymbolKind::S_CONSTANT) {
160         ConstantSym constant(SymbolRecordKind::ConstantSym);
161         cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(result.second,
162                                                                 constant));
163 
164         clang::QualType qual_type = decl->getType();
165         unsigned type_width = decl->getASTContext().getIntWidth(qual_type);
166         unsigned constant_width = constant.Value.getBitWidth();
167 
168         if (qual_type->isIntegralOrEnumerationType()) {
169           if (type_width >= constant_width) {
170             TypeSystemClang::SetIntegerInitializerForVariable(
171                 decl, constant.Value.extOrTrunc(type_width));
172           } else {
173             LLDB_LOG(GetLog(LLDBLog::AST),
174                      "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
175                      "which resolves to a wider constant value ({4} bits). "
176                      "Ignoring constant.",
177                      m_derived_ct.GetTypeName(), static_data_member.Name,
178                      member_ct.GetTypeName(), type_width, constant_width);
179           }
180         } else {
181           lldb::BasicType basic_type_enum = member_ct.GetBasicTypeEnumeration();
182           switch (basic_type_enum) {
183           case lldb::eBasicTypeFloat:
184           case lldb::eBasicTypeDouble:
185           case lldb::eBasicTypeLongDouble:
186             if (type_width == constant_width) {
187               TypeSystemClang::SetFloatingInitializerForVariable(
188                   decl, basic_type_enum == lldb::eBasicTypeFloat
189                             ? llvm::APFloat(constant.Value.bitsToFloat())
190                             : llvm::APFloat(constant.Value.bitsToDouble()));
191               decl->setConstexpr(true);
192             } else {
193               LLDB_LOG(
194                   GetLog(LLDBLog::AST),
195                   "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
196                   "which resolves to a constant value of mismatched width "
197                   "({4} bits). Ignoring constant.",
198                   m_derived_ct.GetTypeName(), static_data_member.Name,
199                   member_ct.GetTypeName(), type_width, constant_width);
200             }
201             break;
202           default:
203             break;
204           }
205         }
206         break;
207       }
208     }
209   }
210 
211   // FIXME: Add a PdbSymUid namespace for field list members and update
212   // the m_uid_to_decl map with this decl.
213   return Error::success();
214 }
215 
216 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
217                                            NestedTypeRecord &nested) {
218   return Error::success();
219 }
220 
221 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
222                                            DataMemberRecord &data_member) {
223 
224   uint64_t offset = data_member.FieldOffset * 8;
225   uint32_t bitfield_width = 0;
226 
227   TypeIndex ti(data_member.Type);
228   if (!ti.isSimple()) {
229     CVType cvt = m_index.tpi().getType(ti);
230     if (cvt.kind() == LF_BITFIELD) {
231       BitFieldRecord bfr;
232       llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
233       offset += bfr.BitOffset;
234       bitfield_width = bfr.BitSize;
235       ti = bfr.Type;
236     }
237   }
238 
239   clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
240   m_ast_builder.CompleteType(member_qt);
241 
242   lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
243 
244   clang::FieldDecl *decl = TypeSystemClang::AddFieldToRecordType(
245       m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt),
246       access, bitfield_width);
247   // FIXME: Add a PdbSymUid namespace for field list members and update
248   // the m_uid_to_decl map with this decl.
249 
250   m_layout.field_offsets.insert(std::make_pair(decl, offset));
251 
252   return Error::success();
253 }
254 
255 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
256                                            OneMethodRecord &one_method) {
257   AddMethod(one_method.Name, one_method.Type, one_method.getAccess(),
258             one_method.getOptions(), one_method.Attrs);
259 
260   return Error::success();
261 }
262 
263 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
264                                            OverloadedMethodRecord &overloaded) {
265   TypeIndex method_list_idx = overloaded.MethodList;
266 
267   CVType method_list_type = m_index.tpi().getType(method_list_idx);
268   assert(method_list_type.kind() == LF_METHODLIST);
269 
270   MethodOverloadListRecord method_list;
271   llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
272       method_list_type, method_list));
273 
274   for (const OneMethodRecord &method : method_list.Methods)
275     AddMethod(overloaded.Name, method.Type, method.getAccess(),
276               method.getOptions(), method.Attrs);
277 
278   return Error::success();
279 }
280 
281 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
282                                            EnumeratorRecord &enumerator) {
283   Declaration decl;
284   llvm::StringRef name = DropNameScope(enumerator.getName());
285 
286   m_ast_builder.clang().AddEnumerationValueToEnumerationType(
287       m_derived_ct, decl, name.str().c_str(), enumerator.Value);
288   return Error::success();
289 }
290 
291 void UdtRecordCompleter::complete() {
292   // Ensure the correct order for virtual bases.
293   std::stable_sort(m_bases.begin(), m_bases.end(),
294                    [](const IndexedBase &lhs, const IndexedBase &rhs) {
295                      return lhs.first < rhs.first;
296                    });
297 
298   std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
299   bases.reserve(m_bases.size());
300   for (auto &ib : m_bases)
301     bases.push_back(std::move(ib.second));
302 
303   TypeSystemClang &clang = m_ast_builder.clang();
304   clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
305 
306   clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
307   TypeSystemClang::BuildIndirectFields(m_derived_ct);
308   TypeSystemClang::CompleteTagDeclarationDefinition(m_derived_ct);
309 
310   if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
311     m_ast_builder.importer().SetRecordLayout(record_decl, m_layout);
312   }
313 }
314