1 #include "UdtRecordCompleter.h" 2 3 #include "PdbAstBuilder.h" 4 #include "PdbIndex.h" 5 #include "PdbSymUid.h" 6 #include "PdbUtil.h" 7 8 #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" 9 #include "Plugins/ExpressionParser/Clang/ClangUtil.h" 10 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 11 #include "lldb/Symbol/Type.h" 12 #include "lldb/Utility/LLDBAssert.h" 13 #include "lldb/lldb-enumerations.h" 14 #include "lldb/lldb-forward.h" 15 16 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 17 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 18 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 19 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" 20 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 21 #include "llvm/DebugInfo/PDB/PDBTypes.h" 22 23 using namespace llvm::codeview; 24 using namespace llvm::pdb; 25 using namespace lldb; 26 using namespace lldb_private; 27 using namespace lldb_private::npdb; 28 29 using Error = llvm::Error; 30 31 UdtRecordCompleter::UdtRecordCompleter(PdbTypeSymId id, 32 CompilerType &derived_ct, 33 clang::TagDecl &tag_decl, 34 PdbAstBuilder &ast_builder, 35 PdbIndex &index) 36 : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl), 37 m_ast_builder(ast_builder), m_index(index) { 38 CVType cvt = m_index.tpi().getType(m_id.index); 39 switch (cvt.kind()) { 40 case LF_ENUM: 41 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er)); 42 break; 43 case LF_UNION: 44 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur)); 45 break; 46 case LF_CLASS: 47 case LF_STRUCTURE: 48 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr)); 49 break; 50 default: 51 llvm_unreachable("unreachable!"); 52 } 53 } 54 55 clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex( 56 llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access, 57 llvm::Optional<uint64_t> vtable_idx) { 58 PdbTypeSymId type_id(ti); 59 clang::QualType qt = m_ast_builder.GetOrCreateType(type_id); 60 61 CVType udt_cvt = m_index.tpi().getType(ti); 62 63 std::unique_ptr<clang::CXXBaseSpecifier> base_spec = 64 m_ast_builder.clang().CreateBaseClassSpecifier( 65 qt.getAsOpaquePtr(), TranslateMemberAccess(access), 66 vtable_idx.hasValue(), udt_cvt.kind() == LF_CLASS); 67 lldbassert(base_spec); 68 69 m_bases.push_back( 70 std::make_pair(vtable_idx.getValueOr(0), std::move(base_spec))); 71 72 return qt; 73 } 74 75 void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx, 76 MemberAccess access, MethodOptions options, 77 MemberAttributes attrs) { 78 clang::QualType method_qt = 79 m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx)); 80 m_ast_builder.CompleteType(method_qt); 81 82 lldb::AccessType access_type = TranslateMemberAccess(access); 83 bool is_artificial = (options & MethodOptions::CompilerGenerated) == 84 MethodOptions::CompilerGenerated; 85 m_ast_builder.clang().AddMethodToCXXRecordType( 86 m_derived_ct.GetOpaqueQualType(), name.data(), nullptr, 87 m_ast_builder.ToCompilerType(method_qt), access_type, attrs.isVirtual(), 88 attrs.isStatic(), false, false, false, is_artificial); 89 } 90 91 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 92 BaseClassRecord &base) { 93 clang::QualType base_qt = 94 AddBaseClassForTypeIndex(base.Type, base.getAccess()); 95 96 auto decl = 97 m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr()); 98 lldbassert(decl); 99 100 auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset()); 101 m_layout.base_offsets.insert(std::make_pair(decl, offset)); 102 103 return llvm::Error::success(); 104 } 105 106 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 107 VirtualBaseClassRecord &base) { 108 AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex); 109 110 return Error::success(); 111 } 112 113 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 114 ListContinuationRecord &cont) { 115 return Error::success(); 116 } 117 118 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 119 VFPtrRecord &vfptr) { 120 return Error::success(); 121 } 122 123 Error UdtRecordCompleter::visitKnownMember( 124 CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) { 125 clang::QualType member_type = 126 m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type)); 127 128 m_ast_builder.CompleteType(member_type); 129 130 CompilerType member_ct = m_ast_builder.ToCompilerType(member_type); 131 132 lldb::AccessType access = 133 TranslateMemberAccess(static_data_member.getAccess()); 134 auto decl = TypeSystemClang::AddVariableToRecordType( 135 m_derived_ct, static_data_member.Name, member_ct, access); 136 137 // Static constant members may be a const[expr] declaration. 138 // Query the symbol's value as the variable initializer if valid. 139 if (member_ct.IsConst()) { 140 std::string qual_name = decl->getQualifiedNameAsString(); 141 142 auto results = 143 m_index.globals().findRecordsByName(qual_name, m_index.symrecords()); 144 145 for (const auto &result : results) { 146 if (result.second.kind() == SymbolKind::S_CONSTANT) { 147 ConstantSym constant(SymbolRecordKind::ConstantSym); 148 cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(result.second, 149 constant)); 150 151 clang::QualType qual_type = decl->getType(); 152 unsigned type_width = decl->getASTContext().getIntWidth(qual_type); 153 unsigned constant_width = constant.Value.getBitWidth(); 154 155 if (qual_type->isIntegralOrEnumerationType()) { 156 if (type_width >= constant_width) { 157 TypeSystemClang::SetIntegerInitializerForVariable( 158 decl, constant.Value.extOrTrunc(type_width)); 159 } else { 160 LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_AST), 161 "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) " 162 "which resolves to a wider constant value ({4} bits). " 163 "Ignoring constant.", 164 m_derived_ct.GetTypeName(), static_data_member.Name, 165 member_ct.GetTypeName(), type_width, constant_width); 166 } 167 } else { 168 lldb::BasicType basic_type_enum = member_ct.GetBasicTypeEnumeration(); 169 switch (basic_type_enum) { 170 case lldb::eBasicTypeFloat: 171 case lldb::eBasicTypeDouble: 172 case lldb::eBasicTypeLongDouble: 173 if (type_width == constant_width) { 174 TypeSystemClang::SetFloatingInitializerForVariable( 175 decl, basic_type_enum == lldb::eBasicTypeFloat 176 ? llvm::APFloat(constant.Value.bitsToFloat()) 177 : llvm::APFloat(constant.Value.bitsToDouble())); 178 decl->setConstexpr(true); 179 } else { 180 LLDB_LOG( 181 GetLogIfAllCategoriesSet(LIBLLDB_LOG_AST), 182 "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) " 183 "which resolves to a constant value of mismatched width " 184 "({4} bits). Ignoring constant.", 185 m_derived_ct.GetTypeName(), static_data_member.Name, 186 member_ct.GetTypeName(), type_width, constant_width); 187 } 188 break; 189 default: 190 break; 191 } 192 } 193 break; 194 } 195 } 196 } 197 198 // FIXME: Add a PdbSymUid namespace for field list members and update 199 // the m_uid_to_decl map with this decl. 200 return Error::success(); 201 } 202 203 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 204 NestedTypeRecord &nested) { 205 return Error::success(); 206 } 207 208 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 209 DataMemberRecord &data_member) { 210 211 uint64_t offset = data_member.FieldOffset * 8; 212 uint32_t bitfield_width = 0; 213 214 TypeIndex ti(data_member.Type); 215 if (!ti.isSimple()) { 216 CVType cvt = m_index.tpi().getType(ti); 217 if (cvt.kind() == LF_BITFIELD) { 218 BitFieldRecord bfr; 219 llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr)); 220 offset += bfr.BitOffset; 221 bitfield_width = bfr.BitSize; 222 ti = bfr.Type; 223 } 224 } 225 226 clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti)); 227 m_ast_builder.CompleteType(member_qt); 228 229 lldb::AccessType access = TranslateMemberAccess(data_member.getAccess()); 230 231 clang::FieldDecl *decl = TypeSystemClang::AddFieldToRecordType( 232 m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt), 233 access, bitfield_width); 234 // FIXME: Add a PdbSymUid namespace for field list members and update 235 // the m_uid_to_decl map with this decl. 236 237 m_layout.field_offsets.insert(std::make_pair(decl, offset)); 238 239 return Error::success(); 240 } 241 242 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 243 OneMethodRecord &one_method) { 244 AddMethod(one_method.Name, one_method.Type, one_method.getAccess(), 245 one_method.getOptions(), one_method.Attrs); 246 247 return Error::success(); 248 } 249 250 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 251 OverloadedMethodRecord &overloaded) { 252 TypeIndex method_list_idx = overloaded.MethodList; 253 254 CVType method_list_type = m_index.tpi().getType(method_list_idx); 255 assert(method_list_type.kind() == LF_METHODLIST); 256 257 MethodOverloadListRecord method_list; 258 llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>( 259 method_list_type, method_list)); 260 261 for (const OneMethodRecord &method : method_list.Methods) 262 AddMethod(overloaded.Name, method.Type, method.getAccess(), 263 method.getOptions(), method.Attrs); 264 265 return Error::success(); 266 } 267 268 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, 269 EnumeratorRecord &enumerator) { 270 Declaration decl; 271 llvm::StringRef name = DropNameScope(enumerator.getName()); 272 273 m_ast_builder.clang().AddEnumerationValueToEnumerationType( 274 m_derived_ct, decl, name.str().c_str(), enumerator.Value); 275 return Error::success(); 276 } 277 278 void UdtRecordCompleter::complete() { 279 // Ensure the correct order for virtual bases. 280 std::stable_sort(m_bases.begin(), m_bases.end(), 281 [](const IndexedBase &lhs, const IndexedBase &rhs) { 282 return lhs.first < rhs.first; 283 }); 284 285 std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases; 286 bases.reserve(m_bases.size()); 287 for (auto &ib : m_bases) 288 bases.push_back(std::move(ib.second)); 289 290 TypeSystemClang &clang = m_ast_builder.clang(); 291 clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases)); 292 293 clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType()); 294 TypeSystemClang::BuildIndirectFields(m_derived_ct); 295 TypeSystemClang::CompleteTagDeclarationDefinition(m_derived_ct); 296 297 if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) { 298 m_ast_builder.importer().SetRecordLayout(record_decl, m_layout); 299 } 300 } 301