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