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 void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx, 69 MemberAccess access, MethodOptions options, 70 MemberAttributes attrs) { 71 clang::QualType method_qt = 72 m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx)); 73 m_ast_builder.CompleteType(method_qt); 74 75 lldb::AccessType access_type = TranslateMemberAccess(access); 76 bool is_artificial = (options & MethodOptions::CompilerGenerated) == 77 MethodOptions::CompilerGenerated; 78 m_ast_builder.clang().AddMethodToCXXRecordType( 79 m_derived_ct.GetOpaqueQualType(), name.data(), nullptr, 80 m_ast_builder.ToCompilerType(method_qt), access_type, attrs.isVirtual(), 81 attrs.isStatic(), false, false, false, is_artificial); 82 } 83 84 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 85 BaseClassRecord &base) { 86 clang::QualType base_qt = 87 AddBaseClassForTypeIndex(base.Type, base.getAccess()); 88 89 auto decl = 90 m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr()); 91 lldbassert(decl); 92 93 auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset()); 94 m_layout.base_offsets.insert(std::make_pair(decl, offset)); 95 96 return llvm::Error::success(); 97 } 98 99 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 100 VirtualBaseClassRecord &base) { 101 AddBaseClassForTypeIndex(base.BaseType, base.getAccess()); 102 103 // FIXME: Handle virtual base offsets. 104 return Error::success(); 105 } 106 107 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 108 ListContinuationRecord &cont) { 109 return Error::success(); 110 } 111 112 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 113 VFPtrRecord &vfptr) { 114 return Error::success(); 115 } 116 117 Error UdtRecordCompleter::visitKnownMember( 118 CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) { 119 clang::QualType member_type = 120 m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type)); 121 122 m_ast_builder.CompleteType(member_type); 123 124 CompilerType member_ct = m_ast_builder.ToCompilerType(member_type); 125 126 lldb::AccessType access = 127 TranslateMemberAccess(static_data_member.getAccess()); 128 ClangASTContext::AddVariableToRecordType( 129 m_derived_ct, static_data_member.Name, member_ct, access); 130 131 // FIXME: Add a PdbSymUid namespace for field list members and update 132 // the m_uid_to_decl map with this decl. 133 return Error::success(); 134 } 135 136 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 137 NestedTypeRecord &nested) { 138 return Error::success(); 139 } 140 141 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 142 DataMemberRecord &data_member) { 143 144 uint64_t offset = data_member.FieldOffset * 8; 145 uint32_t bitfield_width = 0; 146 147 TypeIndex ti(data_member.Type); 148 if (!ti.isSimple()) { 149 CVType cvt = m_tpi.getType(ti); 150 if (cvt.kind() == LF_BITFIELD) { 151 BitFieldRecord bfr; 152 llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr)); 153 offset += bfr.BitOffset; 154 bitfield_width = bfr.BitSize; 155 ti = bfr.Type; 156 } 157 } 158 159 clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti)); 160 m_ast_builder.CompleteType(member_qt); 161 162 lldb::AccessType access = TranslateMemberAccess(data_member.getAccess()); 163 164 clang::FieldDecl *decl = ClangASTContext::AddFieldToRecordType( 165 m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt), 166 access, bitfield_width); 167 // FIXME: Add a PdbSymUid namespace for field list members and update 168 // the m_uid_to_decl map with this decl. 169 170 m_layout.field_offsets.insert(std::make_pair(decl, offset)); 171 172 return Error::success(); 173 } 174 175 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 176 OneMethodRecord &one_method) { 177 AddMethod(one_method.Name, one_method.Type, one_method.getAccess(), 178 one_method.getOptions(), one_method.Attrs); 179 180 return Error::success(); 181 } 182 183 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 184 OverloadedMethodRecord &overloaded) { 185 TypeIndex method_list_idx = overloaded.MethodList; 186 187 CVType method_list_type = m_tpi.getType(method_list_idx); 188 assert(method_list_type.Type == LF_METHODLIST); 189 190 MethodOverloadListRecord method_list; 191 llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>( 192 method_list_type, method_list)); 193 194 for (const OneMethodRecord &method : method_list.Methods) 195 AddMethod(overloaded.Name, method.Type, method.getAccess(), 196 method.getOptions(), method.Attrs); 197 198 return Error::success(); 199 } 200 201 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 202 EnumeratorRecord &enumerator) { 203 Declaration decl; 204 llvm::StringRef name = DropNameScope(enumerator.getName()); 205 206 m_ast_builder.clang().AddEnumerationValueToEnumerationType( 207 m_derived_ct, decl, name.str().c_str(), enumerator.Value); 208 return Error::success(); 209 } 210 211 void UdtRecordCompleter::complete() { 212 ClangASTContext &clang = m_ast_builder.clang(); 213 clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), 214 std::move(m_bases)); 215 216 clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType()); 217 ClangASTContext::BuildIndirectFields(m_derived_ct); 218 ClangASTContext::CompleteTagDeclarationDefinition(m_derived_ct); 219 220 if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) { 221 m_ast_builder.importer().InsertRecordDecl(record_decl, m_layout); 222 } 223 } 224