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