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