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 [®_name](const llvm::EnumEntry<uint16_t> ®ister_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