1351290Sdim//===-- PdbFPOProgramToDWARFExpression.cpp ----------------------*- C++ -*-===// 2351290Sdim// 3351290Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4351290Sdim// See https://llvm.org/LICENSE.txt for license information. 5351290Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6351290Sdim// 7351290Sdim//===----------------------------------------------------------------------===// 8351290Sdim 9351290Sdim#include "PdbFPOProgramToDWARFExpression.h" 10351290Sdim#include "CodeViewRegisterMapping.h" 11351290Sdim 12351290Sdim#include "lldb/Core/StreamBuffer.h" 13351290Sdim#include "lldb/Symbol/PostfixExpression.h" 14351290Sdim#include "lldb/Utility/LLDBAssert.h" 15351290Sdim#include "lldb/Utility/Stream.h" 16351290Sdim#include "llvm/ADT/DenseMap.h" 17351290Sdim 18351290Sdim#include "llvm/ADT/StringExtras.h" 19351290Sdim#include "llvm/DebugInfo/CodeView/CodeView.h" 20351290Sdim#include "llvm/DebugInfo/CodeView/EnumTables.h" 21351290Sdim 22351290Sdimusing namespace lldb; 23351290Sdimusing namespace lldb_private; 24351290Sdimusing namespace lldb_private::postfix; 25351290Sdim 26351290Sdimstatic uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::ArchType arch_type) { 27351290Sdim // lookup register name to get lldb register number 28351290Sdim llvm::codeview::CPUType cpu_type; 29351290Sdim switch (arch_type) { 30351290Sdim case llvm::Triple::ArchType::aarch64: 31351290Sdim cpu_type = llvm::codeview::CPUType::ARM64; 32351290Sdim break; 33351290Sdim 34351290Sdim default: 35351290Sdim cpu_type = llvm::codeview::CPUType::X64; 36351290Sdim break; 37351290Sdim } 38351290Sdim 39351290Sdim llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names = 40351290Sdim llvm::codeview::getRegisterNames(cpu_type); 41351290Sdim auto it = llvm::find_if( 42351290Sdim register_names, 43351290Sdim [®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) { 44351290Sdim return reg_name.compare_lower(register_entry.Name) == 0; 45351290Sdim }); 46351290Sdim 47351290Sdim if (it == register_names.end()) 48351290Sdim return LLDB_INVALID_REGNUM; 49351290Sdim 50351290Sdim auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value); 51351290Sdim return npdb::GetLLDBRegisterNumber(arch_type, reg_id); 52351290Sdim} 53351290Sdim 54360784Sdimstatic Node *ResolveFPOProgram(llvm::StringRef program, 55351290Sdim llvm::StringRef register_name, 56351290Sdim llvm::Triple::ArchType arch_type, 57351290Sdim llvm::BumpPtrAllocator &alloc) { 58360784Sdim std::vector<std::pair<llvm::StringRef, Node *>> parsed = 59360784Sdim postfix::ParseFPOProgram(program, alloc); 60351290Sdim 61360784Sdim for (auto it = parsed.begin(), end = parsed.end(); it != end; ++it) { 62351290Sdim // Emplace valid dependent subtrees to make target assignment independent 63351290Sdim // from predecessors. Resolve all other SymbolNodes as registers. 64351290Sdim bool success = 65360784Sdim ResolveSymbols(it->second, [&](SymbolNode &symbol) -> Node * { 66360784Sdim for (const auto &pair : llvm::make_range(parsed.begin(), it)) { 67360784Sdim if (pair.first == symbol.GetName()) 68360784Sdim return pair.second; 69360784Sdim } 70360784Sdim 71351290Sdim uint32_t reg_num = 72351290Sdim ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), arch_type); 73351290Sdim 74351290Sdim if (reg_num == LLDB_INVALID_REGNUM) 75351290Sdim return nullptr; 76351290Sdim 77351290Sdim return MakeNode<RegisterNode>(alloc, reg_num); 78351290Sdim }); 79351290Sdim if (!success) 80351290Sdim return nullptr; 81351290Sdim 82360784Sdim if (it->first == register_name) { 83351290Sdim // found target assignment program - no need to parse further 84360784Sdim return it->second; 85351290Sdim } 86351290Sdim } 87351290Sdim 88351290Sdim return nullptr; 89351290Sdim} 90351290Sdim 91351290Sdimbool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( 92351290Sdim llvm::StringRef program, llvm::StringRef register_name, 93351290Sdim llvm::Triple::ArchType arch_type, Stream &stream) { 94351290Sdim llvm::BumpPtrAllocator node_alloc; 95351290Sdim Node *target_program = 96360784Sdim ResolveFPOProgram(program, register_name, arch_type, node_alloc); 97351290Sdim if (target_program == nullptr) { 98351290Sdim return false; 99351290Sdim } 100351290Sdim 101351290Sdim ToDWARF(*target_program, stream); 102351290Sdim return true; 103351290Sdim} 104