1 #include "UdtRecordCompleter.h" 2 3 #include "PdbIndex.h" 4 #include "PdbSymUid.h" 5 #include "PdbUtil.h" 6 #include "SymbolFileNativePDB.h" 7 8 #include "lldb/Symbol/ClangASTContext.h" 9 #include "lldb/Symbol/Type.h" 10 #include "lldb/Utility/LLDBAssert.h" 11 #include "lldb/lldb-enumerations.h" 12 #include "lldb/lldb-forward.h" 13 14 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 15 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 16 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 17 #include "llvm/DebugInfo/PDB/PDBTypes.h" 18 19 using namespace llvm::codeview; 20 using namespace llvm::pdb; 21 using namespace lldb; 22 using namespace lldb_private; 23 using namespace lldb_private::npdb; 24 25 using Error = llvm::Error; 26 27 UdtRecordCompleter::UdtRecordCompleter(PdbSymUid uid, CompilerType &derived_ct, 28 clang::TagDecl &tag_decl, 29 SymbolFileNativePDB &symbol_file) 30 : m_uid(uid), m_derived_ct(derived_ct), m_tag_decl(tag_decl), 31 m_symbol_file(symbol_file) { 32 TpiStream &tpi = symbol_file.m_index->tpi(); 33 TypeIndex ti(uid.asTypeSym().index); 34 CVType cvt = tpi.getType(ti); 35 switch (cvt.kind()) { 36 case LF_ENUM: 37 lldbassert(uid.tag() == PDB_SymType::Enum); 38 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er)); 39 break; 40 case LF_UNION: 41 lldbassert(uid.tag() == PDB_SymType::UDT); 42 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur)); 43 break; 44 case LF_CLASS: 45 case LF_STRUCTURE: 46 lldbassert(uid.tag() == PDB_SymType::UDT); 47 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr)); 48 break; 49 default: 50 llvm_unreachable("unreachable!"); 51 } 52 } 53 54 lldb::opaque_compiler_type_t UdtRecordCompleter::AddBaseClassForTypeIndex( 55 llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access) { 56 TypeSP base_type = m_symbol_file.GetOrCreateType(ti); 57 CompilerType base_ct = base_type->GetFullCompilerType(); 58 59 CVType udt_cvt = m_symbol_file.m_index->tpi().getType(ti); 60 61 lldb::opaque_compiler_type_t base_qt = base_ct.GetOpaqueQualType(); 62 std::unique_ptr<clang::CXXBaseSpecifier> base_spec = 63 m_symbol_file.GetASTContext().CreateBaseClassSpecifier( 64 base_qt, TranslateMemberAccess(access), false, 65 udt_cvt.kind() == LF_CLASS); 66 lldbassert(base_spec); 67 m_bases.push_back(std::move(base_spec)); 68 return base_qt; 69 } 70 71 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 72 BaseClassRecord &base) { 73 lldb::opaque_compiler_type_t base_qt = 74 AddBaseClassForTypeIndex(base.Type, base.getAccess()); 75 76 auto decl = m_symbol_file.GetASTContext().GetAsCXXRecordDecl(base_qt); 77 lldbassert(decl); 78 79 auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset()); 80 m_layout.base_offsets.insert(std::make_pair(decl, offset)); 81 82 return llvm::Error::success(); 83 } 84 85 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 86 VirtualBaseClassRecord &base) { 87 AddBaseClassForTypeIndex(base.BaseType, base.getAccess()); 88 89 // FIXME: Handle virtual base offsets. 90 return Error::success(); 91 } 92 93 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 94 ListContinuationRecord &cont) { 95 return Error::success(); 96 } 97 98 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 99 VFPtrRecord &vfptr) { 100 return Error::success(); 101 } 102 103 Error UdtRecordCompleter::visitKnownMember( 104 CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) { 105 TypeSP member_type = m_symbol_file.GetOrCreateType(static_data_member.Type); 106 CompilerType complete_member_type = member_type->GetFullCompilerType(); 107 108 lldb::AccessType access = 109 TranslateMemberAccess(static_data_member.getAccess()); 110 ClangASTContext::AddVariableToRecordType( 111 m_derived_ct, static_data_member.Name, complete_member_type, access); 112 113 // FIXME: Add a PdbSymUid namespace for field list members and update 114 // the m_uid_to_decl map with this decl. 115 return Error::success(); 116 } 117 118 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 119 NestedTypeRecord &nested) { 120 return Error::success(); 121 } 122 123 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 124 DataMemberRecord &data_member) { 125 126 TypeSP member_type = m_symbol_file.GetOrCreateType(data_member.Type); 127 CompilerType complete_member_type = member_type->GetFullCompilerType(); 128 129 lldb::AccessType access = TranslateMemberAccess(data_member.getAccess()); 130 131 clang::FieldDecl *decl = ClangASTContext::AddFieldToRecordType( 132 m_derived_ct, data_member.Name, complete_member_type, access, 0); 133 // FIXME: Add a PdbSymUid namespace for field list members and update 134 // the m_uid_to_decl map with this decl. 135 136 uint64_t offset = data_member.FieldOffset * 8; 137 m_layout.field_offsets.insert(std::make_pair(decl, offset)); 138 139 return Error::success(); 140 } 141 142 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 143 OneMethodRecord &one_method) { 144 return Error::success(); 145 } 146 147 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 148 OverloadedMethodRecord &overloaded) { 149 return Error::success(); 150 } 151 152 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 153 EnumeratorRecord &enumerator) { 154 ClangASTContext &clang = m_symbol_file.GetASTContext(); 155 156 Declaration decl; 157 llvm::StringRef name = DropNameScope(enumerator.getName()); 158 lldbassert(m_uid.tag() == PDB_SymType::Enum); 159 TypeSP underlying_type = 160 m_symbol_file.GetOrCreateType(m_cvr.er.getUnderlyingType()); 161 162 lldb::opaque_compiler_type_t enum_qt = m_derived_ct.GetOpaqueQualType(); 163 164 CompilerType enumerator_type = clang.GetEnumerationIntegerType(enum_qt); 165 uint64_t byte_size = underlying_type->GetByteSize(); 166 clang.AddEnumerationValueToEnumerationType( 167 m_derived_ct.GetOpaqueQualType(), enumerator_type, decl, 168 name.str().c_str(), enumerator.Value.getSExtValue(), 169 byte_size * 8); 170 return Error::success(); 171 } 172 173 void UdtRecordCompleter::complete() { 174 ClangASTContext &clang = m_symbol_file.GetASTContext(); 175 clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), 176 std::move(m_bases)); 177 178 clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType()); 179 ClangASTContext::BuildIndirectFields(m_derived_ct); 180 ClangASTContext::CompleteTagDeclarationDefinition(m_derived_ct); 181 182 if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) { 183 m_symbol_file.GetASTImporter().InsertRecordDecl(record_decl, m_layout); 184 } 185 }