Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 1 | #include "PdbAstBuilder.h" |
| 2 | |
| 3 | #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" |
| 4 | #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" |
| 5 | #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" |
| 6 | #include "llvm/DebugInfo/CodeView/SymbolRecord.h" |
| 7 | #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" |
| 8 | #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" |
| 9 | #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 10 | #include "llvm/DebugInfo/PDB/Native/DbiStream.h" |
| 11 | #include "llvm/DebugInfo/PDB/Native/PublicsStream.h" |
| 12 | #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 13 | #include "llvm/DebugInfo/PDB/Native/TpiStream.h" |
| 14 | #include "llvm/Demangle/MicrosoftDemangle.h" |
| 15 | |
| 16 | #include "lldb/Core/Module.h" |
| 17 | #include "lldb/Symbol/ClangASTContext.h" |
| 18 | #include "lldb/Symbol/ClangExternalASTSourceCommon.h" |
| 19 | #include "lldb/Symbol/ClangUtil.h" |
| 20 | #include "lldb/Symbol/ObjectFile.h" |
| 21 | #include "lldb/Utility/LLDBAssert.h" |
| 22 | |
| 23 | #include "PdbUtil.h" |
| 24 | #include "UdtRecordCompleter.h" |
| 25 | |
| 26 | using namespace lldb_private; |
| 27 | using namespace lldb_private::npdb; |
| 28 | using namespace llvm::codeview; |
| 29 | using namespace llvm::pdb; |
| 30 | |
| 31 | static llvm::Optional<PdbCompilandSymId> FindSymbolScope(PdbIndex &index, |
| 32 | PdbCompilandSymId id) { |
| 33 | CVSymbol sym = index.ReadSymbolRecord(id); |
| 34 | if (symbolOpensScope(sym.kind())) { |
| 35 | // If this exact symbol opens a scope, we can just directly access its |
| 36 | // parent. |
| 37 | id.offset = getScopeParentOffset(sym); |
| 38 | // Global symbols have parent offset of 0. Return llvm::None to indicate |
| 39 | // this. |
| 40 | if (id.offset == 0) |
| 41 | return llvm::None; |
| 42 | return id; |
| 43 | } |
| 44 | |
| 45 | // Otherwise we need to start at the beginning and iterate forward until we |
| 46 | // reach (or pass) this particular symbol |
| 47 | CompilandIndexItem &cii = index.compilands().GetOrCreateCompiland(id.modi); |
| 48 | const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray(); |
| 49 | |
| 50 | auto begin = syms.begin(); |
| 51 | auto end = syms.at(id.offset); |
| 52 | std::vector<PdbCompilandSymId> scope_stack; |
| 53 | |
| 54 | while (begin != end) { |
| 55 | if (id.offset == begin.offset()) { |
| 56 | // We have a match! Return the top of the stack |
| 57 | if (scope_stack.empty()) |
| 58 | return llvm::None; |
| 59 | return scope_stack.back(); |
| 60 | } |
| 61 | if (begin.offset() > id.offset) { |
| 62 | // We passed it. We couldn't even find this symbol record. |
| 63 | lldbassert(false && "Invalid compiland symbol id!"); |
| 64 | return llvm::None; |
| 65 | } |
| 66 | |
| 67 | // We haven't found the symbol yet. Check if we need to open or close the |
| 68 | // scope stack. |
| 69 | if (symbolOpensScope(begin->kind())) { |
| 70 | // We can use the end offset of the scope to determine whether or not |
| 71 | // we can just outright skip this entire scope. |
| 72 | uint32_t scope_end = getScopeEndOffset(*begin); |
| 73 | if (scope_end < id.modi) { |
| 74 | begin = syms.at(scope_end); |
| 75 | } else { |
| 76 | // The symbol we're looking for is somewhere in this scope. |
| 77 | scope_stack.emplace_back(id.modi, begin.offset()); |
| 78 | } |
| 79 | } else if (symbolEndsScope(begin->kind())) { |
| 80 | scope_stack.pop_back(); |
| 81 | } |
| 82 | ++begin; |
| 83 | } |
| 84 | |
| 85 | return llvm::None; |
| 86 | } |
| 87 | |
| 88 | static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) { |
| 89 | switch (cr.Kind) { |
| 90 | case TypeRecordKind::Class: |
| 91 | return clang::TTK_Class; |
| 92 | case TypeRecordKind::Struct: |
| 93 | return clang::TTK_Struct; |
| 94 | case TypeRecordKind::Union: |
| 95 | return clang::TTK_Union; |
| 96 | case TypeRecordKind::Interface: |
| 97 | return clang::TTK_Interface; |
| 98 | case TypeRecordKind::Enum: |
| 99 | return clang::TTK_Enum; |
| 100 | default: |
| 101 | lldbassert(false && "Invalid tag record kind!"); |
| 102 | return clang::TTK_Struct; |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | static bool IsCVarArgsFunction(llvm::ArrayRef<TypeIndex> args) { |
| 107 | if (args.empty()) |
| 108 | return false; |
| 109 | return args.back() == TypeIndex::None(); |
| 110 | } |
| 111 | |
| 112 | static bool |
| 113 | AnyScopesHaveTemplateParams(llvm::ArrayRef<llvm::ms_demangle::Node *> scopes) { |
| 114 | for (llvm::ms_demangle::Node *n : scopes) { |
| 115 | auto *idn = static_cast<llvm::ms_demangle::IdentifierNode *>(n); |
| 116 | if (idn->TemplateParams) |
| 117 | return true; |
| 118 | } |
| 119 | return false; |
| 120 | } |
| 121 | |
| 122 | static ClangASTContext &GetClangASTContext(ObjectFile &obj) { |
| 123 | TypeSystem *ts = |
| 124 | obj.GetModule()->GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); |
| 125 | lldbassert(ts); |
| 126 | return static_cast<ClangASTContext &>(*ts); |
| 127 | } |
| 128 | |
| 129 | static llvm::Optional<clang::CallingConv> |
| 130 | TranslateCallingConvention(llvm::codeview::CallingConvention conv) { |
| 131 | using CC = llvm::codeview::CallingConvention; |
| 132 | switch (conv) { |
| 133 | |
| 134 | case CC::NearC: |
| 135 | case CC::FarC: |
| 136 | return clang::CallingConv::CC_C; |
| 137 | case CC::NearPascal: |
| 138 | case CC::FarPascal: |
| 139 | return clang::CallingConv::CC_X86Pascal; |
| 140 | case CC::NearFast: |
| 141 | case CC::FarFast: |
| 142 | return clang::CallingConv::CC_X86FastCall; |
| 143 | case CC::NearStdCall: |
| 144 | case CC::FarStdCall: |
| 145 | return clang::CallingConv::CC_X86StdCall; |
| 146 | case CC::ThisCall: |
| 147 | return clang::CallingConv::CC_X86ThisCall; |
| 148 | case CC::NearVector: |
| 149 | return clang::CallingConv::CC_X86VectorCall; |
| 150 | default: |
| 151 | return llvm::None; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | static llvm::Optional<CVTagRecord> |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 156 | GetNestedTagDefinition(const NestedTypeRecord &Record, |
| 157 | const CVTagRecord &parent, TpiStream &tpi) { |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 158 | // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it |
| 159 | // is also used to indicate the primary definition of a nested class. That is |
| 160 | // to say, if you have: |
| 161 | // struct A { |
| 162 | // struct B {}; |
| 163 | // using C = B; |
| 164 | // }; |
| 165 | // Then in the debug info, this will appear as: |
| 166 | // LF_STRUCTURE `A::B` [type index = N] |
| 167 | // LF_STRUCTURE `A` |
| 168 | // LF_NESTTYPE [name = `B`, index = N] |
| 169 | // LF_NESTTYPE [name = `C`, index = N] |
| 170 | // In order to accurately reconstruct the decl context hierarchy, we need to |
| 171 | // know which ones are actual definitions and which ones are just aliases. |
| 172 | |
| 173 | // If it's a simple type, then this is something like `using foo = int`. |
| 174 | if (Record.Type.isSimple()) |
| 175 | return llvm::None; |
| 176 | |
| 177 | CVType cvt = tpi.getType(Record.Type); |
| 178 | |
| 179 | if (!IsTagRecord(cvt)) |
| 180 | return llvm::None; |
| 181 | |
| 182 | // If it's an inner definition, then treat whatever name we have here as a |
| 183 | // single component of a mangled name. So we can inject it into the parent's |
| 184 | // mangled name to see if it matches. |
| 185 | CVTagRecord child = CVTagRecord::create(cvt); |
| 186 | std::string qname = parent.asTag().getUniqueName(); |
| 187 | if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4) |
| 188 | return llvm::None; |
| 189 | |
| 190 | // qname[3] is the tag type identifier (struct, class, union, etc). Since the |
| 191 | // inner tag type is not necessarily the same as the outer tag type, re-write |
| 192 | // it to match the inner tag type. |
| 193 | qname[3] = child.asTag().getUniqueName()[3]; |
Zachary Turner | cb67fad | 2018-12-18 23:12:08 +0000 | [diff] [blame] | 194 | std::string piece; |
| 195 | if (qname[3] == 'W') |
| 196 | piece = "4"; |
| 197 | piece += Record.Name; |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 198 | piece.push_back('@'); |
| 199 | qname.insert(4, std::move(piece)); |
| 200 | if (qname != child.asTag().UniqueName) |
| 201 | return llvm::None; |
| 202 | |
| 203 | return std::move(child); |
| 204 | } |
| 205 | |
| 206 | PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index) |
| 207 | : m_index(index), m_clang(GetClangASTContext(obj)) { |
| 208 | BuildParentMap(); |
| 209 | } |
| 210 | |
| 211 | clang::DeclContext &PdbAstBuilder::GetTranslationUnitDecl() { |
| 212 | return *m_clang.GetTranslationUnitDecl(); |
| 213 | } |
| 214 | |
| 215 | std::pair<clang::DeclContext *, std::string> |
| 216 | PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) { |
| 217 | // FIXME: Move this to GetDeclContextContainingUID. |
| 218 | |
| 219 | llvm::ms_demangle::Demangler demangler; |
| 220 | StringView sv(record.UniqueName.begin(), record.UniqueName.size()); |
| 221 | llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv); |
| 222 | llvm::ms_demangle::IdentifierNode *idn = |
| 223 | ttn->QualifiedName->getUnqualifiedIdentifier(); |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 224 | std::string uname = idn->toString(llvm::ms_demangle::OF_NoTagSpecifier); |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 225 | |
| 226 | llvm::ms_demangle::NodeArrayNode *name_components = |
| 227 | ttn->QualifiedName->Components; |
| 228 | llvm::ArrayRef<llvm::ms_demangle::Node *> scopes(name_components->Nodes, |
| 229 | name_components->Count - 1); |
| 230 | |
| 231 | clang::DeclContext *context = m_clang.GetTranslationUnitDecl(); |
| 232 | |
| 233 | // If this type doesn't have a parent type in the debug info, then the best we |
| 234 | // can do is to say that it's either a series of namespaces (if the scope is |
| 235 | // non-empty), or the translation unit (if the scope is empty). |
| 236 | auto parent_iter = m_parent_types.find(ti); |
| 237 | if (parent_iter == m_parent_types.end()) { |
| 238 | if (scopes.empty()) |
| 239 | return {context, uname}; |
| 240 | |
| 241 | // If there is no parent in the debug info, but some of the scopes have |
| 242 | // template params, then this is a case of bad debug info. See, for |
| 243 | // example, llvm.org/pr39607. We don't want to create an ambiguity between |
| 244 | // a NamespaceDecl and a CXXRecordDecl, so instead we create a class at |
| 245 | // global scope with the fully qualified name. |
| 246 | if (AnyScopesHaveTemplateParams(scopes)) |
| 247 | return {context, record.Name}; |
| 248 | |
| 249 | for (llvm::ms_demangle::Node *scope : scopes) { |
| 250 | auto *nii = static_cast<llvm::ms_demangle::NamedIdentifierNode *>(scope); |
| 251 | std::string str = nii->toString(); |
| 252 | context = m_clang.GetUniqueNamespaceDeclaration(str.c_str(), context); |
| 253 | } |
| 254 | return {context, uname}; |
| 255 | } |
| 256 | |
| 257 | // Otherwise, all we need to do is get the parent type of this type and |
| 258 | // recurse into our lazy type creation / AST reconstruction logic to get an |
| 259 | // LLDB TypeSP for the parent. This will cause the AST to automatically get |
| 260 | // the right DeclContext created for any parent. |
| 261 | clang::QualType parent_qt = GetOrCreateType(parent_iter->second); |
| 262 | |
| 263 | context = clang::TagDecl::castToDeclContext(parent_qt->getAsTagDecl()); |
| 264 | return {context, uname}; |
| 265 | } |
| 266 | |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 267 | static bool IsUniqueNameEnumTag(llvm::StringRef unique_name) { |
| 268 | if (unique_name.size() < 4) |
| 269 | return false; |
| 270 | return unique_name[3] == 'W'; |
| 271 | } |
| 272 | |
| 273 | static std::string GetParentUniqueName(llvm::StringRef unique_name) { |
| 274 | if (unique_name.size() < 4) |
| 275 | return unique_name; |
| 276 | size_t start = IsUniqueNameEnumTag(unique_name) ? 5 : 4; |
| 277 | size_t end = unique_name.find('@'); |
| 278 | if (end == llvm::StringRef::npos) |
| 279 | return unique_name; |
| 280 | std::string result = unique_name.str(); |
| 281 | return result.erase(start, end - start + 1); |
| 282 | } |
| 283 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 284 | void PdbAstBuilder::BuildParentMap() { |
| 285 | LazyRandomTypeCollection &types = m_index.tpi().typeCollection(); |
| 286 | |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 287 | llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full; |
| 288 | llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward; |
| 289 | |
| 290 | struct RecordIndices { |
| 291 | TypeIndex forward; |
| 292 | TypeIndex full; |
| 293 | }; |
| 294 | |
| 295 | llvm::StringMap<RecordIndices> record_indices; |
| 296 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 297 | for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { |
| 298 | CVType type = types.getType(*ti); |
| 299 | if (!IsTagRecord(type)) |
| 300 | continue; |
| 301 | |
| 302 | CVTagRecord tag = CVTagRecord::create(type); |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 303 | |
| 304 | RecordIndices &indices = record_indices[tag.asTag().getUniqueName()]; |
| 305 | if (tag.asTag().isForwardRef()) |
| 306 | indices.forward = *ti; |
| 307 | else |
| 308 | indices.full = *ti; |
| 309 | |
| 310 | if (indices.full != TypeIndex::None() && |
| 311 | indices.forward != TypeIndex::None()) { |
| 312 | forward_to_full[indices.forward] = indices.full; |
| 313 | full_to_forward[indices.full] = indices.forward; |
| 314 | } |
| 315 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 316 | // We're looking for LF_NESTTYPE records in the field list, so ignore |
| 317 | // forward references (no field list), and anything without a nested class |
| 318 | // (since there won't be any LF_NESTTYPE records). |
| 319 | if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass()) |
| 320 | continue; |
| 321 | |
| 322 | struct ProcessTpiStream : public TypeVisitorCallbacks { |
| 323 | ProcessTpiStream(PdbIndex &index, TypeIndex parent, |
| 324 | const CVTagRecord &parent_cvt, |
| 325 | llvm::DenseMap<TypeIndex, TypeIndex> &parents) |
| 326 | : index(index), parents(parents), parent(parent), |
| 327 | parent_cvt(parent_cvt) {} |
| 328 | |
| 329 | PdbIndex &index; |
| 330 | llvm::DenseMap<TypeIndex, TypeIndex> &parents; |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 331 | |
| 332 | unsigned unnamed_type_index = 1; |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 333 | TypeIndex parent; |
| 334 | const CVTagRecord &parent_cvt; |
| 335 | |
| 336 | llvm::Error visitKnownMember(CVMemberRecord &CVR, |
| 337 | NestedTypeRecord &Record) override { |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 338 | std::string unnamed_type_name; |
| 339 | if (Record.Name.empty()) { |
| 340 | unnamed_type_name = |
| 341 | llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str(); |
| 342 | Record.Name = unnamed_type_name; |
| 343 | ++unnamed_type_index; |
| 344 | } |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 345 | llvm::Optional<CVTagRecord> tag = |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 346 | GetNestedTagDefinition(Record, parent_cvt, index.tpi()); |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 347 | if (!tag) |
| 348 | return llvm::ErrorSuccess(); |
| 349 | |
| 350 | parents[Record.Type] = parent; |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 351 | return llvm::ErrorSuccess(); |
| 352 | } |
| 353 | }; |
| 354 | |
| 355 | CVType field_list = m_index.tpi().getType(tag.asTag().FieldList); |
| 356 | ProcessTpiStream process(m_index, *ti, tag, m_parent_types); |
| 357 | llvm::Error error = visitMemberRecordStream(field_list.data(), process); |
| 358 | if (error) |
| 359 | llvm::consumeError(std::move(error)); |
| 360 | } |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 361 | |
| 362 | // Now that we know the forward -> full mapping of all type indices, we can |
| 363 | // re-write all the indices. At the end of this process, we want a mapping |
| 364 | // consisting of fwd -> full and full -> full for all child -> parent indices. |
| 365 | // We can re-write the values in place, but for the keys, we must save them |
| 366 | // off so that we don't modify the map in place while also iterating it. |
| 367 | std::vector<TypeIndex> full_keys; |
| 368 | std::vector<TypeIndex> fwd_keys; |
| 369 | for (auto &entry : m_parent_types) { |
Zachary Turner | 489cfbd | 2019-01-02 21:04:22 +0000 | [diff] [blame] | 370 | TypeIndex key = entry.first; |
| 371 | TypeIndex value = entry.second; |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 372 | |
| 373 | auto iter = forward_to_full.find(value); |
| 374 | if (iter != forward_to_full.end()) |
| 375 | entry.second = iter->second; |
| 376 | |
| 377 | iter = forward_to_full.find(key); |
| 378 | if (iter != forward_to_full.end()) |
| 379 | fwd_keys.push_back(key); |
| 380 | else |
| 381 | full_keys.push_back(key); |
| 382 | } |
| 383 | for (TypeIndex fwd : fwd_keys) { |
| 384 | TypeIndex full = forward_to_full[fwd]; |
| 385 | m_parent_types[full] = m_parent_types[fwd]; |
| 386 | } |
| 387 | for (TypeIndex full : full_keys) { |
| 388 | TypeIndex fwd = full_to_forward[full]; |
| 389 | m_parent_types[fwd] = m_parent_types[full]; |
| 390 | } |
| 391 | |
| 392 | // Now that |
| 393 | } |
| 394 | |
| 395 | static bool isLocalVariableType(SymbolKind K) { |
| 396 | switch (K) { |
| 397 | case S_REGISTER: |
| 398 | case S_REGREL32: |
| 399 | case S_LOCAL: |
| 400 | return true; |
| 401 | default: |
| 402 | break; |
| 403 | } |
| 404 | return false; |
| 405 | } |
| 406 | |
| 407 | static std::string |
| 408 | RenderScopeList(llvm::ArrayRef<llvm::ms_demangle::Node *> nodes) { |
| 409 | lldbassert(!nodes.empty()); |
| 410 | |
| 411 | std::string result = nodes.front()->toString(); |
| 412 | nodes = nodes.drop_front(); |
| 413 | while (!nodes.empty()) { |
| 414 | result += "::"; |
| 415 | result += nodes.front()->toString(llvm::ms_demangle::OF_NoTagSpecifier); |
| 416 | nodes = nodes.drop_front(); |
| 417 | } |
| 418 | return result; |
| 419 | } |
| 420 | |
| 421 | static llvm::Optional<PublicSym32> FindPublicSym(const SegmentOffset &addr, |
| 422 | SymbolStream &syms, |
| 423 | PublicsStream &publics) { |
| 424 | llvm::FixedStreamArray<ulittle32_t> addr_map = publics.getAddressMap(); |
| 425 | auto iter = std::lower_bound( |
| 426 | addr_map.begin(), addr_map.end(), addr, |
| 427 | [&](const ulittle32_t &x, const SegmentOffset &y) { |
| 428 | CVSymbol s1 = syms.readRecord(x); |
| 429 | lldbassert(s1.kind() == S_PUB32); |
| 430 | PublicSym32 p1; |
| 431 | llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(s1, p1)); |
| 432 | if (p1.Segment < y.segment) |
| 433 | return true; |
| 434 | return p1.Offset < y.offset; |
| 435 | }); |
| 436 | if (iter == addr_map.end()) |
| 437 | return llvm::None; |
| 438 | CVSymbol sym = syms.readRecord(*iter); |
| 439 | lldbassert(sym.kind() == S_PUB32); |
| 440 | PublicSym32 p; |
| 441 | llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym, p)); |
| 442 | if (p.Segment == addr.segment && p.Offset == addr.offset) |
| 443 | return p; |
| 444 | return llvm::None; |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 445 | } |
| 446 | |
| 447 | clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) { |
| 448 | CVSymbol cvs = m_index.ReadSymbolRecord(id); |
| 449 | |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 450 | if (isLocalVariableType(cvs.kind())) { |
| 451 | clang::DeclContext *scope = GetParentDeclContext(id); |
| 452 | clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope); |
| 453 | PdbCompilandSymId scope_id(id.modi, m_decl_to_status[scope_decl].uid); |
| 454 | return GetOrCreateVariableDecl(scope_id, id); |
| 455 | } |
| 456 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 457 | switch (cvs.kind()) { |
| 458 | case S_GPROC32: |
| 459 | case S_LPROC32: |
| 460 | return GetOrCreateFunctionDecl(id); |
| 461 | case S_GDATA32: |
| 462 | case S_LDATA32: |
| 463 | case S_GTHREAD32: |
| 464 | case S_CONSTANT: |
| 465 | // global variable |
| 466 | return nullptr; |
| 467 | case S_BLOCK32: |
| 468 | return GetOrCreateBlockDecl(id); |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 469 | default: |
| 470 | return nullptr; |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | clang::Decl *PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { |
| 475 | if (clang::Decl *result = TryGetDecl(uid)) |
| 476 | return result; |
| 477 | |
| 478 | clang::Decl *result = nullptr; |
| 479 | switch (uid.kind()) { |
| 480 | case PdbSymUidKind::CompilandSym: |
| 481 | result = GetOrCreateSymbolForId(uid.asCompilandSym()); |
| 482 | break; |
| 483 | case PdbSymUidKind::Type: { |
| 484 | clang::QualType qt = GetOrCreateType(uid.asTypeSym()); |
| 485 | if (auto *tag = qt->getAsTagDecl()) { |
| 486 | result = tag; |
| 487 | break; |
| 488 | } |
| 489 | return nullptr; |
| 490 | } |
| 491 | default: |
| 492 | return nullptr; |
| 493 | } |
| 494 | m_uid_to_decl[toOpaqueUid(uid)] = result; |
| 495 | return result; |
| 496 | } |
| 497 | |
| 498 | clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) { |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 499 | if (uid.kind() == PdbSymUidKind::CompilandSym) { |
| 500 | if (uid.asCompilandSym().offset == 0) |
| 501 | return &GetTranslationUnitDecl(); |
| 502 | } |
| 503 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 504 | clang::Decl *decl = GetOrCreateDeclForUid(uid); |
| 505 | if (!decl) |
| 506 | return nullptr; |
| 507 | |
| 508 | return clang::Decl::castToDeclContext(decl); |
| 509 | } |
| 510 | |
| 511 | clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) { |
| 512 | // We must do this *without* calling GetOrCreate on the current uid, as |
| 513 | // that would be an infinite recursion. |
| 514 | switch (uid.kind()) { |
| 515 | case PdbSymUidKind::CompilandSym: { |
| 516 | llvm::Optional<PdbCompilandSymId> scope = |
| 517 | FindSymbolScope(m_index, uid.asCompilandSym()); |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 518 | if (scope) |
| 519 | return GetOrCreateDeclContextForUid(*scope); |
| 520 | |
| 521 | CVSymbol sym = m_index.ReadSymbolRecord(uid.asCompilandSym()); |
| 522 | if (!SymbolHasAddress(sym)) |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 523 | return &GetTranslationUnitDecl(); |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 524 | SegmentOffset addr = GetSegmentAndOffset(sym); |
| 525 | llvm::Optional<PublicSym32> pub = |
| 526 | FindPublicSym(addr, m_index.symrecords(), m_index.publics()); |
| 527 | if (!pub) |
| 528 | return &GetTranslationUnitDecl(); |
| 529 | |
| 530 | llvm::ms_demangle::Demangler demangler; |
| 531 | StringView name{pub->Name.begin(), pub->Name.size()}; |
| 532 | llvm::ms_demangle::SymbolNode *node = demangler.parse(name); |
| 533 | if (!node) |
| 534 | return &GetTranslationUnitDecl(); |
| 535 | llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{ |
| 536 | node->Name->Components->Nodes, node->Name->Components->Count - 1}; |
| 537 | |
| 538 | if (!name_components.empty()) { |
| 539 | // Render the current list of scope nodes as a fully qualified name, and |
| 540 | // look it up in the debug info as a type name. If we find something, |
| 541 | // this is a type (which may itself be prefixed by a namespace). If we |
| 542 | // don't, this is a list of namespaces. |
| 543 | std::string qname = RenderScopeList(name_components); |
| 544 | std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname); |
| 545 | while (!matches.empty()) { |
| 546 | clang::QualType qt = GetOrCreateType(matches.back()); |
| 547 | clang::TagDecl *tag = qt->getAsTagDecl(); |
| 548 | if (tag) |
| 549 | return clang::TagDecl::castToDeclContext(tag); |
| 550 | matches.pop_back(); |
| 551 | } |
| 552 | } |
| 553 | |
| 554 | // It's not a type. It must be a series of namespaces. |
| 555 | clang::DeclContext *context = &GetTranslationUnitDecl(); |
| 556 | while (!name_components.empty()) { |
| 557 | std::string ns = name_components.front()->toString(); |
| 558 | context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context); |
| 559 | name_components = name_components.drop_front(); |
| 560 | } |
| 561 | return context; |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 562 | } |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 563 | case PdbSymUidKind::Type: { |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 564 | // It could be a namespace, class, or global. We don't support nested |
| 565 | // functions yet. Anyway, we just need to consult the parent type map. |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 566 | PdbTypeSymId type_id = uid.asTypeSym(); |
| 567 | auto iter = m_parent_types.find(type_id.index); |
| 568 | if (iter == m_parent_types.end()) |
| 569 | return &GetTranslationUnitDecl(); |
| 570 | return GetOrCreateDeclContextForUid(PdbTypeSymId(iter->second)); |
| 571 | } |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 572 | case PdbSymUidKind::FieldListMember: |
| 573 | // In this case the parent DeclContext is the one for the class that this |
| 574 | // member is inside of. |
| 575 | break; |
| 576 | default: |
| 577 | break; |
| 578 | } |
| 579 | return &GetTranslationUnitDecl(); |
| 580 | } |
| 581 | |
| 582 | bool PdbAstBuilder::CompleteType(clang::QualType qt) { |
| 583 | clang::TagDecl *tag = qt->getAsTagDecl(); |
| 584 | if (!tag) |
| 585 | return false; |
| 586 | |
| 587 | return CompleteTagDecl(*tag); |
| 588 | } |
| 589 | |
| 590 | bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) { |
| 591 | // If this is not in our map, it's an error. |
| 592 | auto status_iter = m_decl_to_status.find(&tag); |
| 593 | lldbassert(status_iter != m_decl_to_status.end()); |
| 594 | |
| 595 | // If it's already complete, just return. |
| 596 | DeclStatus &status = status_iter->second; |
| 597 | if (status.resolved) |
| 598 | return true; |
| 599 | |
| 600 | PdbTypeSymId type_id = PdbSymUid(status.uid).asTypeSym(); |
| 601 | |
| 602 | lldbassert(IsTagRecord(type_id, m_index.tpi())); |
| 603 | |
| 604 | clang::QualType tag_qt = m_clang.getASTContext()->getTypeDeclType(&tag); |
| 605 | ClangASTContext::SetHasExternalStorage(tag_qt.getAsOpaquePtr(), false); |
| 606 | |
| 607 | TypeIndex tag_ti = type_id.index; |
| 608 | CVType cvt = m_index.tpi().getType(tag_ti); |
| 609 | if (cvt.kind() == LF_MODIFIER) |
| 610 | tag_ti = LookThroughModifierRecord(cvt); |
| 611 | |
| 612 | PdbTypeSymId best_ti = GetBestPossibleDecl(tag_ti, m_index.tpi()); |
| 613 | cvt = m_index.tpi().getType(best_ti.index); |
| 614 | lldbassert(IsTagRecord(cvt)); |
| 615 | |
| 616 | if (IsForwardRefUdt(cvt)) { |
| 617 | // If we can't find a full decl for this forward ref anywhere in the debug |
| 618 | // info, then we have no way to complete it. |
| 619 | return false; |
| 620 | } |
| 621 | |
| 622 | TypeIndex field_list_ti = GetFieldListIndex(cvt); |
| 623 | CVType field_list_cvt = m_index.tpi().getType(field_list_ti); |
| 624 | if (field_list_cvt.kind() != LF_FIELDLIST) |
| 625 | return false; |
| 626 | |
| 627 | // Visit all members of this class, then perform any finalization necessary |
| 628 | // to complete the class. |
| 629 | CompilerType ct = ToCompilerType(tag_qt); |
| 630 | UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index.tpi()); |
| 631 | auto error = |
| 632 | llvm::codeview::visitMemberRecordStream(field_list_cvt.data(), completer); |
| 633 | completer.complete(); |
| 634 | |
| 635 | status.resolved = true; |
| 636 | if (!error) |
| 637 | return true; |
| 638 | |
| 639 | llvm::consumeError(std::move(error)); |
| 640 | return false; |
| 641 | } |
| 642 | |
| 643 | clang::QualType PdbAstBuilder::CreateSimpleType(TypeIndex ti) { |
| 644 | if (ti == TypeIndex::NullptrT()) |
| 645 | return GetBasicType(lldb::eBasicTypeNullPtr); |
| 646 | |
| 647 | if (ti.getSimpleMode() != SimpleTypeMode::Direct) { |
| 648 | clang::QualType direct_type = GetOrCreateType(ti.makeDirect()); |
| 649 | return m_clang.getASTContext()->getPointerType(direct_type); |
| 650 | } |
| 651 | |
| 652 | if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated) |
| 653 | return {}; |
| 654 | |
| 655 | lldb::BasicType bt = GetCompilerTypeForSimpleKind(ti.getSimpleKind()); |
| 656 | if (bt == lldb::eBasicTypeInvalid) |
| 657 | return {}; |
| 658 | |
| 659 | return GetBasicType(bt); |
| 660 | } |
| 661 | |
| 662 | clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) { |
| 663 | clang::QualType pointee_type = GetOrCreateType(pointer.ReferentType); |
| 664 | |
| 665 | if (pointer.isPointerToMember()) { |
| 666 | MemberPointerInfo mpi = pointer.getMemberInfo(); |
| 667 | clang::QualType class_type = GetOrCreateType(mpi.ContainingType); |
| 668 | |
| 669 | return m_clang.getASTContext()->getMemberPointerType( |
| 670 | pointee_type, class_type.getTypePtr()); |
| 671 | } |
| 672 | |
| 673 | clang::QualType pointer_type; |
| 674 | if (pointer.getMode() == PointerMode::LValueReference) |
| 675 | pointer_type = |
| 676 | m_clang.getASTContext()->getLValueReferenceType(pointee_type); |
| 677 | else if (pointer.getMode() == PointerMode::RValueReference) |
| 678 | pointer_type = |
| 679 | m_clang.getASTContext()->getRValueReferenceType(pointee_type); |
| 680 | else |
| 681 | pointer_type = m_clang.getASTContext()->getPointerType(pointee_type); |
| 682 | |
| 683 | if ((pointer.getOptions() & PointerOptions::Const) != PointerOptions::None) |
| 684 | pointer_type.addConst(); |
| 685 | |
| 686 | if ((pointer.getOptions() & PointerOptions::Volatile) != PointerOptions::None) |
| 687 | pointer_type.addVolatile(); |
| 688 | |
| 689 | if ((pointer.getOptions() & PointerOptions::Restrict) != PointerOptions::None) |
| 690 | pointer_type.addRestrict(); |
| 691 | |
| 692 | return pointer_type; |
| 693 | } |
| 694 | |
| 695 | clang::QualType |
| 696 | PdbAstBuilder::CreateModifierType(const ModifierRecord &modifier) { |
| 697 | |
| 698 | clang::QualType unmodified_type = GetOrCreateType(modifier.ModifiedType); |
| 699 | |
| 700 | if ((modifier.Modifiers & ModifierOptions::Const) != ModifierOptions::None) |
| 701 | unmodified_type.addConst(); |
| 702 | if ((modifier.Modifiers & ModifierOptions::Volatile) != ModifierOptions::None) |
| 703 | unmodified_type.addVolatile(); |
| 704 | |
| 705 | return unmodified_type; |
| 706 | } |
| 707 | |
| 708 | clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id, |
| 709 | const TagRecord &record) { |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 710 | clang::DeclContext *context = nullptr; |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 711 | std::string uname; |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 712 | std::tie(context, uname) = CreateDeclInfoForType(record, id.index); |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 713 | clang::TagTypeKind ttk = TranslateUdtKind(record); |
| 714 | lldb::AccessType access = |
| 715 | (ttk == clang::TTK_Class) ? lldb::eAccessPrivate : lldb::eAccessPublic; |
| 716 | |
| 717 | ClangASTMetadata metadata; |
| 718 | metadata.SetUserID(toOpaqueUid(id)); |
| 719 | metadata.SetIsDynamicCXXType(false); |
| 720 | |
| 721 | CompilerType ct = |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 722 | m_clang.CreateRecordType(context, access, uname.c_str(), ttk, |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 723 | lldb::eLanguageTypeC_plus_plus, &metadata); |
| 724 | |
| 725 | lldbassert(ct.IsValid()); |
| 726 | |
| 727 | ClangASTContext::StartTagDeclarationDefinition(ct); |
| 728 | |
| 729 | // Even if it's possible, don't complete it at this point. Just mark it |
| 730 | // forward resolved, and if/when LLDB needs the full definition, it can |
| 731 | // ask us. |
| 732 | clang::QualType result = |
| 733 | clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType()); |
| 734 | |
| 735 | ClangASTContext::SetHasExternalStorage(result.getAsOpaquePtr(), true); |
| 736 | return result; |
| 737 | } |
| 738 | |
| 739 | clang::Decl *PdbAstBuilder::TryGetDecl(PdbSymUid uid) const { |
| 740 | auto iter = m_uid_to_decl.find(toOpaqueUid(uid)); |
| 741 | if (iter != m_uid_to_decl.end()) |
| 742 | return iter->second; |
| 743 | return nullptr; |
| 744 | } |
| 745 | |
| 746 | clang::NamespaceDecl * |
| 747 | PdbAstBuilder::GetOrCreateNamespaceDecl(llvm::StringRef name, |
| 748 | clang::DeclContext &context) { |
| 749 | return m_clang.GetUniqueNamespaceDeclaration(name.str().c_str(), &context); |
| 750 | } |
| 751 | |
| 752 | clang::BlockDecl * |
| 753 | PdbAstBuilder::GetOrCreateBlockDecl(PdbCompilandSymId block_id) { |
| 754 | if (clang::Decl *decl = TryGetDecl(block_id)) |
| 755 | return llvm::dyn_cast<clang::BlockDecl>(decl); |
| 756 | |
| 757 | clang::DeclContext *scope = GetParentDeclContext(block_id); |
| 758 | |
| 759 | clang::BlockDecl *block_decl = m_clang.CreateBlockDeclaration(scope); |
| 760 | m_uid_to_decl.insert({toOpaqueUid(block_id), block_decl}); |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 761 | |
| 762 | DeclStatus status; |
| 763 | status.resolved = true; |
| 764 | status.uid = toOpaqueUid(block_id); |
| 765 | m_decl_to_status.insert({block_decl, status}); |
| 766 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 767 | return block_decl; |
| 768 | } |
| 769 | |
Zachary Turner | 3790029 | 2018-12-20 23:32:37 +0000 | [diff] [blame] | 770 | clang::VarDecl *PdbAstBuilder::CreateVariableDecl(PdbSymUid uid, CVSymbol sym, |
| 771 | clang::DeclContext &scope) { |
| 772 | VariableInfo var_info = GetVariableNameInfo(sym); |
| 773 | clang::QualType qt = GetOrCreateType(var_info.type); |
| 774 | |
| 775 | clang::VarDecl *var_decl = m_clang.CreateVariableDeclaration( |
| 776 | &scope, var_info.name.str().c_str(), qt); |
| 777 | |
| 778 | m_uid_to_decl[toOpaqueUid(uid)] = var_decl; |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 779 | DeclStatus status; |
| 780 | status.resolved = true; |
| 781 | status.uid = toOpaqueUid(uid); |
| 782 | m_decl_to_status.insert({var_decl, status}); |
Zachary Turner | 3790029 | 2018-12-20 23:32:37 +0000 | [diff] [blame] | 783 | return var_decl; |
| 784 | } |
| 785 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 786 | clang::VarDecl * |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 787 | PdbAstBuilder::GetOrCreateVariableDecl(PdbCompilandSymId scope_id, |
| 788 | PdbCompilandSymId var_id) { |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 789 | if (clang::Decl *decl = TryGetDecl(var_id)) |
| 790 | return llvm::dyn_cast<clang::VarDecl>(decl); |
| 791 | |
| 792 | clang::DeclContext *scope = GetOrCreateDeclContextForUid(scope_id); |
| 793 | |
Zachary Turner | 3790029 | 2018-12-20 23:32:37 +0000 | [diff] [blame] | 794 | CVSymbol sym = m_index.ReadSymbolRecord(var_id); |
| 795 | return CreateVariableDecl(PdbSymUid(var_id), sym, *scope); |
| 796 | } |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 797 | |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 798 | clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) { |
Zachary Turner | 3790029 | 2018-12-20 23:32:37 +0000 | [diff] [blame] | 799 | if (clang::Decl *decl = TryGetDecl(var_id)) |
| 800 | return llvm::dyn_cast<clang::VarDecl>(decl); |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 801 | |
Zachary Turner | 3790029 | 2018-12-20 23:32:37 +0000 | [diff] [blame] | 802 | CVSymbol sym = m_index.ReadSymbolRecord(var_id); |
| 803 | return CreateVariableDecl(PdbSymUid(var_id), sym, GetTranslationUnitDecl()); |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 804 | } |
| 805 | |
| 806 | clang::QualType PdbAstBuilder::GetBasicType(lldb::BasicType type) { |
| 807 | CompilerType ct = m_clang.GetBasicType(type); |
| 808 | return clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType()); |
| 809 | } |
| 810 | |
| 811 | clang::QualType PdbAstBuilder::CreateType(PdbTypeSymId type) { |
| 812 | if (type.index.isSimple()) |
| 813 | return CreateSimpleType(type.index); |
| 814 | |
| 815 | CVType cvt = m_index.tpi().getType(type.index); |
| 816 | |
| 817 | if (cvt.kind() == LF_MODIFIER) { |
| 818 | ModifierRecord modifier; |
| 819 | llvm::cantFail( |
| 820 | TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier)); |
| 821 | return CreateModifierType(modifier); |
| 822 | } |
| 823 | |
| 824 | if (cvt.kind() == LF_POINTER) { |
| 825 | PointerRecord pointer; |
| 826 | llvm::cantFail( |
| 827 | TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer)); |
| 828 | return CreatePointerType(pointer); |
| 829 | } |
| 830 | |
| 831 | if (IsTagRecord(cvt)) { |
| 832 | CVTagRecord tag = CVTagRecord::create(cvt); |
| 833 | if (tag.kind() == CVTagRecord::Union) |
| 834 | return CreateRecordType(type.index, tag.asUnion()); |
| 835 | if (tag.kind() == CVTagRecord::Enum) |
| 836 | return CreateEnumType(type.index, tag.asEnum()); |
| 837 | return CreateRecordType(type.index, tag.asClass()); |
| 838 | } |
| 839 | |
| 840 | if (cvt.kind() == LF_ARRAY) { |
| 841 | ArrayRecord ar; |
| 842 | llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar)); |
| 843 | return CreateArrayType(ar); |
| 844 | } |
| 845 | |
| 846 | if (cvt.kind() == LF_PROCEDURE) { |
| 847 | ProcedureRecord pr; |
| 848 | llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr)); |
| 849 | return CreateProcedureType(pr); |
| 850 | } |
| 851 | |
| 852 | return {}; |
| 853 | } |
| 854 | |
| 855 | clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) { |
| 856 | lldb::user_id_t uid = toOpaqueUid(type); |
| 857 | auto iter = m_uid_to_type.find(uid); |
| 858 | if (iter != m_uid_to_type.end()) |
| 859 | return iter->second; |
| 860 | |
| 861 | PdbTypeSymId best_type = GetBestPossibleDecl(type, m_index.tpi()); |
| 862 | |
| 863 | clang::QualType qt; |
| 864 | if (best_type.index != type.index) { |
| 865 | // This is a forward decl. Call GetOrCreate on the full decl, then map the |
| 866 | // forward decl id to the full decl QualType. |
| 867 | clang::QualType qt = GetOrCreateType(best_type); |
| 868 | m_uid_to_type[toOpaqueUid(type)] = qt; |
| 869 | return qt; |
| 870 | } |
| 871 | |
| 872 | // This is either a full decl, or a forward decl with no matching full decl |
| 873 | // in the debug info. |
| 874 | qt = CreateType(type); |
| 875 | m_uid_to_type[toOpaqueUid(type)] = qt; |
| 876 | if (IsTagRecord(type, m_index.tpi())) { |
| 877 | clang::TagDecl *tag = qt->getAsTagDecl(); |
| 878 | lldbassert(m_decl_to_status.count(tag) == 0); |
| 879 | |
| 880 | DeclStatus &status = m_decl_to_status[tag]; |
| 881 | status.uid = uid; |
| 882 | status.resolved = false; |
| 883 | } |
| 884 | return qt; |
| 885 | } |
| 886 | |
| 887 | clang::FunctionDecl * |
| 888 | PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { |
| 889 | if (clang::Decl *decl = TryGetDecl(func_id)) |
| 890 | return llvm::dyn_cast<clang::FunctionDecl>(decl); |
| 891 | |
| 892 | clang::DeclContext *parent = GetParentDeclContext(PdbSymUid(func_id)); |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 893 | std::string context_name; |
| 894 | if (clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(parent)) { |
| 895 | context_name = ns->getQualifiedNameAsString(); |
| 896 | } else if (clang::TagDecl *tag = llvm::dyn_cast<clang::TagDecl>(parent)) { |
| 897 | context_name = tag->getQualifiedNameAsString(); |
| 898 | } |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 899 | |
| 900 | CVSymbol cvs = m_index.ReadSymbolRecord(func_id); |
| 901 | ProcSym proc(static_cast<SymbolRecordKind>(cvs.kind())); |
| 902 | llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(cvs, proc)); |
| 903 | |
| 904 | PdbTypeSymId type_id(proc.FunctionType); |
| 905 | clang::QualType qt = GetOrCreateType(type_id); |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 906 | if (qt.isNull()) |
| 907 | return nullptr; |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 908 | |
| 909 | clang::StorageClass storage = clang::SC_None; |
| 910 | if (proc.Kind == SymbolRecordKind::ProcSym) |
| 911 | storage = clang::SC_Static; |
| 912 | |
| 913 | const clang::FunctionProtoType *func_type = |
| 914 | llvm::dyn_cast<clang::FunctionProtoType>(qt); |
| 915 | |
| 916 | CompilerType func_ct = ToCompilerType(qt); |
| 917 | |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 918 | llvm::StringRef proc_name = proc.Name; |
| 919 | proc_name.consume_front(context_name); |
| 920 | proc_name.consume_front("::"); |
| 921 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 922 | clang::FunctionDecl *function_decl = m_clang.CreateFunctionDeclaration( |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 923 | parent, proc_name.str().c_str(), func_ct, storage, false); |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 924 | |
| 925 | lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0); |
| 926 | m_uid_to_decl[toOpaqueUid(func_id)] = function_decl; |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 927 | DeclStatus status; |
| 928 | status.resolved = true; |
| 929 | status.uid = toOpaqueUid(func_id); |
| 930 | m_decl_to_status.insert({function_decl, status}); |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 931 | |
| 932 | CreateFunctionParameters(func_id, *function_decl, func_type->getNumParams()); |
| 933 | |
| 934 | return function_decl; |
| 935 | } |
| 936 | |
| 937 | void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id, |
| 938 | clang::FunctionDecl &function_decl, |
| 939 | uint32_t param_count) { |
| 940 | CompilandIndexItem *cii = m_index.compilands().GetCompiland(func_id.modi); |
| 941 | CVSymbolArray scope = |
| 942 | cii->m_debug_stream.getSymbolArrayForScope(func_id.offset); |
| 943 | |
| 944 | auto begin = scope.begin(); |
| 945 | auto end = scope.end(); |
| 946 | std::vector<clang::ParmVarDecl *> params; |
| 947 | while (begin != end && param_count > 0) { |
| 948 | uint32_t record_offset = begin.offset(); |
| 949 | CVSymbol sym = *begin++; |
| 950 | |
| 951 | TypeIndex param_type; |
| 952 | llvm::StringRef param_name; |
| 953 | switch (sym.kind()) { |
| 954 | case S_REGREL32: { |
| 955 | RegRelativeSym reg(SymbolRecordKind::RegRelativeSym); |
| 956 | cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg)); |
| 957 | param_type = reg.Type; |
| 958 | param_name = reg.Name; |
| 959 | break; |
| 960 | } |
| 961 | case S_REGISTER: { |
| 962 | RegisterSym reg(SymbolRecordKind::RegisterSym); |
| 963 | cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg)); |
| 964 | param_type = reg.Index; |
| 965 | param_name = reg.Name; |
| 966 | break; |
| 967 | } |
| 968 | case S_LOCAL: { |
| 969 | LocalSym local(SymbolRecordKind::LocalSym); |
| 970 | cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local)); |
| 971 | if ((local.Flags & LocalSymFlags::IsParameter) == LocalSymFlags::None) |
| 972 | continue; |
| 973 | param_type = local.Type; |
| 974 | param_name = local.Name; |
| 975 | break; |
| 976 | } |
| 977 | case S_BLOCK32: |
| 978 | // All parameters should come before the first block. If that isn't the |
| 979 | // case, then perhaps this is bad debug info that doesn't contain |
| 980 | // information about all parameters. |
| 981 | return; |
| 982 | default: |
| 983 | continue; |
| 984 | } |
| 985 | |
| 986 | PdbCompilandSymId param_uid(func_id.modi, record_offset); |
| 987 | clang::QualType qt = GetOrCreateType(param_type); |
| 988 | |
| 989 | CompilerType param_type_ct(&m_clang, qt.getAsOpaquePtr()); |
| 990 | clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration( |
| 991 | &function_decl, param_name.str().c_str(), param_type_ct, |
| 992 | clang::SC_None); |
| 993 | lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0); |
| 994 | |
| 995 | m_uid_to_decl[toOpaqueUid(param_uid)] = param; |
| 996 | params.push_back(param); |
| 997 | --param_count; |
| 998 | } |
| 999 | |
| 1000 | if (!params.empty()) |
| 1001 | m_clang.SetFunctionParameters(&function_decl, params.data(), params.size()); |
| 1002 | } |
| 1003 | |
| 1004 | clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id, |
| 1005 | const EnumRecord &er) { |
| 1006 | clang::DeclContext *decl_context = nullptr; |
| 1007 | std::string uname; |
| 1008 | std::tie(decl_context, uname) = CreateDeclInfoForType(er, id.index); |
| 1009 | clang::QualType underlying_type = GetOrCreateType(er.UnderlyingType); |
| 1010 | |
| 1011 | Declaration declaration; |
| 1012 | CompilerType enum_ct = m_clang.CreateEnumerationType( |
| 1013 | uname.c_str(), decl_context, declaration, ToCompilerType(underlying_type), |
| 1014 | er.isScoped()); |
| 1015 | |
| 1016 | ClangASTContext::StartTagDeclarationDefinition(enum_ct); |
| 1017 | ClangASTContext::SetHasExternalStorage(enum_ct.GetOpaqueQualType(), true); |
| 1018 | |
| 1019 | return clang::QualType::getFromOpaquePtr(enum_ct.GetOpaqueQualType()); |
| 1020 | } |
| 1021 | |
| 1022 | clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) { |
| 1023 | clang::QualType element_type = GetOrCreateType(ar.ElementType); |
| 1024 | |
| 1025 | uint64_t element_count = |
| 1026 | ar.Size / GetSizeOfType({ar.ElementType}, m_index.tpi()); |
| 1027 | |
| 1028 | CompilerType array_ct = m_clang.CreateArrayType(ToCompilerType(element_type), |
| 1029 | element_count, false); |
| 1030 | return clang::QualType::getFromOpaquePtr(array_ct.GetOpaqueQualType()); |
| 1031 | } |
| 1032 | |
| 1033 | clang::QualType |
| 1034 | PdbAstBuilder::CreateProcedureType(const ProcedureRecord &proc) { |
| 1035 | TpiStream &stream = m_index.tpi(); |
| 1036 | CVType args_cvt = stream.getType(proc.ArgumentList); |
| 1037 | ArgListRecord args; |
| 1038 | llvm::cantFail( |
| 1039 | TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args)); |
| 1040 | |
| 1041 | llvm::ArrayRef<TypeIndex> arg_indices = llvm::makeArrayRef(args.ArgIndices); |
| 1042 | bool is_variadic = IsCVarArgsFunction(arg_indices); |
| 1043 | if (is_variadic) |
| 1044 | arg_indices = arg_indices.drop_back(); |
| 1045 | |
| 1046 | std::vector<CompilerType> arg_types; |
| 1047 | arg_types.reserve(arg_indices.size()); |
| 1048 | |
| 1049 | for (TypeIndex arg_index : arg_indices) { |
| 1050 | clang::QualType arg_type = GetOrCreateType(arg_index); |
| 1051 | arg_types.push_back(ToCompilerType(arg_type)); |
| 1052 | } |
| 1053 | |
| 1054 | clang::QualType return_type = GetOrCreateType(proc.ReturnType); |
| 1055 | |
| 1056 | llvm::Optional<clang::CallingConv> cc = |
| 1057 | TranslateCallingConvention(proc.CallConv); |
| 1058 | if (!cc) |
| 1059 | return {}; |
| 1060 | |
| 1061 | CompilerType return_ct = ToCompilerType(return_type); |
| 1062 | CompilerType func_sig_ast_type = m_clang.CreateFunctionType( |
| 1063 | return_ct, arg_types.data(), arg_types.size(), is_variadic, 0, *cc); |
| 1064 | |
| 1065 | return clang::QualType::getFromOpaquePtr( |
| 1066 | func_sig_ast_type.GetOpaqueQualType()); |
| 1067 | } |
| 1068 | |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 1069 | static bool isTagDecl(clang::DeclContext &context) { |
| 1070 | return !!llvm::dyn_cast<clang::TagDecl>(&context); |
| 1071 | } |
| 1072 | |
| 1073 | static bool isFunctionDecl(clang::DeclContext &context) { |
| 1074 | return !!llvm::dyn_cast<clang::FunctionDecl>(&context); |
| 1075 | } |
| 1076 | |
| 1077 | static bool isBlockDecl(clang::DeclContext &context) { |
| 1078 | return !!llvm::dyn_cast<clang::BlockDecl>(&context); |
| 1079 | } |
| 1080 | |
| 1081 | void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf( |
| 1082 | llvm::Optional<llvm::StringRef> parent) { |
| 1083 | TypeIndex ti{m_index.tpi().TypeIndexBegin()}; |
| 1084 | for (const CVType &cvt : m_index.tpi().typeArray()) { |
| 1085 | PdbTypeSymId tid{ti}; |
| 1086 | ++ti; |
| 1087 | |
| 1088 | if (!IsTagRecord(cvt)) |
| 1089 | continue; |
| 1090 | |
| 1091 | CVTagRecord tag = CVTagRecord::create(cvt); |
| 1092 | |
| 1093 | if (!parent.hasValue()) { |
| 1094 | clang::QualType qt = GetOrCreateType(tid); |
| 1095 | CompleteType(qt); |
| 1096 | continue; |
| 1097 | } |
| 1098 | |
| 1099 | // Call CreateDeclInfoForType unconditionally so that the namespace info |
| 1100 | // gets created. But only call CreateRecordType if the namespace name |
| 1101 | // matches. |
| 1102 | clang::DeclContext *context = nullptr; |
| 1103 | std::string uname; |
| 1104 | std::tie(context, uname) = CreateDeclInfoForType(tag.asTag(), tid.index); |
| 1105 | if (!context->isNamespace()) |
| 1106 | continue; |
| 1107 | |
| 1108 | clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(context); |
| 1109 | std::string actual_ns = ns->getQualifiedNameAsString(); |
| 1110 | if (llvm::StringRef(actual_ns).startswith(*parent)) { |
| 1111 | clang::QualType qt = GetOrCreateType(tid); |
| 1112 | CompleteType(qt); |
| 1113 | continue; |
| 1114 | } |
| 1115 | } |
| 1116 | |
| 1117 | uint32_t module_count = m_index.dbi().modules().getModuleCount(); |
| 1118 | for (uint16_t modi = 0; modi < module_count; ++modi) { |
| 1119 | CompilandIndexItem &cii = m_index.compilands().GetOrCreateCompiland(modi); |
| 1120 | const CVSymbolArray &symbols = cii.m_debug_stream.getSymbolArray(); |
| 1121 | auto iter = symbols.begin(); |
| 1122 | while (iter != symbols.end()) { |
| 1123 | PdbCompilandSymId sym_id{modi, iter.offset()}; |
| 1124 | |
| 1125 | switch (iter->kind()) { |
| 1126 | case S_GPROC32: |
| 1127 | case S_LPROC32: |
| 1128 | GetOrCreateFunctionDecl(sym_id); |
| 1129 | iter = symbols.at(getScopeEndOffset(*iter)); |
| 1130 | break; |
| 1131 | case S_GDATA32: |
| 1132 | case S_GTHREAD32: |
| 1133 | case S_LDATA32: |
| 1134 | case S_LTHREAD32: |
| 1135 | GetOrCreateVariableDecl(PdbCompilandSymId(modi, 0), sym_id); |
| 1136 | ++iter; |
| 1137 | break; |
| 1138 | default: |
| 1139 | ++iter; |
| 1140 | continue; |
| 1141 | } |
| 1142 | } |
| 1143 | } |
| 1144 | } |
| 1145 | |
| 1146 | static CVSymbolArray skipFunctionParameters(clang::Decl &decl, |
| 1147 | const CVSymbolArray &symbols) { |
| 1148 | clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>(&decl); |
| 1149 | if (!func_decl) |
| 1150 | return symbols; |
| 1151 | unsigned int params = func_decl->getNumParams(); |
| 1152 | if (params == 0) |
| 1153 | return symbols; |
| 1154 | |
| 1155 | CVSymbolArray result = symbols; |
| 1156 | |
| 1157 | while (!result.empty()) { |
| 1158 | if (params == 0) |
| 1159 | return result; |
| 1160 | |
| 1161 | CVSymbol sym = *result.begin(); |
| 1162 | result.drop_front(); |
| 1163 | |
| 1164 | if (!isLocalVariableType(sym.kind())) |
| 1165 | continue; |
| 1166 | |
| 1167 | --params; |
| 1168 | } |
| 1169 | return result; |
| 1170 | } |
| 1171 | |
| 1172 | void PdbAstBuilder::ParseBlockChildren(PdbCompilandSymId block_id) { |
| 1173 | CVSymbol sym = m_index.ReadSymbolRecord(block_id); |
| 1174 | lldbassert(sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32 || |
| 1175 | sym.kind() == S_BLOCK32); |
| 1176 | CompilandIndexItem &cii = |
| 1177 | m_index.compilands().GetOrCreateCompiland(block_id.modi); |
| 1178 | CVSymbolArray symbols = |
| 1179 | cii.m_debug_stream.getSymbolArrayForScope(block_id.offset); |
| 1180 | |
| 1181 | // Function parameters should already have been created when the function was |
| 1182 | // parsed. |
| 1183 | if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32) |
| 1184 | symbols = |
| 1185 | skipFunctionParameters(*m_uid_to_decl[toOpaqueUid(block_id)], symbols); |
| 1186 | |
| 1187 | auto begin = symbols.begin(); |
| 1188 | while (begin != symbols.end()) { |
| 1189 | PdbCompilandSymId child_sym_id(block_id.modi, begin.offset()); |
| 1190 | GetOrCreateSymbolForId(child_sym_id); |
| 1191 | if (begin->kind() == S_BLOCK32) { |
| 1192 | ParseBlockChildren(child_sym_id); |
| 1193 | begin = symbols.at(getScopeEndOffset(*begin)); |
| 1194 | } |
| 1195 | ++begin; |
| 1196 | } |
| 1197 | } |
| 1198 | |
| 1199 | void PdbAstBuilder::ParseDeclsForSimpleContext(clang::DeclContext &context) { |
| 1200 | |
| 1201 | clang::Decl *decl = clang::Decl::castFromDeclContext(&context); |
| 1202 | lldbassert(decl); |
| 1203 | |
| 1204 | auto iter = m_decl_to_status.find(decl); |
| 1205 | lldbassert(iter != m_decl_to_status.end()); |
| 1206 | |
| 1207 | if (auto *tag = llvm::dyn_cast<clang::TagDecl>(&context)) { |
| 1208 | CompleteTagDecl(*tag); |
| 1209 | return; |
| 1210 | } |
| 1211 | |
| 1212 | if (isFunctionDecl(context) || isBlockDecl(context)) { |
| 1213 | PdbCompilandSymId block_id = PdbSymUid(iter->second.uid).asCompilandSym(); |
| 1214 | ParseBlockChildren(block_id); |
| 1215 | } |
| 1216 | } |
| 1217 | |
| 1218 | void PdbAstBuilder::ParseDeclsForContext(clang::DeclContext &context) { |
| 1219 | // Namespaces aren't explicitly represented in the debug info, and the only |
| 1220 | // way to parse them is to parse all type info, demangling every single type |
| 1221 | // and trying to reconstruct the DeclContext hierarchy this way. Since this |
| 1222 | // is an expensive operation, we have to special case it so that we do other |
| 1223 | // work (such as parsing the items that appear within the namespaces) at the |
| 1224 | // same time. |
| 1225 | if (context.isTranslationUnit()) { |
| 1226 | ParseAllNamespacesPlusChildrenOf(llvm::None); |
| 1227 | return; |
| 1228 | } |
| 1229 | |
| 1230 | if (context.isNamespace()) { |
| 1231 | clang::NamespaceDecl &ns = *llvm::dyn_cast<clang::NamespaceDecl>(&context); |
| 1232 | std::string qname = ns.getQualifiedNameAsString(); |
| 1233 | ParseAllNamespacesPlusChildrenOf(llvm::StringRef{qname}); |
| 1234 | return; |
| 1235 | } |
| 1236 | |
| 1237 | if (isTagDecl(context) || isFunctionDecl(context) || isBlockDecl(context)) { |
| 1238 | ParseDeclsForSimpleContext(context); |
| 1239 | return; |
| 1240 | } |
| 1241 | } |
| 1242 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 1243 | CompilerDecl PdbAstBuilder::ToCompilerDecl(clang::Decl &decl) { |
| 1244 | return {&m_clang, &decl}; |
| 1245 | } |
| 1246 | |
| 1247 | CompilerType PdbAstBuilder::ToCompilerType(clang::QualType qt) { |
| 1248 | return {&m_clang, qt.getAsOpaquePtr()}; |
| 1249 | } |
| 1250 | |
| 1251 | CompilerDeclContext |
| 1252 | PdbAstBuilder::ToCompilerDeclContext(clang::DeclContext &context) { |
| 1253 | return {&m_clang, &context}; |
| 1254 | } |
| 1255 | |
Zachary Turner | 2256633 | 2019-01-02 18:33:54 +0000 | [diff] [blame] | 1256 | clang::DeclContext * |
| 1257 | PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) { |
| 1258 | return static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext()); |
| 1259 | } |
| 1260 | |
Zachary Turner | 594c85e | 2018-12-17 19:43:33 +0000 | [diff] [blame] | 1261 | void PdbAstBuilder::Dump(Stream &stream) { m_clang.Dump(stream); } |