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.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 =
83       m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx));
84   if (method_qt.isNull())
85     return;
86   m_ast_builder.CompleteType(method_qt);
87   CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt);
88   lldb::opaque_compiler_type_t derived_opaque_ty = m_derived_ct.GetOpaqueQualType();
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;
99   m_ast_builder.clang().AddMethodToCXXRecordType(
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());
152   auto decl = TypeSystemClang::AddVariableToRecordType(
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) {
175             TypeSystemClang::SetIntegerInitializerForVariable(
176                 decl, constant.Value.extOrTrunc(type_width));
177           } else {
178             LLDB_LOG(GetLog(LLDBLog::AST),
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) {
188           case lldb::eBasicTypeFloat:
189           case lldb::eBasicTypeDouble:
190           case lldb::eBasicTypeLongDouble:
191             if (type_width == constant_width) {
192               TypeSystemClang::SetFloatingInitializerForVariable(
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(
199                   GetLog(LLDBLog::AST),
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 
293   m_ast_builder.clang().AddEnumerationValueToEnumerationType(
294       m_derived_ct, decl, name.str().c_str(), enumerator.Value);
295   return Error::success();
296 }
297 
298 void UdtRecordCompleter::complete() {
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 
307   TypeSystemClang &clang = m_ast_builder.clang();
308   clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
309 
310   clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
311   TypeSystemClang::BuildIndirectFields(m_derived_ct);
312   TypeSystemClang::CompleteTagDeclarationDefinition(m_derived_ct);
313 
314   if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
315     m_ast_builder.importer().SetRecordLayout(record_decl, m_layout);
316   }
317 }
318