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