Index: source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp =================================================================== --- source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp +++ source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp @@ -25,12 +25,11 @@ namespace { -class FPOProgramNode; -class FPOProgramASTVisitor; - class NodeAllocator { public: template T *makeNode(Args &&... args) { + static_assert(std::is_trivially_destructible::value, + "This object will not be destroyed!"); void *new_node_mem = m_alloc.Allocate(sizeof(T), alignof(T)); return new (new_node_mem) T(std::forward(args)...); } @@ -53,9 +52,6 @@ FPOProgramNode(Kind kind) : m_token_kind(kind) {} public: - virtual ~FPOProgramNode() = default; - virtual void Accept(FPOProgramASTVisitor &visitor) = 0; - Kind GetKind() const { return m_token_kind; } private: @@ -67,8 +63,6 @@ FPOProgramNodeSymbol(llvm::StringRef name) : FPOProgramNode(Symbol), m_name(name) {} - void Accept(FPOProgramASTVisitor &visitor) override; - llvm::StringRef GetName() const { return m_name; } static bool classof(const FPOProgramNode *node) { @@ -84,8 +78,6 @@ FPOProgramNodeRegisterRef(uint32_t lldb_reg_num) : FPOProgramNode(Register), m_lldb_reg_num(lldb_reg_num) {} - void Accept(FPOProgramASTVisitor &visitor) override; - uint32_t GetLLDBRegNum() const { return m_lldb_reg_num; } static bool classof(const FPOProgramNode *node) { @@ -101,8 +93,6 @@ FPOProgramNodeIntegerLiteral(uint32_t value) : FPOProgramNode(IntegerLiteral), m_value(value) {} - void Accept(FPOProgramASTVisitor &visitor) override; - uint32_t GetValue() const { return m_value; } static bool classof(const FPOProgramNode *node) { @@ -126,8 +116,6 @@ : FPOProgramNode(BinaryOp), m_op_type(op_type), m_left(&left), m_right(&right) {} - void Accept(FPOProgramASTVisitor &visitor) override; - OpType GetOpType() const { return m_op_type; } const FPOProgramNode *Left() const { return m_left; } @@ -155,8 +143,6 @@ FPOProgramNodeUnaryOp(OpType op_type, FPOProgramNode &operand) : FPOProgramNode(UnaryOp), m_op_type(op_type), m_operand(&operand) {} - void Accept(FPOProgramASTVisitor &visitor) override; - OpType GetOpType() const { return m_op_type; } const FPOProgramNode *Operand() const { return m_operand; } @@ -171,84 +157,108 @@ FPOProgramNode *m_operand; }; +template class FPOProgramASTVisitor { -public: - virtual ~FPOProgramASTVisitor() = default; +protected: + virtual ResultT Visit(FPOProgramNodeBinaryOp &binary, + FPOProgramNode *&ref) = 0; + virtual ResultT Visit(FPOProgramNodeUnaryOp &unary, FPOProgramNode *&ref) = 0; + virtual ResultT Visit(FPOProgramNodeRegisterRef ®, FPOProgramNode *&) = 0; + virtual ResultT Visit(FPOProgramNodeIntegerLiteral &integer, + FPOProgramNode *&) = 0; + virtual ResultT Visit(FPOProgramNodeSymbol &symbol, FPOProgramNode *&ref) = 0; + + ResultT Dispatch(FPOProgramNode *&node) { + switch (node->GetKind()) { + case FPOProgramNode::Register: + return Visit(llvm::cast(*node), node); + case FPOProgramNode::Symbol: + return Visit(llvm::cast(*node), node); + + case FPOProgramNode::IntegerLiteral: + return Visit(llvm::cast(*node), node); + case FPOProgramNode::UnaryOp: + return Visit(llvm::cast(*node), node); + case FPOProgramNode::BinaryOp: + return Visit(llvm::cast(*node), node); + } + llvm_unreachable("Fully covered switch!"); + } - virtual void Visit(FPOProgramNodeSymbol &node) {} - virtual void Visit(FPOProgramNodeRegisterRef &node) {} - virtual void Visit(FPOProgramNodeIntegerLiteral &node) {} - virtual void Visit(FPOProgramNodeBinaryOp &node) {} - virtual void Visit(FPOProgramNodeUnaryOp &node) {} }; -void FPOProgramNodeSymbol::Accept(FPOProgramASTVisitor &visitor) { - visitor.Visit(*this); -} - -void FPOProgramNodeRegisterRef::Accept(FPOProgramASTVisitor &visitor) { - visitor.Visit(*this); -} +class FPOProgramASTVisitorMergeDependent : public FPOProgramASTVisitor<> { +public: + void Visit(FPOProgramNodeBinaryOp &binary, FPOProgramNode *&) override { + Dispatch(binary.Left()); + Dispatch(binary.Right()); + } -void FPOProgramNodeIntegerLiteral::Accept(FPOProgramASTVisitor &visitor) { - visitor.Visit(*this); -} + void Visit(FPOProgramNodeUnaryOp &unary, FPOProgramNode *&) override { + Dispatch(unary.Operand()); + } -void FPOProgramNodeBinaryOp::Accept(FPOProgramASTVisitor &visitor) { - visitor.Visit(*this); -} + void Visit(FPOProgramNodeRegisterRef &, FPOProgramNode *&) override {} + void Visit(FPOProgramNodeIntegerLiteral &, FPOProgramNode *&) override {} + void Visit(FPOProgramNodeSymbol &symbol, FPOProgramNode *&ref) override; -void FPOProgramNodeUnaryOp::Accept(FPOProgramASTVisitor &visitor) { - visitor.Visit(*this); -} + static void Merge(const llvm::DenseMap + &dependent_programs, + FPOProgramNode *&ast) { + FPOProgramASTVisitorMergeDependent(dependent_programs).Dispatch(ast); + } -class FPOProgramASTVisitorMergeDependent : public FPOProgramASTVisitor { -public: +private: FPOProgramASTVisitorMergeDependent( const llvm::DenseMap &dependent_programs) : m_dependent_programs(dependent_programs) {} - void Merge(FPOProgramNode *&node_ref); - -private: - void Visit(FPOProgramNodeBinaryOp &node) override; - void Visit(FPOProgramNodeUnaryOp &node) override; - - void TryReplace(FPOProgramNode *&node_ref) const; - -private: const llvm::DenseMap &m_dependent_programs; }; -void FPOProgramASTVisitorMergeDependent::Merge(FPOProgramNode *&node_ref) { - TryReplace(node_ref); - node_ref->Accept(*this); -} +void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeSymbol &symbol, + FPOProgramNode *&ref) { -void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeBinaryOp &node) { - Merge(node.Left()); - Merge(node.Right()); -} -void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeUnaryOp &node) { - Merge(node.Operand()); + auto it = m_dependent_programs.find(symbol.GetName()); + if (it == m_dependent_programs.end()) + return; + + ref = it->second; + Dispatch(ref); } -void FPOProgramASTVisitorMergeDependent::TryReplace( - FPOProgramNode *&node_ref) const { +class FPOProgramASTVisitorResolveRegisterRefs + : public FPOProgramASTVisitor { +public: + static bool Resolve(const llvm::DenseMap + &dependent_programs, + llvm::Triple::ArchType arch_type, NodeAllocator &alloc, + FPOProgramNode *&ast) { + return FPOProgramASTVisitorResolveRegisterRefs(dependent_programs, + arch_type, alloc) + .Dispatch(ast); + } - while (auto *symbol = llvm::dyn_cast(node_ref)) { - auto it = m_dependent_programs.find(symbol->GetName()); - if (it == m_dependent_programs.end()) { - break; - } + bool Visit(FPOProgramNodeBinaryOp &binary, FPOProgramNode *&) override { + return Dispatch(binary.Left()) && Dispatch(binary.Right()); + } - node_ref = it->second; + bool Visit(FPOProgramNodeUnaryOp &unary, FPOProgramNode *&) override { + return Dispatch(unary.Operand()); } -} -class FPOProgramASTVisitorResolveRegisterRefs : public FPOProgramASTVisitor { -public: + bool Visit(FPOProgramNodeRegisterRef &, FPOProgramNode *&) override { + return true; + } + + bool Visit(FPOProgramNodeIntegerLiteral &, FPOProgramNode *&) override { + return true; + } + + bool Visit(FPOProgramNodeSymbol &symbol, FPOProgramNode *&ref) override; + +private: FPOProgramASTVisitorResolveRegisterRefs( const llvm::DenseMap &dependent_programs, @@ -256,27 +266,11 @@ : m_dependent_programs(dependent_programs), m_arch_type(arch_type), m_alloc(alloc) {} - bool Resolve(FPOProgramNode *&program); - -private: - void Visit(FPOProgramNodeBinaryOp &node) override; - void Visit(FPOProgramNodeUnaryOp &node) override; - - bool TryReplace(FPOProgramNode *&node_ref); - const llvm::DenseMap &m_dependent_programs; llvm::Triple::ArchType m_arch_type; NodeAllocator &m_alloc; - bool m_no_error_flag = true; }; -bool FPOProgramASTVisitorResolveRegisterRefs::Resolve(FPOProgramNode *&program) { - if (!TryReplace(program)) - return false; - program->Accept(*this); - return m_no_error_flag; -} - static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::ArchType arch_type) { // lookup register name to get lldb register number llvm::ArrayRef> register_names = @@ -294,62 +288,49 @@ return npdb::GetLLDBRegisterNumber(arch_type, reg_id); } -bool FPOProgramASTVisitorResolveRegisterRefs::TryReplace( - FPOProgramNode *&node_ref) { - auto *symbol = llvm::dyn_cast(node_ref); - if (!symbol) - return true; - +bool FPOProgramASTVisitorResolveRegisterRefs::Visit( + FPOProgramNodeSymbol &symbol, FPOProgramNode *&ref) { // Look up register reference as lvalue in preceding assignments. - auto it = m_dependent_programs.find(symbol->GetName()); + auto it = m_dependent_programs.find(symbol.GetName()); if (it != m_dependent_programs.end()) { // Dependent programs are handled elsewhere. return true; } uint32_t reg_num = - ResolveLLDBRegisterNum(symbol->GetName().drop_front(1), m_arch_type); + ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), m_arch_type); if (reg_num == LLDB_INVALID_REGNUM) return false; - node_ref = m_alloc.makeNode(reg_num); + ref = m_alloc.makeNode(reg_num); return true; } -void FPOProgramASTVisitorResolveRegisterRefs::Visit( - FPOProgramNodeBinaryOp &node) { - m_no_error_flag = Resolve(node.Left()) && Resolve(node.Right()); -} - -void FPOProgramASTVisitorResolveRegisterRefs::Visit( - FPOProgramNodeUnaryOp &node) { - m_no_error_flag = Resolve(node.Operand()); -} - -class FPOProgramASTVisitorDWARFCodegen : public FPOProgramASTVisitor { +class FPOProgramASTVisitorDWARFCodegen : public FPOProgramASTVisitor<> { public: - FPOProgramASTVisitorDWARFCodegen(Stream &stream) : m_out_stream(stream) {} + static void Emit(Stream &stream, FPOProgramNode *&ast) { + FPOProgramASTVisitorDWARFCodegen(stream).Dispatch(ast); + } - void Emit(FPOProgramNode &program); + void Visit(FPOProgramNodeRegisterRef ®, FPOProgramNode *&); + void Visit(FPOProgramNodeBinaryOp &binary, FPOProgramNode *&); + void Visit(FPOProgramNodeUnaryOp &unary, FPOProgramNode *&); + void Visit(FPOProgramNodeSymbol &symbol, FPOProgramNode *&) { + llvm_unreachable("Symbols should have been resolved by now!"); + } + void Visit(FPOProgramNodeIntegerLiteral &integer, FPOProgramNode *&); private: - void Visit(FPOProgramNodeRegisterRef &node) override; - void Visit(FPOProgramNodeIntegerLiteral &node) override; - void Visit(FPOProgramNodeBinaryOp &node) override; - void Visit(FPOProgramNodeUnaryOp &node) override; + FPOProgramASTVisitorDWARFCodegen(Stream &stream) : m_out_stream(stream) {} -private: Stream &m_out_stream; }; -void FPOProgramASTVisitorDWARFCodegen::Emit(FPOProgramNode &program) { - program.Accept(*this); -} - -void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeRegisterRef &node) { +void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeRegisterRef ®, + FPOProgramNode *&) { - uint32_t reg_num = node.GetLLDBRegNum(); + uint32_t reg_num = reg.GetLLDBRegNum(); lldbassert(reg_num != LLDB_INVALID_REGNUM); if (reg_num > 31) { @@ -362,18 +343,18 @@ } void FPOProgramASTVisitorDWARFCodegen::Visit( - FPOProgramNodeIntegerLiteral &node) { - uint32_t value = node.GetValue(); + FPOProgramNodeIntegerLiteral &integer, FPOProgramNode *&) { + uint32_t value = integer.GetValue(); m_out_stream.PutHex8(DW_OP_constu); m_out_stream.PutULEB128(value); } -void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeBinaryOp &node) { +void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeBinaryOp &binary, + FPOProgramNode *&) { + Dispatch(binary.Left()); + Dispatch(binary.Right()); - Emit(*node.Left()); - Emit(*node.Right()); - - switch (node.GetOpType()) { + switch (binary.GetOpType()) { case FPOProgramNodeBinaryOp::Plus: m_out_stream.PutHex8(DW_OP_plus); // NOTE: can be optimized by using DW_OP_plus_uconst opcpode @@ -395,10 +376,11 @@ } } -void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeUnaryOp &node) { - Emit(*node.Operand()); +void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeUnaryOp &unary, + FPOProgramNode *&) { + Dispatch(unary.Operand()); - switch (node.GetOpType()) { + switch (unary.GetOpType()) { case FPOProgramNodeUnaryOp::Deref: m_out_stream.PutHex8(DW_OP_deref); break; @@ -523,19 +505,16 @@ lldbassert(rvalue_ast); // check & resolve assignment program - FPOProgramASTVisitorResolveRegisterRefs resolver(dependent_programs, - arch_type, alloc); - if (!resolver.Resolve(rvalue_ast)) { + if (!FPOProgramASTVisitorResolveRegisterRefs::Resolve( + dependent_programs, arch_type, alloc, rvalue_ast)) return nullptr; - } if (lvalue_name == register_name) { // found target assignment program - no need to parse further // emplace valid dependent subtrees to make target assignment independent // from predecessors - FPOProgramASTVisitorMergeDependent merger(dependent_programs); - merger.Merge(rvalue_ast); + FPOProgramASTVisitorMergeDependent::Merge(dependent_programs, rvalue_ast); return rvalue_ast; } @@ -557,7 +536,6 @@ return false; } - FPOProgramASTVisitorDWARFCodegen codegen(stream); - codegen.Emit(*target_program); + FPOProgramASTVisitorDWARFCodegen::Emit(stream, target_program); return true; }