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