forked from OSchip/llvm-project
Move postfix expression code out of the NativePDB plugin
Summary: The NativePDB plugin contains code to convert "programs" describing the layout of function frames into dwarf (for easier interaction with the rest of lldb). This functionality is useful for the Breakpad plugin too, as it contains the same kind of expressions (because breakpad info is generated from pdb files). In this patch, I move the core classes of this code into a common place, where it can be used from both files. Previously, these were the details of the implementation, but here I am exposing them (instead of just a single "string->string" conversion function), as breakpad will need to use these in a slightly different way. The reason for that is that breakpad files generated from dwarf expressions use a slightly different syntax, although most of the core code can be reused with a bit of thought. This is also the reason why I am not moving the parsing or dwarf generation bits, as they will need to be generalized a bit before they're usable for both scenarios. This patch should be NFC, modulo renaming the moved entities to more neutral names. The reason I am moving this to the "Symbol" library, is because both customers will be "Symbol"Files, and also the unwinding code lives in the Symbol library. From a purely dependency standpoint this code will probably be standalone, and so it could be moved all the way to Utility, but that seems too low for this kind of functionality. Reviewers: jasonmolenda, amccarth, clayborg, JDevlieghere, aleksandr.urakov Subscribers: aprantl, markmentovai, lldb-commits Differential Revision: https://reviews.llvm.org/D60599 llvm-svn: 358976
This commit is contained in:
parent
003c18a39c
commit
4eda12aea5
|
@ -0,0 +1,179 @@
|
|||
//===-- PostfixExpression.h -------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements support for postfix expressions found in several symbol
|
||||
// file formats, and their conversion to DWARF.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLDB_SYMBOL_POSTFIXEXPRESSION_H
|
||||
#define LLDB_SYMBOL_POSTFIXEXPRESSION_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
||||
namespace lldb_private {
|
||||
namespace postfix {
|
||||
|
||||
/// The base class for all nodes in the parsed postfix tree.
|
||||
class Node {
|
||||
public:
|
||||
enum Kind {
|
||||
BinaryOp,
|
||||
Integer,
|
||||
Register,
|
||||
Symbol,
|
||||
UnaryOp,
|
||||
};
|
||||
|
||||
protected:
|
||||
Node(Kind kind) : m_kind(kind) {}
|
||||
|
||||
public:
|
||||
Kind GetKind() const { return m_kind; }
|
||||
|
||||
private:
|
||||
Kind m_kind;
|
||||
};
|
||||
|
||||
/// A node representing a binary expression.
|
||||
class BinaryOpNode : public Node {
|
||||
public:
|
||||
enum OpType {
|
||||
Align, // alignDown(a, b)
|
||||
Minus, // a - b
|
||||
Plus, // a + b
|
||||
};
|
||||
|
||||
BinaryOpNode(OpType op_type, Node &left, Node &right)
|
||||
: Node(BinaryOp), m_op_type(op_type), m_left(&left), m_right(&right) {}
|
||||
|
||||
OpType GetOpType() const { return m_op_type; }
|
||||
|
||||
const Node *Left() const { return m_left; }
|
||||
Node *&Left() { return m_left; }
|
||||
|
||||
const Node *Right() const { return m_right; }
|
||||
Node *&Right() { return m_right; }
|
||||
|
||||
static bool classof(const Node *node) { return node->GetKind() == BinaryOp; }
|
||||
|
||||
private:
|
||||
OpType m_op_type;
|
||||
Node *m_left;
|
||||
Node *m_right;
|
||||
};
|
||||
|
||||
/// A node representing an integer literal.
|
||||
class IntegerNode : public Node {
|
||||
public:
|
||||
IntegerNode(uint32_t value) : Node(Integer), m_value(value) {}
|
||||
|
||||
uint32_t GetValue() const { return m_value; }
|
||||
|
||||
static bool classof(const Node *node) { return node->GetKind() == Integer; }
|
||||
|
||||
private:
|
||||
uint32_t m_value;
|
||||
};
|
||||
|
||||
/// A node representing the value of a register with the given register number.
|
||||
/// The register kind (RegisterKind enum) used for the specifying the register
|
||||
/// number is implicit and assumed to be the same for all Register nodes in a
|
||||
/// given tree.
|
||||
class RegisterNode : public Node {
|
||||
public:
|
||||
RegisterNode(uint32_t reg_num) : Node(Register), m_reg_num(reg_num) {}
|
||||
|
||||
uint32_t GetRegNum() const { return m_reg_num; }
|
||||
|
||||
static bool classof(const Node *node) { return node->GetKind() == Register; }
|
||||
|
||||
private:
|
||||
uint32_t m_reg_num;
|
||||
};
|
||||
|
||||
/// A node representing a symbolic reference to a named entity. This may be a
|
||||
/// register, which hasn't yet been resolved to a RegisterNode.
|
||||
class SymbolNode : public Node {
|
||||
public:
|
||||
SymbolNode(llvm::StringRef name) : Node(Symbol), m_name(name) {}
|
||||
|
||||
llvm::StringRef GetName() const { return m_name; }
|
||||
|
||||
static bool classof(const Node *node) { return node->GetKind() == Symbol; }
|
||||
|
||||
private:
|
||||
llvm::StringRef m_name;
|
||||
};
|
||||
|
||||
/// A node representing a unary operation.
|
||||
class UnaryOpNode : public Node {
|
||||
public:
|
||||
enum OpType {
|
||||
Deref, // *a
|
||||
};
|
||||
|
||||
UnaryOpNode(OpType op_type, Node &operand)
|
||||
: Node(UnaryOp), m_op_type(op_type), m_operand(&operand) {}
|
||||
|
||||
OpType GetOpType() const { return m_op_type; }
|
||||
|
||||
const Node *Operand() const { return m_operand; }
|
||||
Node *&Operand() { return m_operand; }
|
||||
|
||||
static bool classof(const Node *node) { return node->GetKind() == UnaryOp; }
|
||||
|
||||
private:
|
||||
OpType m_op_type;
|
||||
Node *m_operand;
|
||||
};
|
||||
|
||||
/// A template class implementing a visitor pattern, but with a couple of
|
||||
/// twists:
|
||||
/// - It uses type switch instead of virtual double dispatch. This allows the
|
||||
// node classes to be vtable-free and trivially destructible.
|
||||
/// - The Visit functions get an extra Node *& parameter, which refers to the
|
||||
/// child pointer of the parent of the node we are currently visiting. This
|
||||
/// allows mutating algorithms, which replace the currently visited node with
|
||||
/// a different one.
|
||||
/// - The class is templatized on the return type of the Visit functions, which
|
||||
/// means it's possible to return values from them.
|
||||
template <typename ResultT = void> class Visitor {
|
||||
protected:
|
||||
virtual ~Visitor() = default;
|
||||
|
||||
virtual ResultT Visit(BinaryOpNode &binary, Node *&ref) = 0;
|
||||
virtual ResultT Visit(IntegerNode &integer, Node *&) = 0;
|
||||
virtual ResultT Visit(RegisterNode ®, Node *&) = 0;
|
||||
virtual ResultT Visit(SymbolNode &symbol, Node *&ref) = 0;
|
||||
virtual ResultT Visit(UnaryOpNode &unary, Node *&ref) = 0;
|
||||
|
||||
/// Invoke the correct Visit function based on the dynamic type of the given
|
||||
/// node.
|
||||
ResultT Dispatch(Node *&node) {
|
||||
switch (node->GetKind()) {
|
||||
case Node::BinaryOp:
|
||||
return Visit(llvm::cast<BinaryOpNode>(*node), node);
|
||||
case Node::Integer:
|
||||
return Visit(llvm::cast<IntegerNode>(*node), node);
|
||||
case Node::Register:
|
||||
return Visit(llvm::cast<RegisterNode>(*node), node);
|
||||
case Node::Symbol:
|
||||
return Visit(llvm::cast<SymbolNode>(*node), node);
|
||||
case Node::UnaryOp:
|
||||
return Visit(llvm::cast<UnaryOpNode>(*node), node);
|
||||
}
|
||||
llvm_unreachable("Fully covered switch!");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace postfix
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // LLDB_SYMBOL_POSTFIXEXPRESSION_H
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "lldb/Core/StreamBuffer.h"
|
||||
#include "lldb/Core/dwarf.h"
|
||||
#include "lldb/Symbol/PostfixExpression.h"
|
||||
#include "lldb/Utility/LLDBAssert.h"
|
||||
#include "lldb/Utility/Stream.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
@ -18,10 +19,10 @@
|
|||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/EnumTables.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::postfix;
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -38,190 +39,36 @@ private:
|
|||
llvm::BumpPtrAllocator m_alloc;
|
||||
};
|
||||
|
||||
class FPOProgramNode {
|
||||
class FPOProgramASTVisitorMergeDependent : public Visitor<> {
|
||||
public:
|
||||
enum Kind {
|
||||
Symbol,
|
||||
Register,
|
||||
IntegerLiteral,
|
||||
BinaryOp,
|
||||
UnaryOp,
|
||||
};
|
||||
|
||||
protected:
|
||||
FPOProgramNode(Kind kind) : m_token_kind(kind) {}
|
||||
|
||||
public:
|
||||
Kind GetKind() const { return m_token_kind; }
|
||||
|
||||
private:
|
||||
Kind m_token_kind;
|
||||
};
|
||||
|
||||
class FPOProgramNodeSymbol: public FPOProgramNode {
|
||||
public:
|
||||
FPOProgramNodeSymbol(llvm::StringRef name)
|
||||
: FPOProgramNode(Symbol), m_name(name) {}
|
||||
|
||||
llvm::StringRef GetName() const { return m_name; }
|
||||
|
||||
static bool classof(const FPOProgramNode *node) {
|
||||
return node->GetKind() == Symbol;
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::StringRef m_name;
|
||||
};
|
||||
|
||||
class FPOProgramNodeRegisterRef : public FPOProgramNode {
|
||||
public:
|
||||
FPOProgramNodeRegisterRef(uint32_t lldb_reg_num)
|
||||
: FPOProgramNode(Register), m_lldb_reg_num(lldb_reg_num) {}
|
||||
|
||||
uint32_t GetLLDBRegNum() const { return m_lldb_reg_num; }
|
||||
|
||||
static bool classof(const FPOProgramNode *node) {
|
||||
return node->GetKind() == Register;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_lldb_reg_num;
|
||||
};
|
||||
|
||||
class FPOProgramNodeIntegerLiteral : public FPOProgramNode {
|
||||
public:
|
||||
FPOProgramNodeIntegerLiteral(uint32_t value)
|
||||
: FPOProgramNode(IntegerLiteral), m_value(value) {}
|
||||
|
||||
uint32_t GetValue() const { return m_value; }
|
||||
|
||||
static bool classof(const FPOProgramNode *node) {
|
||||
return node->GetKind() == IntegerLiteral;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_value;
|
||||
};
|
||||
|
||||
class FPOProgramNodeBinaryOp : public FPOProgramNode {
|
||||
public:
|
||||
enum OpType {
|
||||
Plus,
|
||||
Minus,
|
||||
Align,
|
||||
};
|
||||
|
||||
FPOProgramNodeBinaryOp(OpType op_type, FPOProgramNode &left,
|
||||
FPOProgramNode &right)
|
||||
: FPOProgramNode(BinaryOp), m_op_type(op_type), m_left(&left),
|
||||
m_right(&right) {}
|
||||
|
||||
OpType GetOpType() const { return m_op_type; }
|
||||
|
||||
const FPOProgramNode *Left() const { return m_left; }
|
||||
FPOProgramNode *&Left() { return m_left; }
|
||||
|
||||
const FPOProgramNode *Right() const { return m_right; }
|
||||
FPOProgramNode *&Right() { return m_right; }
|
||||
|
||||
static bool classof(const FPOProgramNode *node) {
|
||||
return node->GetKind() == BinaryOp;
|
||||
}
|
||||
|
||||
private:
|
||||
OpType m_op_type;
|
||||
FPOProgramNode *m_left;
|
||||
FPOProgramNode *m_right;
|
||||
};
|
||||
|
||||
class FPOProgramNodeUnaryOp : public FPOProgramNode {
|
||||
public:
|
||||
enum OpType {
|
||||
Deref,
|
||||
};
|
||||
|
||||
FPOProgramNodeUnaryOp(OpType op_type, FPOProgramNode &operand)
|
||||
: FPOProgramNode(UnaryOp), m_op_type(op_type), m_operand(&operand) {}
|
||||
|
||||
OpType GetOpType() const { return m_op_type; }
|
||||
|
||||
const FPOProgramNode *Operand() const { return m_operand; }
|
||||
FPOProgramNode *&Operand() { return m_operand; }
|
||||
|
||||
static bool classof(const FPOProgramNode *node) {
|
||||
return node->GetKind() == UnaryOp;
|
||||
}
|
||||
|
||||
private:
|
||||
OpType m_op_type;
|
||||
FPOProgramNode *m_operand;
|
||||
};
|
||||
|
||||
template <typename ResultT = void>
|
||||
class FPOProgramASTVisitor {
|
||||
protected:
|
||||
virtual ~FPOProgramASTVisitor() = default;
|
||||
|
||||
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<FPOProgramNodeRegisterRef>(*node), node);
|
||||
case FPOProgramNode::Symbol:
|
||||
return Visit(llvm::cast<FPOProgramNodeSymbol>(*node), node);
|
||||
|
||||
case FPOProgramNode::IntegerLiteral:
|
||||
return Visit(llvm::cast<FPOProgramNodeIntegerLiteral>(*node), node);
|
||||
case FPOProgramNode::UnaryOp:
|
||||
return Visit(llvm::cast<FPOProgramNodeUnaryOp>(*node), node);
|
||||
case FPOProgramNode::BinaryOp:
|
||||
return Visit(llvm::cast<FPOProgramNodeBinaryOp>(*node), node);
|
||||
}
|
||||
llvm_unreachable("Fully covered switch!");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FPOProgramASTVisitorMergeDependent : public FPOProgramASTVisitor<> {
|
||||
public:
|
||||
void Visit(FPOProgramNodeBinaryOp &binary, FPOProgramNode *&) override {
|
||||
void Visit(BinaryOpNode &binary, Node *&) override {
|
||||
Dispatch(binary.Left());
|
||||
Dispatch(binary.Right());
|
||||
}
|
||||
|
||||
void Visit(FPOProgramNodeUnaryOp &unary, FPOProgramNode *&) override {
|
||||
void Visit(UnaryOpNode &unary, Node *&) override {
|
||||
Dispatch(unary.Operand());
|
||||
}
|
||||
|
||||
void Visit(FPOProgramNodeRegisterRef &, FPOProgramNode *&) override {}
|
||||
void Visit(FPOProgramNodeIntegerLiteral &, FPOProgramNode *&) override {}
|
||||
void Visit(FPOProgramNodeSymbol &symbol, FPOProgramNode *&ref) override;
|
||||
void Visit(RegisterNode &, Node *&) override {}
|
||||
void Visit(IntegerNode &, Node *&) override {}
|
||||
void Visit(SymbolNode &symbol, Node *&ref) override;
|
||||
|
||||
static void Merge(const llvm::DenseMap<llvm::StringRef, FPOProgramNode *>
|
||||
&dependent_programs,
|
||||
FPOProgramNode *&ast) {
|
||||
static void
|
||||
Merge(const llvm::DenseMap<llvm::StringRef, Node *> &dependent_programs,
|
||||
Node *&ast) {
|
||||
FPOProgramASTVisitorMergeDependent(dependent_programs).Dispatch(ast);
|
||||
}
|
||||
|
||||
private:
|
||||
FPOProgramASTVisitorMergeDependent(
|
||||
const llvm::DenseMap<llvm::StringRef, FPOProgramNode *>
|
||||
&dependent_programs)
|
||||
const llvm::DenseMap<llvm::StringRef, Node *> &dependent_programs)
|
||||
: m_dependent_programs(dependent_programs) {}
|
||||
|
||||
const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs;
|
||||
const llvm::DenseMap<llvm::StringRef, Node *> &m_dependent_programs;
|
||||
};
|
||||
|
||||
void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeSymbol &symbol,
|
||||
FPOProgramNode *&ref) {
|
||||
|
||||
void FPOProgramASTVisitorMergeDependent::Visit(SymbolNode &symbol, Node *&ref) {
|
||||
auto it = m_dependent_programs.find(symbol.GetName());
|
||||
if (it == m_dependent_programs.end())
|
||||
return;
|
||||
|
@ -230,45 +77,38 @@ void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeSymbol &symbol,
|
|||
Dispatch(ref);
|
||||
}
|
||||
|
||||
class FPOProgramASTVisitorResolveRegisterRefs
|
||||
: public FPOProgramASTVisitor<bool> {
|
||||
class FPOProgramASTVisitorResolveRegisterRefs : public Visitor<bool> {
|
||||
public:
|
||||
static bool Resolve(const llvm::DenseMap<llvm::StringRef, FPOProgramNode *>
|
||||
&dependent_programs,
|
||||
llvm::Triple::ArchType arch_type, NodeAllocator &alloc,
|
||||
FPOProgramNode *&ast) {
|
||||
static bool
|
||||
Resolve(const llvm::DenseMap<llvm::StringRef, Node *> &dependent_programs,
|
||||
llvm::Triple::ArchType arch_type, NodeAllocator &alloc, Node *&ast) {
|
||||
return FPOProgramASTVisitorResolveRegisterRefs(dependent_programs,
|
||||
arch_type, alloc)
|
||||
.Dispatch(ast);
|
||||
}
|
||||
|
||||
bool Visit(FPOProgramNodeBinaryOp &binary, FPOProgramNode *&) override {
|
||||
bool Visit(BinaryOpNode &binary, Node *&) override {
|
||||
return Dispatch(binary.Left()) && Dispatch(binary.Right());
|
||||
}
|
||||
|
||||
bool Visit(FPOProgramNodeUnaryOp &unary, FPOProgramNode *&) override {
|
||||
bool Visit(UnaryOpNode &unary, Node *&) override {
|
||||
return Dispatch(unary.Operand());
|
||||
}
|
||||
|
||||
bool Visit(FPOProgramNodeRegisterRef &, FPOProgramNode *&) override {
|
||||
return true;
|
||||
}
|
||||
bool Visit(RegisterNode &, Node *&) override { return true; }
|
||||
|
||||
bool Visit(FPOProgramNodeIntegerLiteral &, FPOProgramNode *&) override {
|
||||
return true;
|
||||
}
|
||||
bool Visit(IntegerNode &, Node *&) override { return true; }
|
||||
|
||||
bool Visit(FPOProgramNodeSymbol &symbol, FPOProgramNode *&ref) override;
|
||||
bool Visit(SymbolNode &symbol, Node *&ref) override;
|
||||
|
||||
private:
|
||||
FPOProgramASTVisitorResolveRegisterRefs(
|
||||
const llvm::DenseMap<llvm::StringRef, FPOProgramNode *>
|
||||
&dependent_programs,
|
||||
const llvm::DenseMap<llvm::StringRef, Node *> &dependent_programs,
|
||||
llvm::Triple::ArchType arch_type, NodeAllocator &alloc)
|
||||
: m_dependent_programs(dependent_programs), m_arch_type(arch_type),
|
||||
m_alloc(alloc) {}
|
||||
|
||||
const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs;
|
||||
const llvm::DenseMap<llvm::StringRef, Node *> &m_dependent_programs;
|
||||
llvm::Triple::ArchType m_arch_type;
|
||||
NodeAllocator &m_alloc;
|
||||
};
|
||||
|
@ -290,8 +130,8 @@ static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::A
|
|||
return npdb::GetLLDBRegisterNumber(arch_type, reg_id);
|
||||
}
|
||||
|
||||
bool FPOProgramASTVisitorResolveRegisterRefs::Visit(
|
||||
FPOProgramNodeSymbol &symbol, FPOProgramNode *&ref) {
|
||||
bool FPOProgramASTVisitorResolveRegisterRefs::Visit(SymbolNode &symbol,
|
||||
Node *&ref) {
|
||||
// Look up register reference as lvalue in preceding assignments.
|
||||
auto it = m_dependent_programs.find(symbol.GetName());
|
||||
if (it != m_dependent_programs.end()) {
|
||||
|
@ -305,23 +145,23 @@ bool FPOProgramASTVisitorResolveRegisterRefs::Visit(
|
|||
if (reg_num == LLDB_INVALID_REGNUM)
|
||||
return false;
|
||||
|
||||
ref = m_alloc.makeNode<FPOProgramNodeRegisterRef>(reg_num);
|
||||
ref = m_alloc.makeNode<RegisterNode>(reg_num);
|
||||
return true;
|
||||
}
|
||||
|
||||
class FPOProgramASTVisitorDWARFCodegen : public FPOProgramASTVisitor<> {
|
||||
class FPOProgramASTVisitorDWARFCodegen : public Visitor<> {
|
||||
public:
|
||||
static void Emit(Stream &stream, FPOProgramNode *&ast) {
|
||||
static void Emit(Stream &stream, Node *&ast) {
|
||||
FPOProgramASTVisitorDWARFCodegen(stream).Dispatch(ast);
|
||||
}
|
||||
|
||||
void Visit(FPOProgramNodeRegisterRef ®, FPOProgramNode *&);
|
||||
void Visit(FPOProgramNodeBinaryOp &binary, FPOProgramNode *&);
|
||||
void Visit(FPOProgramNodeUnaryOp &unary, FPOProgramNode *&);
|
||||
void Visit(FPOProgramNodeSymbol &symbol, FPOProgramNode *&) {
|
||||
void Visit(RegisterNode ®, Node *&);
|
||||
void Visit(BinaryOpNode &binary, Node *&);
|
||||
void Visit(UnaryOpNode &unary, Node *&);
|
||||
void Visit(SymbolNode &symbol, Node *&) {
|
||||
llvm_unreachable("Symbols should have been resolved by now!");
|
||||
}
|
||||
void Visit(FPOProgramNodeIntegerLiteral &integer, FPOProgramNode *&);
|
||||
void Visit(IntegerNode &integer, Node *&);
|
||||
|
||||
private:
|
||||
FPOProgramASTVisitorDWARFCodegen(Stream &stream) : m_out_stream(stream) {}
|
||||
|
@ -329,10 +169,8 @@ private:
|
|||
Stream &m_out_stream;
|
||||
};
|
||||
|
||||
void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeRegisterRef ®,
|
||||
FPOProgramNode *&) {
|
||||
|
||||
uint32_t reg_num = reg.GetLLDBRegNum();
|
||||
void FPOProgramASTVisitorDWARFCodegen::Visit(RegisterNode ®, Node *&) {
|
||||
uint32_t reg_num = reg.GetRegNum();
|
||||
lldbassert(reg_num != LLDB_INVALID_REGNUM);
|
||||
|
||||
if (reg_num > 31) {
|
||||
|
@ -344,28 +182,26 @@ void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeRegisterRef ®,
|
|||
m_out_stream.PutSLEB128(0);
|
||||
}
|
||||
|
||||
void FPOProgramASTVisitorDWARFCodegen::Visit(
|
||||
FPOProgramNodeIntegerLiteral &integer, FPOProgramNode *&) {
|
||||
void FPOProgramASTVisitorDWARFCodegen::Visit(IntegerNode &integer, Node *&) {
|
||||
uint32_t value = integer.GetValue();
|
||||
m_out_stream.PutHex8(DW_OP_constu);
|
||||
m_out_stream.PutULEB128(value);
|
||||
}
|
||||
|
||||
void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeBinaryOp &binary,
|
||||
FPOProgramNode *&) {
|
||||
void FPOProgramASTVisitorDWARFCodegen::Visit(BinaryOpNode &binary, Node *&) {
|
||||
Dispatch(binary.Left());
|
||||
Dispatch(binary.Right());
|
||||
|
||||
switch (binary.GetOpType()) {
|
||||
case FPOProgramNodeBinaryOp::Plus:
|
||||
case BinaryOpNode::Plus:
|
||||
m_out_stream.PutHex8(DW_OP_plus);
|
||||
// NOTE: can be optimized by using DW_OP_plus_uconst opcpode
|
||||
// if right child node is constant value
|
||||
break;
|
||||
case FPOProgramNodeBinaryOp::Minus:
|
||||
case BinaryOpNode::Minus:
|
||||
m_out_stream.PutHex8(DW_OP_minus);
|
||||
break;
|
||||
case FPOProgramNodeBinaryOp::Align:
|
||||
case BinaryOpNode::Align:
|
||||
// emit align operator a @ b as
|
||||
// a & ~(b - 1)
|
||||
// NOTE: implicitly assuming that b is power of 2
|
||||
|
@ -378,12 +214,11 @@ void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeBinaryOp &binary,
|
|||
}
|
||||
}
|
||||
|
||||
void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeUnaryOp &unary,
|
||||
FPOProgramNode *&) {
|
||||
void FPOProgramASTVisitorDWARFCodegen::Visit(UnaryOpNode &unary, Node *&) {
|
||||
Dispatch(unary.Operand());
|
||||
|
||||
switch (unary.GetOpType()) {
|
||||
case FPOProgramNodeUnaryOp::Deref:
|
||||
case UnaryOpNode::Deref:
|
||||
m_out_stream.PutHex8(DW_OP_deref);
|
||||
break;
|
||||
}
|
||||
|
@ -394,23 +229,23 @@ void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeUnaryOp &unary,
|
|||
static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
|
||||
NodeAllocator &alloc,
|
||||
llvm::StringRef ®ister_name,
|
||||
FPOProgramNode *&ast) {
|
||||
Node *&ast) {
|
||||
llvm::SmallVector<llvm::StringRef, 16> tokens;
|
||||
llvm::SplitString(program, tokens, " ");
|
||||
|
||||
if (tokens.empty())
|
||||
return false;
|
||||
|
||||
llvm::SmallVector<FPOProgramNode *, 4> eval_stack;
|
||||
llvm::SmallVector<Node *, 4> eval_stack;
|
||||
|
||||
llvm::DenseMap<llvm::StringRef, FPOProgramNodeBinaryOp::OpType> ops_binary = {
|
||||
{"+", FPOProgramNodeBinaryOp::Plus},
|
||||
{"-", FPOProgramNodeBinaryOp::Minus},
|
||||
{"@", FPOProgramNodeBinaryOp::Align},
|
||||
llvm::DenseMap<llvm::StringRef, BinaryOpNode::OpType> ops_binary = {
|
||||
{"+", BinaryOpNode::Plus},
|
||||
{"-", BinaryOpNode::Minus},
|
||||
{"@", BinaryOpNode::Align},
|
||||
};
|
||||
|
||||
llvm::DenseMap<llvm::StringRef, FPOProgramNodeUnaryOp::OpType> ops_unary = {
|
||||
{"^", FPOProgramNodeUnaryOp::Deref},
|
||||
llvm::DenseMap<llvm::StringRef, UnaryOpNode::OpType> ops_unary = {
|
||||
{"^", UnaryOpNode::Deref},
|
||||
};
|
||||
|
||||
constexpr llvm::StringLiteral ra_search_keyword = ".raSearch";
|
||||
|
@ -426,10 +261,10 @@ static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
|
|||
if (eval_stack.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
FPOProgramNode *right = eval_stack.pop_back_val();
|
||||
FPOProgramNode *left = eval_stack.pop_back_val();
|
||||
FPOProgramNode *node = alloc.makeNode<FPOProgramNodeBinaryOp>(
|
||||
ops_binary_it->second, *left, *right);
|
||||
Node *right = eval_stack.pop_back_val();
|
||||
Node *left = eval_stack.pop_back_val();
|
||||
Node *node =
|
||||
alloc.makeNode<BinaryOpNode>(ops_binary_it->second, *left, *right);
|
||||
eval_stack.push_back(node);
|
||||
continue;
|
||||
}
|
||||
|
@ -440,15 +275,14 @@ static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
|
|||
if (eval_stack.empty()) {
|
||||
return false;
|
||||
}
|
||||
FPOProgramNode *operand = eval_stack.pop_back_val();
|
||||
FPOProgramNode *node =
|
||||
alloc.makeNode<FPOProgramNodeUnaryOp>(ops_unary_it->second, *operand);
|
||||
Node *operand = eval_stack.pop_back_val();
|
||||
Node *node = alloc.makeNode<UnaryOpNode>(ops_unary_it->second, *operand);
|
||||
eval_stack.push_back(node);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cur.startswith("$")) {
|
||||
eval_stack.push_back(alloc.makeNode<FPOProgramNodeSymbol>(cur));
|
||||
eval_stack.push_back(alloc.makeNode<SymbolNode>(cur));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -460,7 +294,7 @@ static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
|
|||
uint32_t value;
|
||||
if (!cur.getAsInteger(10, value)) {
|
||||
// token is integer literal
|
||||
eval_stack.push_back(alloc.makeNode<FPOProgramNodeIntegerLiteral>(value));
|
||||
eval_stack.push_back(alloc.makeNode<IntegerNode>(value));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -478,11 +312,11 @@ static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
|
|||
return true;
|
||||
}
|
||||
|
||||
static FPOProgramNode *ParseFPOProgram(llvm::StringRef program,
|
||||
llvm::StringRef register_name,
|
||||
llvm::Triple::ArchType arch_type,
|
||||
NodeAllocator &alloc) {
|
||||
llvm::DenseMap<llvm::StringRef, FPOProgramNode *> dependent_programs;
|
||||
static Node *ParseFPOProgram(llvm::StringRef program,
|
||||
llvm::StringRef register_name,
|
||||
llvm::Triple::ArchType arch_type,
|
||||
NodeAllocator &alloc) {
|
||||
llvm::DenseMap<llvm::StringRef, Node *> dependent_programs;
|
||||
|
||||
size_t cur = 0;
|
||||
while (true) {
|
||||
|
@ -498,7 +332,7 @@ static FPOProgramNode *ParseFPOProgram(llvm::StringRef program,
|
|||
llvm::StringRef assignment_program = program.slice(cur, assign_index);
|
||||
|
||||
llvm::StringRef lvalue_name;
|
||||
FPOProgramNode *rvalue_ast = nullptr;
|
||||
Node *rvalue_ast = nullptr;
|
||||
if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name,
|
||||
rvalue_ast)) {
|
||||
return nullptr;
|
||||
|
@ -532,7 +366,7 @@ bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression(
|
|||
llvm::StringRef program, llvm::StringRef register_name,
|
||||
llvm::Triple::ArchType arch_type, Stream &stream) {
|
||||
NodeAllocator node_alloc;
|
||||
FPOProgramNode *target_program =
|
||||
Node *target_program =
|
||||
ParseFPOProgram(program, register_name, arch_type, node_alloc);
|
||||
if (target_program == nullptr) {
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue