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" 13758657e5SAleksandr Urakov #include "lldb/Core/dwarf.h" 14*4eda12aeSPavel Labath #include "lldb/Symbol/PostfixExpression.h" 15758657e5SAleksandr Urakov #include "lldb/Utility/LLDBAssert.h" 16758657e5SAleksandr Urakov #include "lldb/Utility/Stream.h" 17758657e5SAleksandr Urakov #include "llvm/ADT/DenseMap.h" 18758657e5SAleksandr Urakov 19758657e5SAleksandr Urakov #include "llvm/ADT/StringExtras.h" 20758657e5SAleksandr Urakov #include "llvm/DebugInfo/CodeView/CodeView.h" 21758657e5SAleksandr Urakov #include "llvm/DebugInfo/CodeView/EnumTables.h" 22758657e5SAleksandr Urakov 23758657e5SAleksandr Urakov using namespace lldb; 24758657e5SAleksandr Urakov using namespace lldb_private; 25*4eda12aeSPavel Labath using namespace lldb_private::postfix; 26758657e5SAleksandr Urakov 27758657e5SAleksandr Urakov namespace { 28758657e5SAleksandr Urakov 291c4ee160SPavel Labath class NodeAllocator { 301c4ee160SPavel Labath public: 311c4ee160SPavel Labath template <typename T, typename... Args> T *makeNode(Args &&... args) { 3285ce053dSPavel Labath static_assert(std::is_trivially_destructible<T>::value, 3385ce053dSPavel Labath "This object will not be destroyed!"); 341c4ee160SPavel Labath void *new_node_mem = m_alloc.Allocate(sizeof(T), alignof(T)); 351c4ee160SPavel Labath return new (new_node_mem) T(std::forward<Args>(args)...); 361c4ee160SPavel Labath } 371c4ee160SPavel Labath 381c4ee160SPavel Labath private: 391c4ee160SPavel Labath llvm::BumpPtrAllocator m_alloc; 401c4ee160SPavel Labath }; 411c4ee160SPavel Labath 42*4eda12aeSPavel Labath class FPOProgramASTVisitorMergeDependent : public Visitor<> { 43758657e5SAleksandr Urakov public: 44*4eda12aeSPavel Labath void Visit(BinaryOpNode &binary, Node *&) override { 4585ce053dSPavel Labath Dispatch(binary.Left()); 4685ce053dSPavel Labath Dispatch(binary.Right()); 4785ce053dSPavel Labath } 4885ce053dSPavel Labath 49*4eda12aeSPavel Labath void Visit(UnaryOpNode &unary, Node *&) override { 5085ce053dSPavel Labath Dispatch(unary.Operand()); 5185ce053dSPavel Labath } 5285ce053dSPavel Labath 53*4eda12aeSPavel Labath void Visit(RegisterNode &, Node *&) override {} 54*4eda12aeSPavel Labath void Visit(IntegerNode &, Node *&) override {} 55*4eda12aeSPavel Labath void Visit(SymbolNode &symbol, Node *&ref) override; 5685ce053dSPavel Labath 57*4eda12aeSPavel Labath static void 58*4eda12aeSPavel Labath Merge(const llvm::DenseMap<llvm::StringRef, Node *> &dependent_programs, 59*4eda12aeSPavel Labath Node *&ast) { 6085ce053dSPavel Labath FPOProgramASTVisitorMergeDependent(dependent_programs).Dispatch(ast); 6185ce053dSPavel Labath } 6285ce053dSPavel Labath 6385ce053dSPavel Labath private: 64758657e5SAleksandr Urakov FPOProgramASTVisitorMergeDependent( 65*4eda12aeSPavel Labath const llvm::DenseMap<llvm::StringRef, Node *> &dependent_programs) 66758657e5SAleksandr Urakov : m_dependent_programs(dependent_programs) {} 67758657e5SAleksandr Urakov 68*4eda12aeSPavel Labath const llvm::DenseMap<llvm::StringRef, Node *> &m_dependent_programs; 69758657e5SAleksandr Urakov }; 70758657e5SAleksandr Urakov 71*4eda12aeSPavel Labath void FPOProgramASTVisitorMergeDependent::Visit(SymbolNode &symbol, Node *&ref) { 7285ce053dSPavel Labath auto it = m_dependent_programs.find(symbol.GetName()); 7385ce053dSPavel Labath if (it == m_dependent_programs.end()) 7485ce053dSPavel Labath return; 7585ce053dSPavel Labath 7685ce053dSPavel Labath ref = it->second; 7785ce053dSPavel Labath Dispatch(ref); 78758657e5SAleksandr Urakov } 79758657e5SAleksandr Urakov 80*4eda12aeSPavel Labath class FPOProgramASTVisitorResolveRegisterRefs : public Visitor<bool> { 81758657e5SAleksandr Urakov public: 82*4eda12aeSPavel Labath static bool 83*4eda12aeSPavel Labath Resolve(const llvm::DenseMap<llvm::StringRef, Node *> &dependent_programs, 84*4eda12aeSPavel Labath llvm::Triple::ArchType arch_type, NodeAllocator &alloc, Node *&ast) { 8585ce053dSPavel Labath return FPOProgramASTVisitorResolveRegisterRefs(dependent_programs, 8685ce053dSPavel Labath arch_type, alloc) 8785ce053dSPavel Labath .Dispatch(ast); 8885ce053dSPavel Labath } 8985ce053dSPavel Labath 90*4eda12aeSPavel Labath bool Visit(BinaryOpNode &binary, Node *&) override { 9185ce053dSPavel Labath return Dispatch(binary.Left()) && Dispatch(binary.Right()); 9285ce053dSPavel Labath } 9385ce053dSPavel Labath 94*4eda12aeSPavel Labath bool Visit(UnaryOpNode &unary, Node *&) override { 9585ce053dSPavel Labath return Dispatch(unary.Operand()); 9685ce053dSPavel Labath } 9785ce053dSPavel Labath 98*4eda12aeSPavel Labath bool Visit(RegisterNode &, Node *&) override { return true; } 9985ce053dSPavel Labath 100*4eda12aeSPavel Labath bool Visit(IntegerNode &, Node *&) override { return true; } 10185ce053dSPavel Labath 102*4eda12aeSPavel Labath bool Visit(SymbolNode &symbol, Node *&ref) override; 10385ce053dSPavel Labath 10485ce053dSPavel Labath private: 105758657e5SAleksandr Urakov FPOProgramASTVisitorResolveRegisterRefs( 106*4eda12aeSPavel Labath const llvm::DenseMap<llvm::StringRef, Node *> &dependent_programs, 1071c4ee160SPavel Labath llvm::Triple::ArchType arch_type, NodeAllocator &alloc) 1081c4ee160SPavel Labath : m_dependent_programs(dependent_programs), m_arch_type(arch_type), 1091c4ee160SPavel Labath m_alloc(alloc) {} 110758657e5SAleksandr Urakov 111*4eda12aeSPavel Labath const llvm::DenseMap<llvm::StringRef, Node *> &m_dependent_programs; 112758657e5SAleksandr Urakov llvm::Triple::ArchType m_arch_type; 1131c4ee160SPavel Labath NodeAllocator &m_alloc; 114758657e5SAleksandr Urakov }; 115758657e5SAleksandr Urakov 1161c4ee160SPavel Labath static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::ArchType arch_type) { 1171c4ee160SPavel Labath // lookup register name to get lldb register number 1181c4ee160SPavel Labath llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names = 1191c4ee160SPavel Labath llvm::codeview::getRegisterNames(); 1201c4ee160SPavel Labath auto it = llvm::find_if( 1211c4ee160SPavel Labath register_names, 1221c4ee160SPavel Labath [®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) { 1231c4ee160SPavel Labath return reg_name.compare_lower(register_entry.Name) == 0; 1241c4ee160SPavel Labath }); 125758657e5SAleksandr Urakov 1261c4ee160SPavel Labath if (it == register_names.end()) 1271c4ee160SPavel Labath return LLDB_INVALID_REGNUM; 1281c4ee160SPavel Labath 1291c4ee160SPavel Labath auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value); 1301c4ee160SPavel Labath return npdb::GetLLDBRegisterNumber(arch_type, reg_id); 131758657e5SAleksandr Urakov } 1321c4ee160SPavel Labath 133*4eda12aeSPavel Labath bool FPOProgramASTVisitorResolveRegisterRefs::Visit(SymbolNode &symbol, 134*4eda12aeSPavel Labath Node *&ref) { 1351c4ee160SPavel Labath // Look up register reference as lvalue in preceding assignments. 13685ce053dSPavel Labath auto it = m_dependent_programs.find(symbol.GetName()); 1371c4ee160SPavel Labath if (it != m_dependent_programs.end()) { 1381c4ee160SPavel Labath // Dependent programs are handled elsewhere. 1391c4ee160SPavel Labath return true; 1401c4ee160SPavel Labath } 1411c4ee160SPavel Labath 1421c4ee160SPavel Labath uint32_t reg_num = 14385ce053dSPavel Labath ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), m_arch_type); 1441c4ee160SPavel Labath 1451c4ee160SPavel Labath if (reg_num == LLDB_INVALID_REGNUM) 1461c4ee160SPavel Labath return false; 1471c4ee160SPavel Labath 148*4eda12aeSPavel Labath ref = m_alloc.makeNode<RegisterNode>(reg_num); 1491c4ee160SPavel Labath return true; 150758657e5SAleksandr Urakov } 151758657e5SAleksandr Urakov 152*4eda12aeSPavel Labath class FPOProgramASTVisitorDWARFCodegen : public Visitor<> { 153758657e5SAleksandr Urakov public: 154*4eda12aeSPavel Labath static void Emit(Stream &stream, Node *&ast) { 15585ce053dSPavel Labath FPOProgramASTVisitorDWARFCodegen(stream).Dispatch(ast); 15685ce053dSPavel Labath } 15785ce053dSPavel Labath 158*4eda12aeSPavel Labath void Visit(RegisterNode ®, Node *&); 159*4eda12aeSPavel Labath void Visit(BinaryOpNode &binary, Node *&); 160*4eda12aeSPavel Labath void Visit(UnaryOpNode &unary, Node *&); 161*4eda12aeSPavel Labath void Visit(SymbolNode &symbol, Node *&) { 16285ce053dSPavel Labath llvm_unreachable("Symbols should have been resolved by now!"); 16385ce053dSPavel Labath } 164*4eda12aeSPavel Labath void Visit(IntegerNode &integer, Node *&); 16585ce053dSPavel Labath 16685ce053dSPavel Labath private: 167758657e5SAleksandr Urakov FPOProgramASTVisitorDWARFCodegen(Stream &stream) : m_out_stream(stream) {} 168758657e5SAleksandr Urakov 169758657e5SAleksandr Urakov Stream &m_out_stream; 170758657e5SAleksandr Urakov }; 171758657e5SAleksandr Urakov 172*4eda12aeSPavel Labath void FPOProgramASTVisitorDWARFCodegen::Visit(RegisterNode ®, Node *&) { 173*4eda12aeSPavel Labath uint32_t reg_num = reg.GetRegNum(); 174758657e5SAleksandr Urakov lldbassert(reg_num != LLDB_INVALID_REGNUM); 175758657e5SAleksandr Urakov 176758657e5SAleksandr Urakov if (reg_num > 31) { 177758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_bregx); 178758657e5SAleksandr Urakov m_out_stream.PutULEB128(reg_num); 179758657e5SAleksandr Urakov } else 180758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_breg0 + reg_num); 181758657e5SAleksandr Urakov 182758657e5SAleksandr Urakov m_out_stream.PutSLEB128(0); 183758657e5SAleksandr Urakov } 184758657e5SAleksandr Urakov 185*4eda12aeSPavel Labath void FPOProgramASTVisitorDWARFCodegen::Visit(IntegerNode &integer, Node *&) { 18685ce053dSPavel Labath uint32_t value = integer.GetValue(); 187758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_constu); 188758657e5SAleksandr Urakov m_out_stream.PutULEB128(value); 189758657e5SAleksandr Urakov } 190758657e5SAleksandr Urakov 191*4eda12aeSPavel Labath void FPOProgramASTVisitorDWARFCodegen::Visit(BinaryOpNode &binary, Node *&) { 19285ce053dSPavel Labath Dispatch(binary.Left()); 19385ce053dSPavel Labath Dispatch(binary.Right()); 194758657e5SAleksandr Urakov 19585ce053dSPavel Labath switch (binary.GetOpType()) { 196*4eda12aeSPavel Labath case BinaryOpNode::Plus: 197758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_plus); 198758657e5SAleksandr Urakov // NOTE: can be optimized by using DW_OP_plus_uconst opcpode 199758657e5SAleksandr Urakov // if right child node is constant value 200758657e5SAleksandr Urakov break; 201*4eda12aeSPavel Labath case BinaryOpNode::Minus: 202758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_minus); 203758657e5SAleksandr Urakov break; 204*4eda12aeSPavel Labath case BinaryOpNode::Align: 205758657e5SAleksandr Urakov // emit align operator a @ b as 206758657e5SAleksandr Urakov // a & ~(b - 1) 207758657e5SAleksandr Urakov // NOTE: implicitly assuming that b is power of 2 208758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_lit1); 209758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_minus); 210758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_not); 211758657e5SAleksandr Urakov 212758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_and); 213758657e5SAleksandr Urakov break; 214758657e5SAleksandr Urakov } 215758657e5SAleksandr Urakov } 216758657e5SAleksandr Urakov 217*4eda12aeSPavel Labath void FPOProgramASTVisitorDWARFCodegen::Visit(UnaryOpNode &unary, Node *&) { 21885ce053dSPavel Labath Dispatch(unary.Operand()); 219758657e5SAleksandr Urakov 22085ce053dSPavel Labath switch (unary.GetOpType()) { 221*4eda12aeSPavel Labath case UnaryOpNode::Deref: 222758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_deref); 223758657e5SAleksandr Urakov break; 224758657e5SAleksandr Urakov } 225758657e5SAleksandr Urakov } 226758657e5SAleksandr Urakov 227758657e5SAleksandr Urakov } // namespace 228758657e5SAleksandr Urakov 229758657e5SAleksandr Urakov static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program, 230758657e5SAleksandr Urakov NodeAllocator &alloc, 231758657e5SAleksandr Urakov llvm::StringRef ®ister_name, 232*4eda12aeSPavel Labath Node *&ast) { 233758657e5SAleksandr Urakov llvm::SmallVector<llvm::StringRef, 16> tokens; 234758657e5SAleksandr Urakov llvm::SplitString(program, tokens, " "); 235758657e5SAleksandr Urakov 236758657e5SAleksandr Urakov if (tokens.empty()) 237758657e5SAleksandr Urakov return false; 238758657e5SAleksandr Urakov 239*4eda12aeSPavel Labath llvm::SmallVector<Node *, 4> eval_stack; 240758657e5SAleksandr Urakov 241*4eda12aeSPavel Labath llvm::DenseMap<llvm::StringRef, BinaryOpNode::OpType> ops_binary = { 242*4eda12aeSPavel Labath {"+", BinaryOpNode::Plus}, 243*4eda12aeSPavel Labath {"-", BinaryOpNode::Minus}, 244*4eda12aeSPavel Labath {"@", BinaryOpNode::Align}, 245758657e5SAleksandr Urakov }; 246758657e5SAleksandr Urakov 247*4eda12aeSPavel Labath llvm::DenseMap<llvm::StringRef, UnaryOpNode::OpType> ops_unary = { 248*4eda12aeSPavel Labath {"^", UnaryOpNode::Deref}, 249758657e5SAleksandr Urakov }; 250758657e5SAleksandr Urakov 251758657e5SAleksandr Urakov constexpr llvm::StringLiteral ra_search_keyword = ".raSearch"; 252758657e5SAleksandr Urakov 253758657e5SAleksandr Urakov // lvalue of assignment is always first token 254758657e5SAleksandr Urakov // rvalue program goes next 255758657e5SAleksandr Urakov for (size_t i = 1; i < tokens.size(); ++i) { 256758657e5SAleksandr Urakov llvm::StringRef cur = tokens[i]; 257758657e5SAleksandr Urakov 258758657e5SAleksandr Urakov auto ops_binary_it = ops_binary.find(cur); 259758657e5SAleksandr Urakov if (ops_binary_it != ops_binary.end()) { 260758657e5SAleksandr Urakov // token is binary operator 261758657e5SAleksandr Urakov if (eval_stack.size() < 2) { 262758657e5SAleksandr Urakov return false; 263758657e5SAleksandr Urakov } 264*4eda12aeSPavel Labath Node *right = eval_stack.pop_back_val(); 265*4eda12aeSPavel Labath Node *left = eval_stack.pop_back_val(); 266*4eda12aeSPavel Labath Node *node = 267*4eda12aeSPavel Labath alloc.makeNode<BinaryOpNode>(ops_binary_it->second, *left, *right); 268758657e5SAleksandr Urakov eval_stack.push_back(node); 269758657e5SAleksandr Urakov continue; 270758657e5SAleksandr Urakov } 271758657e5SAleksandr Urakov 272758657e5SAleksandr Urakov auto ops_unary_it = ops_unary.find(cur); 273758657e5SAleksandr Urakov if (ops_unary_it != ops_unary.end()) { 274758657e5SAleksandr Urakov // token is unary operator 275758657e5SAleksandr Urakov if (eval_stack.empty()) { 276758657e5SAleksandr Urakov return false; 277758657e5SAleksandr Urakov } 278*4eda12aeSPavel Labath Node *operand = eval_stack.pop_back_val(); 279*4eda12aeSPavel Labath Node *node = alloc.makeNode<UnaryOpNode>(ops_unary_it->second, *operand); 280758657e5SAleksandr Urakov eval_stack.push_back(node); 281758657e5SAleksandr Urakov continue; 282758657e5SAleksandr Urakov } 283758657e5SAleksandr Urakov 284758657e5SAleksandr Urakov if (cur.startswith("$")) { 285*4eda12aeSPavel Labath eval_stack.push_back(alloc.makeNode<SymbolNode>(cur)); 286758657e5SAleksandr Urakov continue; 287758657e5SAleksandr Urakov } 288758657e5SAleksandr Urakov 289758657e5SAleksandr Urakov if (cur == ra_search_keyword) { 290758657e5SAleksandr Urakov // TODO: .raSearch is unsupported 291758657e5SAleksandr Urakov return false; 292758657e5SAleksandr Urakov } 293758657e5SAleksandr Urakov 294758657e5SAleksandr Urakov uint32_t value; 295758657e5SAleksandr Urakov if (!cur.getAsInteger(10, value)) { 296758657e5SAleksandr Urakov // token is integer literal 297*4eda12aeSPavel Labath eval_stack.push_back(alloc.makeNode<IntegerNode>(value)); 298758657e5SAleksandr Urakov continue; 299758657e5SAleksandr Urakov } 300758657e5SAleksandr Urakov 301758657e5SAleksandr Urakov // unexpected token 302758657e5SAleksandr Urakov return false; 303758657e5SAleksandr Urakov } 304758657e5SAleksandr Urakov 305758657e5SAleksandr Urakov if (eval_stack.size() != 1) { 306758657e5SAleksandr Urakov return false; 307758657e5SAleksandr Urakov } 308758657e5SAleksandr Urakov 309758657e5SAleksandr Urakov register_name = tokens[0]; 310758657e5SAleksandr Urakov ast = eval_stack.pop_back_val(); 311758657e5SAleksandr Urakov 312758657e5SAleksandr Urakov return true; 313758657e5SAleksandr Urakov } 314758657e5SAleksandr Urakov 315*4eda12aeSPavel Labath static Node *ParseFPOProgram(llvm::StringRef program, 316758657e5SAleksandr Urakov llvm::StringRef register_name, 317758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type, 318758657e5SAleksandr Urakov NodeAllocator &alloc) { 319*4eda12aeSPavel Labath llvm::DenseMap<llvm::StringRef, Node *> dependent_programs; 320758657e5SAleksandr Urakov 321758657e5SAleksandr Urakov size_t cur = 0; 322758657e5SAleksandr Urakov while (true) { 323758657e5SAleksandr Urakov size_t assign_index = program.find('=', cur); 324758657e5SAleksandr Urakov if (assign_index == llvm::StringRef::npos) { 325758657e5SAleksandr Urakov llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos); 326758657e5SAleksandr Urakov if (!tail.trim().empty()) { 327758657e5SAleksandr Urakov // missing assign operator 328758657e5SAleksandr Urakov return nullptr; 329758657e5SAleksandr Urakov } 330758657e5SAleksandr Urakov break; 331758657e5SAleksandr Urakov } 332758657e5SAleksandr Urakov llvm::StringRef assignment_program = program.slice(cur, assign_index); 333758657e5SAleksandr Urakov 334758657e5SAleksandr Urakov llvm::StringRef lvalue_name; 335*4eda12aeSPavel Labath Node *rvalue_ast = nullptr; 336758657e5SAleksandr Urakov if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name, 337758657e5SAleksandr Urakov rvalue_ast)) { 338758657e5SAleksandr Urakov return nullptr; 339758657e5SAleksandr Urakov } 340758657e5SAleksandr Urakov 341758657e5SAleksandr Urakov lldbassert(rvalue_ast); 342758657e5SAleksandr Urakov 343758657e5SAleksandr Urakov // check & resolve assignment program 34485ce053dSPavel Labath if (!FPOProgramASTVisitorResolveRegisterRefs::Resolve( 34585ce053dSPavel Labath dependent_programs, arch_type, alloc, rvalue_ast)) 346758657e5SAleksandr Urakov return nullptr; 347758657e5SAleksandr Urakov 348758657e5SAleksandr Urakov if (lvalue_name == register_name) { 349758657e5SAleksandr Urakov // found target assignment program - no need to parse further 350758657e5SAleksandr Urakov 351758657e5SAleksandr Urakov // emplace valid dependent subtrees to make target assignment independent 352758657e5SAleksandr Urakov // from predecessors 35385ce053dSPavel Labath FPOProgramASTVisitorMergeDependent::Merge(dependent_programs, rvalue_ast); 354758657e5SAleksandr Urakov 355758657e5SAleksandr Urakov return rvalue_ast; 356758657e5SAleksandr Urakov } 357758657e5SAleksandr Urakov 358758657e5SAleksandr Urakov dependent_programs[lvalue_name] = rvalue_ast; 359758657e5SAleksandr Urakov cur = assign_index + 1; 360758657e5SAleksandr Urakov } 361758657e5SAleksandr Urakov 362758657e5SAleksandr Urakov return nullptr; 363758657e5SAleksandr Urakov } 364758657e5SAleksandr Urakov 365758657e5SAleksandr Urakov bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( 366758657e5SAleksandr Urakov llvm::StringRef program, llvm::StringRef register_name, 367758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type, Stream &stream) { 368758657e5SAleksandr Urakov NodeAllocator node_alloc; 369*4eda12aeSPavel Labath Node *target_program = 370758657e5SAleksandr Urakov ParseFPOProgram(program, register_name, arch_type, node_alloc); 371758657e5SAleksandr Urakov if (target_program == nullptr) { 372758657e5SAleksandr Urakov return false; 373758657e5SAleksandr Urakov } 374758657e5SAleksandr Urakov 37585ce053dSPavel Labath FPOProgramASTVisitorDWARFCodegen::Emit(stream, target_program); 376758657e5SAleksandr Urakov return true; 377758657e5SAleksandr Urakov } 378