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