1758657e5SAleksandr Urakov //===-- PDBFPOProgramToDWARFExpression.cpp ----------------------*- C++ -*-===// 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 281c4ee160SPavel Labath llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names = 291c4ee160SPavel Labath llvm::codeview::getRegisterNames(); 301c4ee160SPavel Labath auto it = llvm::find_if( 311c4ee160SPavel Labath register_names, 321c4ee160SPavel Labath [®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) { 331c4ee160SPavel Labath return reg_name.compare_lower(register_entry.Name) == 0; 341c4ee160SPavel Labath }); 35758657e5SAleksandr Urakov 361c4ee160SPavel Labath if (it == register_names.end()) 371c4ee160SPavel Labath return LLDB_INVALID_REGNUM; 381c4ee160SPavel Labath 391c4ee160SPavel Labath auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value); 401c4ee160SPavel Labath return npdb::GetLLDBRegisterNumber(arch_type, reg_id); 41758657e5SAleksandr Urakov } 421c4ee160SPavel Labath 43758657e5SAleksandr Urakov static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program, 4488813103SPavel Labath llvm::BumpPtrAllocator &alloc, 45758657e5SAleksandr Urakov llvm::StringRef ®ister_name, 464eda12aeSPavel Labath Node *&ast) { 47758657e5SAleksandr Urakov // lvalue of assignment is always first token 48758657e5SAleksandr Urakov // rvalue program goes next 4988813103SPavel Labath std::tie(register_name, program) = getToken(program); 5088813103SPavel Labath if (register_name.empty()) 51758657e5SAleksandr Urakov return false; 52758657e5SAleksandr Urakov 5388813103SPavel Labath ast = Parse(program, alloc); 5488813103SPavel Labath return ast != nullptr; 55758657e5SAleksandr Urakov } 56758657e5SAleksandr Urakov 574eda12aeSPavel Labath static Node *ParseFPOProgram(llvm::StringRef program, 58758657e5SAleksandr Urakov llvm::StringRef register_name, 59758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type, 6088813103SPavel Labath llvm::BumpPtrAllocator &alloc) { 614eda12aeSPavel Labath llvm::DenseMap<llvm::StringRef, Node *> dependent_programs; 62758657e5SAleksandr Urakov 63758657e5SAleksandr Urakov size_t cur = 0; 64758657e5SAleksandr Urakov while (true) { 65758657e5SAleksandr Urakov size_t assign_index = program.find('=', cur); 66758657e5SAleksandr Urakov if (assign_index == llvm::StringRef::npos) { 67758657e5SAleksandr Urakov llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos); 68758657e5SAleksandr Urakov if (!tail.trim().empty()) { 69758657e5SAleksandr Urakov // missing assign operator 70758657e5SAleksandr Urakov return nullptr; 71758657e5SAleksandr Urakov } 72758657e5SAleksandr Urakov break; 73758657e5SAleksandr Urakov } 74758657e5SAleksandr Urakov llvm::StringRef assignment_program = program.slice(cur, assign_index); 75758657e5SAleksandr Urakov 76758657e5SAleksandr Urakov llvm::StringRef lvalue_name; 774eda12aeSPavel Labath Node *rvalue_ast = nullptr; 78758657e5SAleksandr Urakov if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name, 79758657e5SAleksandr Urakov rvalue_ast)) { 80758657e5SAleksandr Urakov return nullptr; 81758657e5SAleksandr Urakov } 82758657e5SAleksandr Urakov 83758657e5SAleksandr Urakov lldbassert(rvalue_ast); 84758657e5SAleksandr Urakov 85*0eadd988SPavel Labath // Emplace valid dependent subtrees to make target assignment independent 86*0eadd988SPavel Labath // from predecessors. Resolve all other SymbolNodes as registers. 87*0eadd988SPavel Labath bool success = 88*0eadd988SPavel Labath ResolveSymbols(rvalue_ast, [&](SymbolNode &symbol) -> Node * { 89*0eadd988SPavel Labath if (Node *node = dependent_programs.lookup(symbol.GetName())) 90*0eadd988SPavel Labath return node; 91*0eadd988SPavel Labath uint32_t reg_num = 92*0eadd988SPavel Labath ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), arch_type); 93*0eadd988SPavel Labath 94*0eadd988SPavel Labath if (reg_num == LLDB_INVALID_REGNUM) 95*0eadd988SPavel Labath return nullptr; 96*0eadd988SPavel Labath 97*0eadd988SPavel Labath return MakeNode<RegisterNode>(alloc, reg_num); 98*0eadd988SPavel Labath }); 99*0eadd988SPavel Labath if (!success) 100758657e5SAleksandr Urakov return nullptr; 101758657e5SAleksandr Urakov 102758657e5SAleksandr Urakov if (lvalue_name == register_name) { 103758657e5SAleksandr Urakov // found target assignment program - no need to parse further 104758657e5SAleksandr Urakov return rvalue_ast; 105758657e5SAleksandr Urakov } 106758657e5SAleksandr Urakov 107758657e5SAleksandr Urakov dependent_programs[lvalue_name] = rvalue_ast; 108758657e5SAleksandr Urakov cur = assign_index + 1; 109758657e5SAleksandr Urakov } 110758657e5SAleksandr Urakov 111758657e5SAleksandr Urakov return nullptr; 112758657e5SAleksandr Urakov } 113758657e5SAleksandr Urakov 114758657e5SAleksandr Urakov bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( 115758657e5SAleksandr Urakov llvm::StringRef program, llvm::StringRef register_name, 116758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type, Stream &stream) { 11788813103SPavel Labath llvm::BumpPtrAllocator node_alloc; 1184eda12aeSPavel Labath Node *target_program = 119758657e5SAleksandr Urakov ParseFPOProgram(program, register_name, arch_type, node_alloc); 120758657e5SAleksandr Urakov if (target_program == nullptr) { 121758657e5SAleksandr Urakov return false; 122758657e5SAleksandr Urakov } 123758657e5SAleksandr Urakov 124*0eadd988SPavel Labath ToDWARF(*target_program, stream); 125758657e5SAleksandr Urakov return true; 126758657e5SAleksandr Urakov } 127