xref: /llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp (revision 20c77a5789331956cd47d1804df7885a82094964)
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 
124eda12aeSPavel Labath #include "lldb/Symbol/PostfixExpression.h"
13758657e5SAleksandr Urakov #include "lldb/Utility/LLDBAssert.h"
14758657e5SAleksandr Urakov #include "lldb/Utility/Stream.h"
15758657e5SAleksandr Urakov #include "llvm/ADT/DenseMap.h"
16758657e5SAleksandr Urakov 
17758657e5SAleksandr Urakov #include "llvm/ADT/StringExtras.h"
18758657e5SAleksandr Urakov #include "llvm/DebugInfo/CodeView/CodeView.h"
19758657e5SAleksandr Urakov #include "llvm/DebugInfo/CodeView/EnumTables.h"
20*81cde474Sserge-sans-paille #include "llvm/Support/ScopedPrinter.h"
21758657e5SAleksandr Urakov 
22758657e5SAleksandr Urakov using namespace lldb;
23758657e5SAleksandr Urakov using namespace lldb_private;
244eda12aeSPavel Labath using namespace lldb_private::postfix;
25758657e5SAleksandr Urakov 
ResolveLLDBRegisterNum(llvm::StringRef reg_name,llvm::Triple::ArchType arch_type)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       [&reg_name](const llvm::EnumEntry<uint16_t> &register_entry) {
44e50f9c41SMartin 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 
ResolveFPOProgram(llvm::StringRef program,llvm::StringRef register_name,llvm::Triple::ArchType arch_type,llvm::BumpPtrAllocator & alloc)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 
TranslateFPOProgramToDWARFExpression(llvm::StringRef program,llvm::StringRef register_name,llvm::Triple::ArchType arch_type,Stream & stream)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