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"
21*81cde474Sserge-sans-paille #include "llvm/Support/ScopedPrinter.h"
22758657e5SAleksandr Urakov
23758657e5SAleksandr Urakov using namespace lldb;
24758657e5SAleksandr Urakov using namespace lldb_private;
254eda12aeSPavel Labath using namespace lldb_private::postfix;
26758657e5SAleksandr Urakov
ResolveLLDBRegisterNum(llvm::StringRef reg_name,llvm::Triple::ArchType arch_type)271c4ee160SPavel Labath static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::ArchType arch_type) {
281c4ee160SPavel Labath // lookup register name to get lldb register number
29382320eaSTom Tan llvm::codeview::CPUType cpu_type;
30382320eaSTom Tan switch (arch_type) {
31382320eaSTom Tan case llvm::Triple::ArchType::aarch64:
32382320eaSTom Tan cpu_type = llvm::codeview::CPUType::ARM64;
33382320eaSTom Tan break;
34382320eaSTom Tan
35382320eaSTom Tan default:
36382320eaSTom Tan cpu_type = llvm::codeview::CPUType::X64;
37382320eaSTom Tan break;
38382320eaSTom Tan }
39382320eaSTom Tan
401c4ee160SPavel Labath llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names =
41382320eaSTom Tan llvm::codeview::getRegisterNames(cpu_type);
421c4ee160SPavel Labath auto it = llvm::find_if(
431c4ee160SPavel Labath register_names,
441c4ee160SPavel Labath [®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) {
45e50f9c41SMartin Storsjö return reg_name.compare_insensitive(register_entry.Name) == 0;
461c4ee160SPavel Labath });
47758657e5SAleksandr Urakov
481c4ee160SPavel Labath if (it == register_names.end())
491c4ee160SPavel Labath return LLDB_INVALID_REGNUM;
501c4ee160SPavel Labath
511c4ee160SPavel Labath auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value);
521c4ee160SPavel Labath return npdb::GetLLDBRegisterNumber(arch_type, reg_id);
53758657e5SAleksandr Urakov }
541c4ee160SPavel Labath
ResolveFPOProgram(llvm::StringRef program,llvm::StringRef register_name,llvm::Triple::ArchType arch_type,llvm::BumpPtrAllocator & alloc)55c7deb7f8SPavel Labath static Node *ResolveFPOProgram(llvm::StringRef program,
56758657e5SAleksandr Urakov llvm::StringRef register_name,
57758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type,
5888813103SPavel Labath llvm::BumpPtrAllocator &alloc) {
59c7deb7f8SPavel Labath std::vector<std::pair<llvm::StringRef, Node *>> parsed =
60c7deb7f8SPavel Labath postfix::ParseFPOProgram(program, alloc);
61758657e5SAleksandr Urakov
62c7deb7f8SPavel Labath for (auto it = parsed.begin(), end = parsed.end(); it != end; ++it) {
630eadd988SPavel Labath // Emplace valid dependent subtrees to make target assignment independent
640eadd988SPavel Labath // from predecessors. Resolve all other SymbolNodes as registers.
650eadd988SPavel Labath bool success =
66c7deb7f8SPavel Labath ResolveSymbols(it->second, [&](SymbolNode &symbol) -> Node * {
67c7deb7f8SPavel Labath for (const auto &pair : llvm::make_range(parsed.begin(), it)) {
68c7deb7f8SPavel Labath if (pair.first == symbol.GetName())
69c7deb7f8SPavel Labath return pair.second;
70c7deb7f8SPavel Labath }
71c7deb7f8SPavel Labath
720eadd988SPavel Labath uint32_t reg_num =
730eadd988SPavel Labath ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), arch_type);
740eadd988SPavel Labath
750eadd988SPavel Labath if (reg_num == LLDB_INVALID_REGNUM)
760eadd988SPavel Labath return nullptr;
770eadd988SPavel Labath
780eadd988SPavel Labath return MakeNode<RegisterNode>(alloc, reg_num);
790eadd988SPavel Labath });
800eadd988SPavel Labath if (!success)
81758657e5SAleksandr Urakov return nullptr;
82758657e5SAleksandr Urakov
83c7deb7f8SPavel Labath if (it->first == register_name) {
84758657e5SAleksandr Urakov // found target assignment program - no need to parse further
85c7deb7f8SPavel Labath return it->second;
86758657e5SAleksandr Urakov }
87758657e5SAleksandr Urakov }
88758657e5SAleksandr Urakov
89758657e5SAleksandr Urakov return nullptr;
90758657e5SAleksandr Urakov }
91758657e5SAleksandr Urakov
TranslateFPOProgramToDWARFExpression(llvm::StringRef program,llvm::StringRef register_name,llvm::Triple::ArchType arch_type,Stream & stream)92758657e5SAleksandr Urakov bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression(
93758657e5SAleksandr Urakov llvm::StringRef program, llvm::StringRef register_name,
94758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type, Stream &stream) {
9588813103SPavel Labath llvm::BumpPtrAllocator node_alloc;
964eda12aeSPavel Labath Node *target_program =
97c7deb7f8SPavel Labath ResolveFPOProgram(program, register_name, arch_type, node_alloc);
98758657e5SAleksandr Urakov if (target_program == nullptr) {
99758657e5SAleksandr Urakov return false;
100758657e5SAleksandr Urakov }
101758657e5SAleksandr Urakov
1020eadd988SPavel Labath ToDWARF(*target_program, stream);
103758657e5SAleksandr Urakov return true;
104758657e5SAleksandr Urakov }
105