180814287SRaphael Isemann //===-- PdbFPOProgramToDWARFExpression.cpp --------------------------------===// 2758657e5SAleksandr Urakov // 3ee21a66aSAleksandr Urakov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ee21a66aSAleksandr Urakov // See https://llvm.org/LICENSE.txt for license information. 5ee21a66aSAleksandr Urakov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6758657e5SAleksandr Urakov // 7758657e5SAleksandr Urakov //===----------------------------------------------------------------------===// 8758657e5SAleksandr Urakov 9758657e5SAleksandr Urakov #include "PdbFPOProgramToDWARFExpression.h" 10758657e5SAleksandr Urakov #include "CodeViewRegisterMapping.h" 11758657e5SAleksandr Urakov 12758657e5SAleksandr Urakov #include "lldb/Core/StreamBuffer.h" 134eda12aeSPavel Labath #include "lldb/Symbol/PostfixExpression.h" 14758657e5SAleksandr Urakov #include "lldb/Utility/LLDBAssert.h" 15758657e5SAleksandr Urakov #include "lldb/Utility/Stream.h" 16758657e5SAleksandr Urakov #include "llvm/ADT/DenseMap.h" 17758657e5SAleksandr Urakov 18758657e5SAleksandr Urakov #include "llvm/ADT/StringExtras.h" 19758657e5SAleksandr Urakov #include "llvm/DebugInfo/CodeView/CodeView.h" 20758657e5SAleksandr Urakov #include "llvm/DebugInfo/CodeView/EnumTables.h" 21758657e5SAleksandr Urakov 22758657e5SAleksandr Urakov using namespace lldb; 23758657e5SAleksandr Urakov using namespace lldb_private; 244eda12aeSPavel Labath using namespace lldb_private::postfix; 25758657e5SAleksandr Urakov 261c4ee160SPavel Labath static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::ArchType arch_type) { 271c4ee160SPavel Labath // lookup register name to get lldb register number 28382320eaSTom Tan llvm::codeview::CPUType cpu_type; 29382320eaSTom Tan switch (arch_type) { 30382320eaSTom Tan case llvm::Triple::ArchType::aarch64: 31382320eaSTom Tan cpu_type = llvm::codeview::CPUType::ARM64; 32382320eaSTom Tan break; 33382320eaSTom Tan 34382320eaSTom Tan default: 35382320eaSTom Tan cpu_type = llvm::codeview::CPUType::X64; 36382320eaSTom Tan break; 37382320eaSTom Tan } 38382320eaSTom Tan 391c4ee160SPavel Labath llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names = 40382320eaSTom Tan llvm::codeview::getRegisterNames(cpu_type); 411c4ee160SPavel Labath auto it = llvm::find_if( 421c4ee160SPavel Labath register_names, 431c4ee160SPavel Labath [®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) { 44*e50f9c41SMartin Storsjö return reg_name.compare_insensitive(register_entry.Name) == 0; 451c4ee160SPavel Labath }); 46758657e5SAleksandr Urakov 471c4ee160SPavel Labath if (it == register_names.end()) 481c4ee160SPavel Labath return LLDB_INVALID_REGNUM; 491c4ee160SPavel Labath 501c4ee160SPavel Labath auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value); 511c4ee160SPavel Labath return npdb::GetLLDBRegisterNumber(arch_type, reg_id); 52758657e5SAleksandr Urakov } 531c4ee160SPavel Labath 54c7deb7f8SPavel Labath static Node *ResolveFPOProgram(llvm::StringRef program, 55758657e5SAleksandr Urakov llvm::StringRef register_name, 56758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type, 5788813103SPavel Labath llvm::BumpPtrAllocator &alloc) { 58c7deb7f8SPavel Labath std::vector<std::pair<llvm::StringRef, Node *>> parsed = 59c7deb7f8SPavel Labath postfix::ParseFPOProgram(program, alloc); 60758657e5SAleksandr Urakov 61c7deb7f8SPavel Labath for (auto it = parsed.begin(), end = parsed.end(); it != end; ++it) { 620eadd988SPavel Labath // Emplace valid dependent subtrees to make target assignment independent 630eadd988SPavel Labath // from predecessors. Resolve all other SymbolNodes as registers. 640eadd988SPavel Labath bool success = 65c7deb7f8SPavel Labath ResolveSymbols(it->second, [&](SymbolNode &symbol) -> Node * { 66c7deb7f8SPavel Labath for (const auto &pair : llvm::make_range(parsed.begin(), it)) { 67c7deb7f8SPavel Labath if (pair.first == symbol.GetName()) 68c7deb7f8SPavel Labath return pair.second; 69c7deb7f8SPavel Labath } 70c7deb7f8SPavel Labath 710eadd988SPavel Labath uint32_t reg_num = 720eadd988SPavel Labath ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), arch_type); 730eadd988SPavel Labath 740eadd988SPavel Labath if (reg_num == LLDB_INVALID_REGNUM) 750eadd988SPavel Labath return nullptr; 760eadd988SPavel Labath 770eadd988SPavel Labath return MakeNode<RegisterNode>(alloc, reg_num); 780eadd988SPavel Labath }); 790eadd988SPavel Labath if (!success) 80758657e5SAleksandr Urakov return nullptr; 81758657e5SAleksandr Urakov 82c7deb7f8SPavel Labath if (it->first == register_name) { 83758657e5SAleksandr Urakov // found target assignment program - no need to parse further 84c7deb7f8SPavel Labath return it->second; 85758657e5SAleksandr Urakov } 86758657e5SAleksandr Urakov } 87758657e5SAleksandr Urakov 88758657e5SAleksandr Urakov return nullptr; 89758657e5SAleksandr Urakov } 90758657e5SAleksandr Urakov 91758657e5SAleksandr Urakov bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( 92758657e5SAleksandr Urakov llvm::StringRef program, llvm::StringRef register_name, 93758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type, Stream &stream) { 9488813103SPavel Labath llvm::BumpPtrAllocator node_alloc; 954eda12aeSPavel Labath Node *target_program = 96c7deb7f8SPavel Labath ResolveFPOProgram(program, register_name, arch_type, node_alloc); 97758657e5SAleksandr Urakov if (target_program == nullptr) { 98758657e5SAleksandr Urakov return false; 99758657e5SAleksandr Urakov } 100758657e5SAleksandr Urakov 1010eadd988SPavel Labath ToDWARF(*target_program, stream); 102758657e5SAleksandr Urakov return true; 103758657e5SAleksandr Urakov } 104