]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Plugins / SymbolFile / NativePDB / PdbFPOProgramToDWARFExpression.cpp
1 //===-- PdbFPOProgramToDWARFExpression.cpp ----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "PdbFPOProgramToDWARFExpression.h"
10 #include "CodeViewRegisterMapping.h"
11
12 #include "lldb/Core/StreamBuffer.h"
13 #include "lldb/Symbol/PostfixExpression.h"
14 #include "lldb/Utility/LLDBAssert.h"
15 #include "lldb/Utility/Stream.h"
16 #include "llvm/ADT/DenseMap.h"
17
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/DebugInfo/CodeView/CodeView.h"
20 #include "llvm/DebugInfo/CodeView/EnumTables.h"
21
22 using namespace lldb;
23 using namespace lldb_private;
24 using namespace lldb_private::postfix;
25
26 static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::ArchType arch_type) {
27   // lookup register name to get lldb register number
28   llvm::codeview::CPUType cpu_type;
29   switch (arch_type) {
30     case llvm::Triple::ArchType::aarch64:
31       cpu_type = llvm::codeview::CPUType::ARM64;
32       break;
33
34     default:
35       cpu_type = llvm::codeview::CPUType::X64;
36       break;
37   }
38
39   llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names =
40       llvm::codeview::getRegisterNames(cpu_type);
41   auto it = llvm::find_if(
42       register_names,
43       [&reg_name](const llvm::EnumEntry<uint16_t> &register_entry) {
44         return reg_name.compare_lower(register_entry.Name) == 0;
45       });
46
47   if (it == register_names.end())
48     return LLDB_INVALID_REGNUM;
49
50   auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value);
51   return npdb::GetLLDBRegisterNumber(arch_type, reg_id);
52 }
53
54 static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
55                                             llvm::BumpPtrAllocator &alloc,
56                                             llvm::StringRef &register_name,
57                                             Node *&ast) {
58   // lvalue of assignment is always first token
59   // rvalue program goes next
60   std::tie(register_name, program) = getToken(program);
61   if (register_name.empty())
62     return false;
63
64   ast = Parse(program, alloc);
65   return ast != nullptr;
66 }
67
68 static Node *ParseFPOProgram(llvm::StringRef program,
69                              llvm::StringRef register_name,
70                              llvm::Triple::ArchType arch_type,
71                              llvm::BumpPtrAllocator &alloc) {
72   llvm::DenseMap<llvm::StringRef, Node *> dependent_programs;
73
74   size_t cur = 0;
75   while (true) {
76     size_t assign_index = program.find('=', cur);
77     if (assign_index == llvm::StringRef::npos) {
78       llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos);
79       if (!tail.trim().empty()) {
80         // missing assign operator
81         return nullptr;
82       }
83       break;
84     }
85     llvm::StringRef assignment_program = program.slice(cur, assign_index);
86
87     llvm::StringRef lvalue_name;
88     Node *rvalue_ast = nullptr;
89     if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name,
90                                          rvalue_ast)) {
91       return nullptr;
92     }
93
94     lldbassert(rvalue_ast);
95
96     // Emplace valid dependent subtrees to make target assignment independent
97     // from predecessors. Resolve all other SymbolNodes as registers.
98     bool success =
99         ResolveSymbols(rvalue_ast, [&](SymbolNode &symbol) -> Node * {
100           if (Node *node = dependent_programs.lookup(symbol.GetName()))
101             return node;
102           uint32_t reg_num =
103               ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), arch_type);
104
105           if (reg_num == LLDB_INVALID_REGNUM)
106             return nullptr;
107
108           return MakeNode<RegisterNode>(alloc, reg_num);
109         });
110     if (!success)
111       return nullptr;
112
113     if (lvalue_name == register_name) {
114       // found target assignment program - no need to parse further
115       return rvalue_ast;
116     }
117
118     dependent_programs[lvalue_name] = rvalue_ast;
119     cur = assign_index + 1;
120   }
121
122   return nullptr;
123 }
124
125 bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression(
126     llvm::StringRef program, llvm::StringRef register_name,
127     llvm::Triple::ArchType arch_type, Stream &stream) {
128   llvm::BumpPtrAllocator node_alloc;
129   Node *target_program =
130       ParseFPOProgram(program, register_name, arch_type, node_alloc);
131   if (target_program == nullptr) {
132     return false;
133   }
134
135   ToDWARF(*target_program, stream);
136   return true;
137 }