1758657e5SAleksandr Urakov //===-- PDBFPOProgramToDWARFExpression.cpp ----------------------*- C++ -*-===// 2758657e5SAleksandr Urakov // 3*ee21a66aSAleksandr Urakov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*ee21a66aSAleksandr Urakov // See https://llvm.org/LICENSE.txt for license information. 5*ee21a66aSAleksandr 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" 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; 24758657e5SAleksandr Urakov 25758657e5SAleksandr Urakov namespace { 26758657e5SAleksandr Urakov 27758657e5SAleksandr Urakov class FPOProgramNode; 28758657e5SAleksandr Urakov class FPOProgramASTVisitor; 29758657e5SAleksandr Urakov 30758657e5SAleksandr Urakov class FPOProgramNode { 31758657e5SAleksandr Urakov public: 32758657e5SAleksandr Urakov enum Kind { 33758657e5SAleksandr Urakov Register, 34758657e5SAleksandr Urakov IntegerLiteral, 35758657e5SAleksandr Urakov BinaryOp, 36758657e5SAleksandr Urakov UnaryOp, 37758657e5SAleksandr Urakov }; 38758657e5SAleksandr Urakov 39758657e5SAleksandr Urakov protected: 40758657e5SAleksandr Urakov FPOProgramNode(Kind kind) : m_token_kind(kind) {} 41758657e5SAleksandr Urakov 42758657e5SAleksandr Urakov public: 43758657e5SAleksandr Urakov virtual ~FPOProgramNode() = default; 44758657e5SAleksandr Urakov virtual void Accept(FPOProgramASTVisitor *visitor) = 0; 45758657e5SAleksandr Urakov 46758657e5SAleksandr Urakov Kind GetKind() const { return m_token_kind; } 47758657e5SAleksandr Urakov 48758657e5SAleksandr Urakov private: 49758657e5SAleksandr Urakov Kind m_token_kind; 50758657e5SAleksandr Urakov }; 51758657e5SAleksandr Urakov 52758657e5SAleksandr Urakov class FPOProgramNodeRegisterRef : public FPOProgramNode { 53758657e5SAleksandr Urakov public: 54758657e5SAleksandr Urakov FPOProgramNodeRegisterRef(llvm::StringRef name) 55758657e5SAleksandr Urakov : FPOProgramNode(Register), m_name(name) {} 56758657e5SAleksandr Urakov 57758657e5SAleksandr Urakov void Accept(FPOProgramASTVisitor *visitor) override; 58758657e5SAleksandr Urakov 59758657e5SAleksandr Urakov llvm::StringRef GetName() const { return m_name; } 60758657e5SAleksandr Urakov uint32_t GetLLDBRegNum() const { return m_lldb_reg_num; } 61758657e5SAleksandr Urakov 62758657e5SAleksandr Urakov bool ResolveLLDBRegisterNum(llvm::Triple::ArchType arch_type); 63758657e5SAleksandr Urakov 64758657e5SAleksandr Urakov private: 65758657e5SAleksandr Urakov llvm::StringRef m_name; 66758657e5SAleksandr Urakov uint32_t m_lldb_reg_num = LLDB_INVALID_REGNUM; 67758657e5SAleksandr Urakov }; 68758657e5SAleksandr Urakov 69758657e5SAleksandr Urakov bool FPOProgramNodeRegisterRef::ResolveLLDBRegisterNum( 70758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type) { 71758657e5SAleksandr Urakov 72758657e5SAleksandr Urakov llvm::StringRef reg_name = m_name.slice(1, m_name.size()); 73758657e5SAleksandr Urakov 74758657e5SAleksandr Urakov // lookup register name to get lldb register number 75758657e5SAleksandr Urakov llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names = 76758657e5SAleksandr Urakov llvm::codeview::getRegisterNames(); 77758657e5SAleksandr Urakov auto it = llvm::find_if( 78758657e5SAleksandr Urakov register_names, 79758657e5SAleksandr Urakov [®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) { 80758657e5SAleksandr Urakov return reg_name.compare_lower(register_entry.Name) == 0; 81758657e5SAleksandr Urakov }); 82758657e5SAleksandr Urakov 83758657e5SAleksandr Urakov if (it == register_names.end()) { 84758657e5SAleksandr Urakov return false; 85758657e5SAleksandr Urakov } 86758657e5SAleksandr Urakov 87758657e5SAleksandr Urakov auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value); 88758657e5SAleksandr Urakov m_lldb_reg_num = npdb::GetLLDBRegisterNumber(arch_type, reg_id); 89758657e5SAleksandr Urakov 90758657e5SAleksandr Urakov return m_lldb_reg_num != LLDB_INVALID_REGNUM; 91758657e5SAleksandr Urakov } 92758657e5SAleksandr Urakov 93758657e5SAleksandr Urakov class FPOProgramNodeIntegerLiteral : public FPOProgramNode { 94758657e5SAleksandr Urakov public: 95758657e5SAleksandr Urakov FPOProgramNodeIntegerLiteral(uint32_t value) 96758657e5SAleksandr Urakov : FPOProgramNode(IntegerLiteral), m_value(value) {} 97758657e5SAleksandr Urakov 98758657e5SAleksandr Urakov void Accept(FPOProgramASTVisitor *visitor) override; 99758657e5SAleksandr Urakov 100758657e5SAleksandr Urakov uint32_t GetValue() const { return m_value; } 101758657e5SAleksandr Urakov 102758657e5SAleksandr Urakov private: 103758657e5SAleksandr Urakov uint32_t m_value; 104758657e5SAleksandr Urakov }; 105758657e5SAleksandr Urakov 106758657e5SAleksandr Urakov class FPOProgramNodeBinaryOp : public FPOProgramNode { 107758657e5SAleksandr Urakov public: 108758657e5SAleksandr Urakov enum OpType { 109758657e5SAleksandr Urakov Plus, 110758657e5SAleksandr Urakov Minus, 111758657e5SAleksandr Urakov Align, 112758657e5SAleksandr Urakov }; 113758657e5SAleksandr Urakov 114758657e5SAleksandr Urakov FPOProgramNodeBinaryOp(OpType op_type, FPOProgramNode *left, 115758657e5SAleksandr Urakov FPOProgramNode *right) 116758657e5SAleksandr Urakov : FPOProgramNode(BinaryOp), m_op_type(op_type), m_left(left), 117758657e5SAleksandr Urakov m_right(right) {} 118758657e5SAleksandr Urakov 119758657e5SAleksandr Urakov void Accept(FPOProgramASTVisitor *visitor) override; 120758657e5SAleksandr Urakov 121758657e5SAleksandr Urakov OpType GetOpType() const { return m_op_type; } 122758657e5SAleksandr Urakov 123758657e5SAleksandr Urakov const FPOProgramNode *Left() const { return m_left; } 124758657e5SAleksandr Urakov FPOProgramNode *&Left() { return m_left; } 125758657e5SAleksandr Urakov 126758657e5SAleksandr Urakov const FPOProgramNode *Right() const { return m_right; } 127758657e5SAleksandr Urakov FPOProgramNode *&Right() { return m_right; } 128758657e5SAleksandr Urakov 129758657e5SAleksandr Urakov private: 130758657e5SAleksandr Urakov OpType m_op_type; 131758657e5SAleksandr Urakov FPOProgramNode *m_left; 132758657e5SAleksandr Urakov FPOProgramNode *m_right; 133758657e5SAleksandr Urakov }; 134758657e5SAleksandr Urakov 135758657e5SAleksandr Urakov class FPOProgramNodeUnaryOp : public FPOProgramNode { 136758657e5SAleksandr Urakov public: 137758657e5SAleksandr Urakov enum OpType { 138758657e5SAleksandr Urakov Deref, 139758657e5SAleksandr Urakov }; 140758657e5SAleksandr Urakov 141758657e5SAleksandr Urakov FPOProgramNodeUnaryOp(OpType op_type, FPOProgramNode *operand) 142758657e5SAleksandr Urakov : FPOProgramNode(UnaryOp), m_op_type(op_type), m_operand(operand) {} 143758657e5SAleksandr Urakov 144758657e5SAleksandr Urakov void Accept(FPOProgramASTVisitor *visitor) override; 145758657e5SAleksandr Urakov 146758657e5SAleksandr Urakov OpType GetOpType() const { return m_op_type; } 147758657e5SAleksandr Urakov 148758657e5SAleksandr Urakov const FPOProgramNode *Operand() const { return m_operand; } 149758657e5SAleksandr Urakov FPOProgramNode *&Operand() { return m_operand; } 150758657e5SAleksandr Urakov 151758657e5SAleksandr Urakov private: 152758657e5SAleksandr Urakov OpType m_op_type; 153758657e5SAleksandr Urakov FPOProgramNode *m_operand; 154758657e5SAleksandr Urakov }; 155758657e5SAleksandr Urakov 156758657e5SAleksandr Urakov class FPOProgramASTVisitor { 157758657e5SAleksandr Urakov public: 158758657e5SAleksandr Urakov virtual ~FPOProgramASTVisitor() = default; 159758657e5SAleksandr Urakov 160758657e5SAleksandr Urakov virtual void Visit(FPOProgramNodeRegisterRef *node) {} 161758657e5SAleksandr Urakov virtual void Visit(FPOProgramNodeIntegerLiteral *node) {} 162758657e5SAleksandr Urakov virtual void Visit(FPOProgramNodeBinaryOp *node) {} 163758657e5SAleksandr Urakov virtual void Visit(FPOProgramNodeUnaryOp *node) {} 164758657e5SAleksandr Urakov }; 165758657e5SAleksandr Urakov 166758657e5SAleksandr Urakov void FPOProgramNodeRegisterRef::Accept(FPOProgramASTVisitor *visitor) { 167758657e5SAleksandr Urakov visitor->Visit(this); 168758657e5SAleksandr Urakov } 169758657e5SAleksandr Urakov 170758657e5SAleksandr Urakov void FPOProgramNodeIntegerLiteral::Accept(FPOProgramASTVisitor *visitor) { 171758657e5SAleksandr Urakov visitor->Visit(this); 172758657e5SAleksandr Urakov } 173758657e5SAleksandr Urakov 174758657e5SAleksandr Urakov void FPOProgramNodeBinaryOp::Accept(FPOProgramASTVisitor *visitor) { 175758657e5SAleksandr Urakov visitor->Visit(this); 176758657e5SAleksandr Urakov } 177758657e5SAleksandr Urakov 178758657e5SAleksandr Urakov void FPOProgramNodeUnaryOp::Accept(FPOProgramASTVisitor *visitor) { 179758657e5SAleksandr Urakov visitor->Visit(this); 180758657e5SAleksandr Urakov } 181758657e5SAleksandr Urakov 182758657e5SAleksandr Urakov class FPOProgramASTVisitorMergeDependent : public FPOProgramASTVisitor { 183758657e5SAleksandr Urakov public: 184758657e5SAleksandr Urakov FPOProgramASTVisitorMergeDependent( 185758657e5SAleksandr Urakov const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> 186758657e5SAleksandr Urakov &dependent_programs) 187758657e5SAleksandr Urakov : m_dependent_programs(dependent_programs) {} 188758657e5SAleksandr Urakov 189758657e5SAleksandr Urakov void Merge(FPOProgramNode *&node_ref); 190758657e5SAleksandr Urakov 191758657e5SAleksandr Urakov private: 192758657e5SAleksandr Urakov void Visit(FPOProgramNodeRegisterRef *node) override {} 193758657e5SAleksandr Urakov void Visit(FPOProgramNodeIntegerLiteral *node) override {} 194758657e5SAleksandr Urakov void Visit(FPOProgramNodeBinaryOp *node) override; 195758657e5SAleksandr Urakov void Visit(FPOProgramNodeUnaryOp *node) override; 196758657e5SAleksandr Urakov 197758657e5SAleksandr Urakov void TryReplace(FPOProgramNode *&node_ref) const; 198758657e5SAleksandr Urakov 199758657e5SAleksandr Urakov private: 200758657e5SAleksandr Urakov const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs; 201758657e5SAleksandr Urakov }; 202758657e5SAleksandr Urakov 203758657e5SAleksandr Urakov void FPOProgramASTVisitorMergeDependent::Merge(FPOProgramNode *&node_ref) { 204758657e5SAleksandr Urakov TryReplace(node_ref); 205758657e5SAleksandr Urakov node_ref->Accept(this); 206758657e5SAleksandr Urakov } 207758657e5SAleksandr Urakov 208758657e5SAleksandr Urakov void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeBinaryOp *node) { 209758657e5SAleksandr Urakov Merge(node->Left()); 210758657e5SAleksandr Urakov Merge(node->Right()); 211758657e5SAleksandr Urakov } 212758657e5SAleksandr Urakov void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeUnaryOp *node) { 213758657e5SAleksandr Urakov Merge(node->Operand()); 214758657e5SAleksandr Urakov } 215758657e5SAleksandr Urakov 216758657e5SAleksandr Urakov void FPOProgramASTVisitorMergeDependent::TryReplace( 217758657e5SAleksandr Urakov FPOProgramNode *&node_ref) const { 218758657e5SAleksandr Urakov 219758657e5SAleksandr Urakov while (node_ref->GetKind() == FPOProgramNode::Register) { 220758657e5SAleksandr Urakov auto *node_register_ref = 221758657e5SAleksandr Urakov static_cast<FPOProgramNodeRegisterRef *>(node_ref); 222758657e5SAleksandr Urakov 223758657e5SAleksandr Urakov auto it = m_dependent_programs.find(node_register_ref->GetName()); 224758657e5SAleksandr Urakov if (it == m_dependent_programs.end()) { 225758657e5SAleksandr Urakov break; 226758657e5SAleksandr Urakov } 227758657e5SAleksandr Urakov 228758657e5SAleksandr Urakov node_ref = it->second; 229758657e5SAleksandr Urakov } 230758657e5SAleksandr Urakov } 231758657e5SAleksandr Urakov 232758657e5SAleksandr Urakov class FPOProgramASTVisitorResolveRegisterRefs : public FPOProgramASTVisitor { 233758657e5SAleksandr Urakov public: 234758657e5SAleksandr Urakov FPOProgramASTVisitorResolveRegisterRefs( 235758657e5SAleksandr Urakov const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> 236758657e5SAleksandr Urakov &dependent_programs, 237758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type) 238758657e5SAleksandr Urakov : m_dependent_programs(dependent_programs), m_arch_type(arch_type) {} 239758657e5SAleksandr Urakov 240758657e5SAleksandr Urakov bool Resolve(FPOProgramNode *program); 241758657e5SAleksandr Urakov 242758657e5SAleksandr Urakov private: 243758657e5SAleksandr Urakov void Visit(FPOProgramNodeRegisterRef *node) override; 244758657e5SAleksandr Urakov void Visit(FPOProgramNodeIntegerLiteral *node) override {} 245758657e5SAleksandr Urakov void Visit(FPOProgramNodeBinaryOp *node) override; 246758657e5SAleksandr Urakov void Visit(FPOProgramNodeUnaryOp *node) override; 247758657e5SAleksandr Urakov 248758657e5SAleksandr Urakov private: 249758657e5SAleksandr Urakov const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs; 250758657e5SAleksandr Urakov llvm::Triple::ArchType m_arch_type; 251758657e5SAleksandr Urakov bool m_no_error_flag = true; 252758657e5SAleksandr Urakov }; 253758657e5SAleksandr Urakov 254758657e5SAleksandr Urakov bool FPOProgramASTVisitorResolveRegisterRefs::Resolve(FPOProgramNode *program) { 255758657e5SAleksandr Urakov program->Accept(this); 256758657e5SAleksandr Urakov return m_no_error_flag; 257758657e5SAleksandr Urakov } 258758657e5SAleksandr Urakov 259758657e5SAleksandr Urakov void FPOProgramASTVisitorResolveRegisterRefs::Visit( 260758657e5SAleksandr Urakov FPOProgramNodeRegisterRef *node) { 261758657e5SAleksandr Urakov 262758657e5SAleksandr Urakov // lookup register reference as lvalue in predecedent assignments 263758657e5SAleksandr Urakov auto it = m_dependent_programs.find(node->GetName()); 264758657e5SAleksandr Urakov if (it != m_dependent_programs.end()) { 265758657e5SAleksandr Urakov // dependent programs are already resolved and valid 266758657e5SAleksandr Urakov return; 267758657e5SAleksandr Urakov } 268758657e5SAleksandr Urakov // try to resolve register reference as lldb register name 269758657e5SAleksandr Urakov m_no_error_flag = node->ResolveLLDBRegisterNum(m_arch_type); 270758657e5SAleksandr Urakov } 271758657e5SAleksandr Urakov 272758657e5SAleksandr Urakov void FPOProgramASTVisitorResolveRegisterRefs::Visit( 273758657e5SAleksandr Urakov FPOProgramNodeBinaryOp *node) { 274758657e5SAleksandr Urakov m_no_error_flag = Resolve(node->Left()) && Resolve(node->Right()); 275758657e5SAleksandr Urakov } 276758657e5SAleksandr Urakov 277758657e5SAleksandr Urakov void FPOProgramASTVisitorResolveRegisterRefs::Visit( 278758657e5SAleksandr Urakov FPOProgramNodeUnaryOp *node) { 279758657e5SAleksandr Urakov m_no_error_flag = Resolve(node->Operand()); 280758657e5SAleksandr Urakov } 281758657e5SAleksandr Urakov 282758657e5SAleksandr Urakov class FPOProgramASTVisitorDWARFCodegen : public FPOProgramASTVisitor { 283758657e5SAleksandr Urakov public: 284758657e5SAleksandr Urakov FPOProgramASTVisitorDWARFCodegen(Stream &stream) : m_out_stream(stream) {} 285758657e5SAleksandr Urakov 286758657e5SAleksandr Urakov void Emit(FPOProgramNode *program); 287758657e5SAleksandr Urakov 288758657e5SAleksandr Urakov private: 289758657e5SAleksandr Urakov void Visit(FPOProgramNodeRegisterRef *node) override; 290758657e5SAleksandr Urakov void Visit(FPOProgramNodeIntegerLiteral *node) override; 291758657e5SAleksandr Urakov void Visit(FPOProgramNodeBinaryOp *node) override; 292758657e5SAleksandr Urakov void Visit(FPOProgramNodeUnaryOp *node) override; 293758657e5SAleksandr Urakov 294758657e5SAleksandr Urakov private: 295758657e5SAleksandr Urakov Stream &m_out_stream; 296758657e5SAleksandr Urakov }; 297758657e5SAleksandr Urakov 298758657e5SAleksandr Urakov void FPOProgramASTVisitorDWARFCodegen::Emit(FPOProgramNode *program) { 299758657e5SAleksandr Urakov program->Accept(this); 300758657e5SAleksandr Urakov } 301758657e5SAleksandr Urakov 302758657e5SAleksandr Urakov void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeRegisterRef *node) { 303758657e5SAleksandr Urakov 304758657e5SAleksandr Urakov uint32_t reg_num = node->GetLLDBRegNum(); 305758657e5SAleksandr Urakov lldbassert(reg_num != LLDB_INVALID_REGNUM); 306758657e5SAleksandr Urakov 307758657e5SAleksandr Urakov if (reg_num > 31) { 308758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_bregx); 309758657e5SAleksandr Urakov m_out_stream.PutULEB128(reg_num); 310758657e5SAleksandr Urakov } else 311758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_breg0 + reg_num); 312758657e5SAleksandr Urakov 313758657e5SAleksandr Urakov m_out_stream.PutSLEB128(0); 314758657e5SAleksandr Urakov } 315758657e5SAleksandr Urakov 316758657e5SAleksandr Urakov void FPOProgramASTVisitorDWARFCodegen::Visit( 317758657e5SAleksandr Urakov FPOProgramNodeIntegerLiteral *node) { 318758657e5SAleksandr Urakov uint32_t value = node->GetValue(); 319758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_constu); 320758657e5SAleksandr Urakov m_out_stream.PutULEB128(value); 321758657e5SAleksandr Urakov } 322758657e5SAleksandr Urakov 323758657e5SAleksandr Urakov void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeBinaryOp *node) { 324758657e5SAleksandr Urakov 325758657e5SAleksandr Urakov Emit(node->Left()); 326758657e5SAleksandr Urakov Emit(node->Right()); 327758657e5SAleksandr Urakov 328758657e5SAleksandr Urakov switch (node->GetOpType()) { 329758657e5SAleksandr Urakov case FPOProgramNodeBinaryOp::Plus: 330758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_plus); 331758657e5SAleksandr Urakov // NOTE: can be optimized by using DW_OP_plus_uconst opcpode 332758657e5SAleksandr Urakov // if right child node is constant value 333758657e5SAleksandr Urakov break; 334758657e5SAleksandr Urakov case FPOProgramNodeBinaryOp::Minus: 335758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_minus); 336758657e5SAleksandr Urakov break; 337758657e5SAleksandr Urakov case FPOProgramNodeBinaryOp::Align: 338758657e5SAleksandr Urakov // emit align operator a @ b as 339758657e5SAleksandr Urakov // a & ~(b - 1) 340758657e5SAleksandr Urakov // NOTE: implicitly assuming that b is power of 2 341758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_lit1); 342758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_minus); 343758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_not); 344758657e5SAleksandr Urakov 345758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_and); 346758657e5SAleksandr Urakov break; 347758657e5SAleksandr Urakov } 348758657e5SAleksandr Urakov } 349758657e5SAleksandr Urakov 350758657e5SAleksandr Urakov void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeUnaryOp *node) { 351758657e5SAleksandr Urakov Emit(node->Operand()); 352758657e5SAleksandr Urakov 353758657e5SAleksandr Urakov switch (node->GetOpType()) { 354758657e5SAleksandr Urakov case FPOProgramNodeUnaryOp::Deref: 355758657e5SAleksandr Urakov m_out_stream.PutHex8(DW_OP_deref); 356758657e5SAleksandr Urakov break; 357758657e5SAleksandr Urakov } 358758657e5SAleksandr Urakov } 359758657e5SAleksandr Urakov 360758657e5SAleksandr Urakov class NodeAllocator { 361758657e5SAleksandr Urakov public: 362758657e5SAleksandr Urakov template <typename T, typename... Args> T *makeNode(Args &&... args) { 363758657e5SAleksandr Urakov void *new_node_mem = m_alloc.Allocate(sizeof(T), alignof(T)); 364758657e5SAleksandr Urakov return new (new_node_mem) T(std::forward<Args>(args)...); 365758657e5SAleksandr Urakov } 366758657e5SAleksandr Urakov 367758657e5SAleksandr Urakov private: 368758657e5SAleksandr Urakov llvm::BumpPtrAllocator m_alloc; 369758657e5SAleksandr Urakov }; 370758657e5SAleksandr Urakov 371758657e5SAleksandr Urakov } // namespace 372758657e5SAleksandr Urakov 373758657e5SAleksandr Urakov static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program, 374758657e5SAleksandr Urakov NodeAllocator &alloc, 375758657e5SAleksandr Urakov llvm::StringRef ®ister_name, 376758657e5SAleksandr Urakov FPOProgramNode *&ast) { 377758657e5SAleksandr Urakov llvm::SmallVector<llvm::StringRef, 16> tokens; 378758657e5SAleksandr Urakov llvm::SplitString(program, tokens, " "); 379758657e5SAleksandr Urakov 380758657e5SAleksandr Urakov if (tokens.empty()) 381758657e5SAleksandr Urakov return false; 382758657e5SAleksandr Urakov 383758657e5SAleksandr Urakov llvm::SmallVector<FPOProgramNode *, 4> eval_stack; 384758657e5SAleksandr Urakov 385758657e5SAleksandr Urakov llvm::DenseMap<llvm::StringRef, FPOProgramNodeBinaryOp::OpType> ops_binary = { 386758657e5SAleksandr Urakov {"+", FPOProgramNodeBinaryOp::Plus}, 387758657e5SAleksandr Urakov {"-", FPOProgramNodeBinaryOp::Minus}, 388758657e5SAleksandr Urakov {"@", FPOProgramNodeBinaryOp::Align}, 389758657e5SAleksandr Urakov }; 390758657e5SAleksandr Urakov 391758657e5SAleksandr Urakov llvm::DenseMap<llvm::StringRef, FPOProgramNodeUnaryOp::OpType> ops_unary = { 392758657e5SAleksandr Urakov {"^", FPOProgramNodeUnaryOp::Deref}, 393758657e5SAleksandr Urakov }; 394758657e5SAleksandr Urakov 395758657e5SAleksandr Urakov constexpr llvm::StringLiteral ra_search_keyword = ".raSearch"; 396758657e5SAleksandr Urakov 397758657e5SAleksandr Urakov // lvalue of assignment is always first token 398758657e5SAleksandr Urakov // rvalue program goes next 399758657e5SAleksandr Urakov for (size_t i = 1; i < tokens.size(); ++i) { 400758657e5SAleksandr Urakov llvm::StringRef cur = tokens[i]; 401758657e5SAleksandr Urakov 402758657e5SAleksandr Urakov auto ops_binary_it = ops_binary.find(cur); 403758657e5SAleksandr Urakov if (ops_binary_it != ops_binary.end()) { 404758657e5SAleksandr Urakov // token is binary operator 405758657e5SAleksandr Urakov if (eval_stack.size() < 2) { 406758657e5SAleksandr Urakov return false; 407758657e5SAleksandr Urakov } 408758657e5SAleksandr Urakov FPOProgramNode *right = eval_stack.pop_back_val(); 409758657e5SAleksandr Urakov FPOProgramNode *left = eval_stack.pop_back_val(); 410758657e5SAleksandr Urakov FPOProgramNode *node = alloc.makeNode<FPOProgramNodeBinaryOp>( 411758657e5SAleksandr Urakov ops_binary_it->second, left, right); 412758657e5SAleksandr Urakov eval_stack.push_back(node); 413758657e5SAleksandr Urakov continue; 414758657e5SAleksandr Urakov } 415758657e5SAleksandr Urakov 416758657e5SAleksandr Urakov auto ops_unary_it = ops_unary.find(cur); 417758657e5SAleksandr Urakov if (ops_unary_it != ops_unary.end()) { 418758657e5SAleksandr Urakov // token is unary operator 419758657e5SAleksandr Urakov if (eval_stack.empty()) { 420758657e5SAleksandr Urakov return false; 421758657e5SAleksandr Urakov } 422758657e5SAleksandr Urakov FPOProgramNode *operand = eval_stack.pop_back_val(); 423758657e5SAleksandr Urakov FPOProgramNode *node = 424758657e5SAleksandr Urakov alloc.makeNode<FPOProgramNodeUnaryOp>(ops_unary_it->second, operand); 425758657e5SAleksandr Urakov eval_stack.push_back(node); 426758657e5SAleksandr Urakov continue; 427758657e5SAleksandr Urakov } 428758657e5SAleksandr Urakov 429758657e5SAleksandr Urakov if (cur.startswith("$")) { 430758657e5SAleksandr Urakov // token is register ref 431758657e5SAleksandr Urakov eval_stack.push_back(alloc.makeNode<FPOProgramNodeRegisterRef>(cur)); 432758657e5SAleksandr Urakov continue; 433758657e5SAleksandr Urakov } 434758657e5SAleksandr Urakov 435758657e5SAleksandr Urakov if (cur == ra_search_keyword) { 436758657e5SAleksandr Urakov // TODO: .raSearch is unsupported 437758657e5SAleksandr Urakov return false; 438758657e5SAleksandr Urakov } 439758657e5SAleksandr Urakov 440758657e5SAleksandr Urakov uint32_t value; 441758657e5SAleksandr Urakov if (!cur.getAsInteger(10, value)) { 442758657e5SAleksandr Urakov // token is integer literal 443758657e5SAleksandr Urakov eval_stack.push_back(alloc.makeNode<FPOProgramNodeIntegerLiteral>(value)); 444758657e5SAleksandr Urakov continue; 445758657e5SAleksandr Urakov } 446758657e5SAleksandr Urakov 447758657e5SAleksandr Urakov // unexpected token 448758657e5SAleksandr Urakov return false; 449758657e5SAleksandr Urakov } 450758657e5SAleksandr Urakov 451758657e5SAleksandr Urakov if (eval_stack.size() != 1) { 452758657e5SAleksandr Urakov return false; 453758657e5SAleksandr Urakov } 454758657e5SAleksandr Urakov 455758657e5SAleksandr Urakov register_name = tokens[0]; 456758657e5SAleksandr Urakov ast = eval_stack.pop_back_val(); 457758657e5SAleksandr Urakov 458758657e5SAleksandr Urakov return true; 459758657e5SAleksandr Urakov } 460758657e5SAleksandr Urakov 461758657e5SAleksandr Urakov static FPOProgramNode *ParseFPOProgram(llvm::StringRef program, 462758657e5SAleksandr Urakov llvm::StringRef register_name, 463758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type, 464758657e5SAleksandr Urakov NodeAllocator &alloc) { 465758657e5SAleksandr Urakov llvm::DenseMap<llvm::StringRef, FPOProgramNode *> dependent_programs; 466758657e5SAleksandr Urakov 467758657e5SAleksandr Urakov size_t cur = 0; 468758657e5SAleksandr Urakov while (true) { 469758657e5SAleksandr Urakov size_t assign_index = program.find('=', cur); 470758657e5SAleksandr Urakov if (assign_index == llvm::StringRef::npos) { 471758657e5SAleksandr Urakov llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos); 472758657e5SAleksandr Urakov if (!tail.trim().empty()) { 473758657e5SAleksandr Urakov // missing assign operator 474758657e5SAleksandr Urakov return nullptr; 475758657e5SAleksandr Urakov } 476758657e5SAleksandr Urakov break; 477758657e5SAleksandr Urakov } 478758657e5SAleksandr Urakov llvm::StringRef assignment_program = program.slice(cur, assign_index); 479758657e5SAleksandr Urakov 480758657e5SAleksandr Urakov llvm::StringRef lvalue_name; 481758657e5SAleksandr Urakov FPOProgramNode *rvalue_ast = nullptr; 482758657e5SAleksandr Urakov if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name, 483758657e5SAleksandr Urakov rvalue_ast)) { 484758657e5SAleksandr Urakov return nullptr; 485758657e5SAleksandr Urakov } 486758657e5SAleksandr Urakov 487758657e5SAleksandr Urakov lldbassert(rvalue_ast); 488758657e5SAleksandr Urakov 489758657e5SAleksandr Urakov // check & resolve assignment program 490758657e5SAleksandr Urakov FPOProgramASTVisitorResolveRegisterRefs resolver(dependent_programs, 491758657e5SAleksandr Urakov arch_type); 492758657e5SAleksandr Urakov if (!resolver.Resolve(rvalue_ast)) { 493758657e5SAleksandr Urakov return nullptr; 494758657e5SAleksandr Urakov } 495758657e5SAleksandr Urakov 496758657e5SAleksandr Urakov if (lvalue_name == register_name) { 497758657e5SAleksandr Urakov // found target assignment program - no need to parse further 498758657e5SAleksandr Urakov 499758657e5SAleksandr Urakov // emplace valid dependent subtrees to make target assignment independent 500758657e5SAleksandr Urakov // from predecessors 501758657e5SAleksandr Urakov FPOProgramASTVisitorMergeDependent merger(dependent_programs); 502758657e5SAleksandr Urakov merger.Merge(rvalue_ast); 503758657e5SAleksandr Urakov 504758657e5SAleksandr Urakov return rvalue_ast; 505758657e5SAleksandr Urakov } 506758657e5SAleksandr Urakov 507758657e5SAleksandr Urakov dependent_programs[lvalue_name] = rvalue_ast; 508758657e5SAleksandr Urakov cur = assign_index + 1; 509758657e5SAleksandr Urakov } 510758657e5SAleksandr Urakov 511758657e5SAleksandr Urakov return nullptr; 512758657e5SAleksandr Urakov } 513758657e5SAleksandr Urakov 514758657e5SAleksandr Urakov bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( 515758657e5SAleksandr Urakov llvm::StringRef program, llvm::StringRef register_name, 516758657e5SAleksandr Urakov llvm::Triple::ArchType arch_type, Stream &stream) { 517758657e5SAleksandr Urakov NodeAllocator node_alloc; 518758657e5SAleksandr Urakov FPOProgramNode *target_program = 519758657e5SAleksandr Urakov ParseFPOProgram(program, register_name, arch_type, node_alloc); 520758657e5SAleksandr Urakov if (target_program == nullptr) { 521758657e5SAleksandr Urakov return false; 522758657e5SAleksandr Urakov } 523758657e5SAleksandr Urakov 524758657e5SAleksandr Urakov FPOProgramASTVisitorDWARFCodegen codegen(stream); 525758657e5SAleksandr Urakov codegen.Emit(target_program); 526758657e5SAleksandr Urakov return true; 527758657e5SAleksandr Urakov } 528