PDBFPO: Refactor register reference resolution

Summary:
This refactors moves the register name->number resolution out of the
FPOProgramNodeRegisterRef class. Instead I create a special
FPOProgramNodeSymbol class, which holds unresolved symbols, and move the
resolution into the ResolveRegisterRefs visitor.

The background here is that I'd like to use this code for Breakpad
unwind info, which uses similar syntax to describe unwind info. For
example, a simple breakpad unwind program might look like:
    .cfa: $esp 8 + $ebp: .cfa 8 - ^

To be able to do this, I need to be able to customize register
resolving, as that is presently hardcoded to use codeview register
names, but breakpad supports a lot more architectures with different
register names. Moving the resolution into a separate class will allow
each user to use a different resolution logic.

Reviewers: aleksandr.urakov, zturner, amccarth

Subscribers: jdoerfert, lldb-commits

Differential Revision: https://reviews.llvm.org/D60068

llvm-svn: 357455
This commit is contained in:
Pavel Labath 2019-04-02 08:44:24 +00:00
parent bea52e5289
commit 1c4ee16012
1 changed files with 80 additions and 60 deletions

View File

@ -27,9 +27,21 @@ namespace {
class FPOProgramNode; class FPOProgramNode;
class FPOProgramASTVisitor; class FPOProgramASTVisitor;
class NodeAllocator {
public:
template <typename T, typename... Args> T *makeNode(Args &&... args) {
void *new_node_mem = m_alloc.Allocate(sizeof(T), alignof(T));
return new (new_node_mem) T(std::forward<Args>(args)...);
}
private:
llvm::BumpPtrAllocator m_alloc;
};
class FPOProgramNode { class FPOProgramNode {
public: public:
enum Kind { enum Kind {
Symbol,
Register, Register,
IntegerLiteral, IntegerLiteral,
BinaryOp, BinaryOp,
@ -49,46 +61,31 @@ private:
Kind m_token_kind; Kind m_token_kind;
}; };
class FPOProgramNodeRegisterRef : public FPOProgramNode { class FPOProgramNodeSymbol: public FPOProgramNode {
public: public:
FPOProgramNodeRegisterRef(llvm::StringRef name) FPOProgramNodeSymbol(llvm::StringRef name)
: FPOProgramNode(Register), m_name(name) {} : FPOProgramNode(Symbol), m_name(name) {}
void Accept(FPOProgramASTVisitor *visitor) override; void Accept(FPOProgramASTVisitor *visitor) override;
llvm::StringRef GetName() const { return m_name; } llvm::StringRef GetName() const { return m_name; }
uint32_t GetLLDBRegNum() const { return m_lldb_reg_num; }
bool ResolveLLDBRegisterNum(llvm::Triple::ArchType arch_type);
private: private:
llvm::StringRef m_name; llvm::StringRef m_name;
uint32_t m_lldb_reg_num = LLDB_INVALID_REGNUM;
}; };
bool FPOProgramNodeRegisterRef::ResolveLLDBRegisterNum( class FPOProgramNodeRegisterRef : public FPOProgramNode {
llvm::Triple::ArchType arch_type) { public:
FPOProgramNodeRegisterRef(uint32_t lldb_reg_num)
: FPOProgramNode(Register), m_lldb_reg_num(lldb_reg_num) {}
llvm::StringRef reg_name = m_name.slice(1, m_name.size()); void Accept(FPOProgramASTVisitor *visitor) override;
// lookup register name to get lldb register number uint32_t GetLLDBRegNum() const { return m_lldb_reg_num; }
llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names =
llvm::codeview::getRegisterNames();
auto it = llvm::find_if(
register_names,
[&reg_name](const llvm::EnumEntry<uint16_t> &register_entry) {
return reg_name.compare_lower(register_entry.Name) == 0;
});
if (it == register_names.end()) { private:
return false; uint32_t m_lldb_reg_num;
} };
auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value);
m_lldb_reg_num = npdb::GetLLDBRegisterNumber(arch_type, reg_id);
return m_lldb_reg_num != LLDB_INVALID_REGNUM;
}
class FPOProgramNodeIntegerLiteral : public FPOProgramNode { class FPOProgramNodeIntegerLiteral : public FPOProgramNode {
public: public:
@ -157,12 +154,17 @@ class FPOProgramASTVisitor {
public: public:
virtual ~FPOProgramASTVisitor() = default; virtual ~FPOProgramASTVisitor() = default;
virtual void Visit(FPOProgramNodeSymbol *node) {}
virtual void Visit(FPOProgramNodeRegisterRef *node) {} virtual void Visit(FPOProgramNodeRegisterRef *node) {}
virtual void Visit(FPOProgramNodeIntegerLiteral *node) {} virtual void Visit(FPOProgramNodeIntegerLiteral *node) {}
virtual void Visit(FPOProgramNodeBinaryOp *node) {} virtual void Visit(FPOProgramNodeBinaryOp *node) {}
virtual void Visit(FPOProgramNodeUnaryOp *node) {} virtual void Visit(FPOProgramNodeUnaryOp *node) {}
}; };
void FPOProgramNodeSymbol::Accept(FPOProgramASTVisitor *visitor) {
visitor->Visit(this);
}
void FPOProgramNodeRegisterRef::Accept(FPOProgramASTVisitor *visitor) { void FPOProgramNodeRegisterRef::Accept(FPOProgramASTVisitor *visitor) {
visitor->Visit(this); visitor->Visit(this);
} }
@ -216,11 +218,10 @@ void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeUnaryOp *node) {
void FPOProgramASTVisitorMergeDependent::TryReplace( void FPOProgramASTVisitorMergeDependent::TryReplace(
FPOProgramNode *&node_ref) const { FPOProgramNode *&node_ref) const {
while (node_ref->GetKind() == FPOProgramNode::Register) { while (node_ref->GetKind() == FPOProgramNode::Symbol) {
auto *node_register_ref = auto *node_symbol_ref = static_cast<FPOProgramNodeSymbol *>(node_ref);
static_cast<FPOProgramNodeRegisterRef *>(node_ref);
auto it = m_dependent_programs.find(node_register_ref->GetName()); auto it = m_dependent_programs.find(node_symbol_ref->GetName());
if (it == m_dependent_programs.end()) { if (it == m_dependent_programs.end()) {
break; break;
} }
@ -234,39 +235,70 @@ public:
FPOProgramASTVisitorResolveRegisterRefs( FPOProgramASTVisitorResolveRegisterRefs(
const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> const llvm::DenseMap<llvm::StringRef, FPOProgramNode *>
&dependent_programs, &dependent_programs,
llvm::Triple::ArchType arch_type) llvm::Triple::ArchType arch_type, NodeAllocator &alloc)
: m_dependent_programs(dependent_programs), m_arch_type(arch_type) {} : m_dependent_programs(dependent_programs), m_arch_type(arch_type),
m_alloc(alloc) {}
bool Resolve(FPOProgramNode *program); bool Resolve(FPOProgramNode *&program);
private: private:
void Visit(FPOProgramNodeRegisterRef *node) override;
void Visit(FPOProgramNodeIntegerLiteral *node) override {}
void Visit(FPOProgramNodeBinaryOp *node) override; void Visit(FPOProgramNodeBinaryOp *node) override;
void Visit(FPOProgramNodeUnaryOp *node) override; void Visit(FPOProgramNodeUnaryOp *node) override;
private: bool TryReplace(FPOProgramNode *&node_ref);
const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs; const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs;
llvm::Triple::ArchType m_arch_type; llvm::Triple::ArchType m_arch_type;
NodeAllocator &m_alloc;
bool m_no_error_flag = true; bool m_no_error_flag = true;
}; };
bool FPOProgramASTVisitorResolveRegisterRefs::Resolve(FPOProgramNode *program) { bool FPOProgramASTVisitorResolveRegisterRefs::Resolve(FPOProgramNode *&program) {
if (!TryReplace(program))
return false;
program->Accept(this); program->Accept(this);
return m_no_error_flag; return m_no_error_flag;
} }
void FPOProgramASTVisitorResolveRegisterRefs::Visit( static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::ArchType arch_type) {
FPOProgramNodeRegisterRef *node) { // lookup register name to get lldb register number
llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names =
llvm::codeview::getRegisterNames();
auto it = llvm::find_if(
register_names,
[&reg_name](const llvm::EnumEntry<uint16_t> &register_entry) {
return reg_name.compare_lower(register_entry.Name) == 0;
});
// lookup register reference as lvalue in predecedent assignments if (it == register_names.end())
auto it = m_dependent_programs.find(node->GetName()); return LLDB_INVALID_REGNUM;
if (it != m_dependent_programs.end()) {
// dependent programs are already resolved and valid auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value);
return; return npdb::GetLLDBRegisterNumber(arch_type, reg_id);
} }
// try to resolve register reference as lldb register name
m_no_error_flag = node->ResolveLLDBRegisterNum(m_arch_type); bool FPOProgramASTVisitorResolveRegisterRefs::TryReplace(
FPOProgramNode *&node_ref) {
if (node_ref->GetKind() != FPOProgramNode::Symbol)
return true;
auto *symbol = static_cast<FPOProgramNodeSymbol *>(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()) {
// Dependent programs are handled elsewhere.
return true;
}
uint32_t reg_num =
ResolveLLDBRegisterNum(symbol->GetName().drop_front(1), m_arch_type);
if (reg_num == LLDB_INVALID_REGNUM)
return false;
node_ref = m_alloc.makeNode<FPOProgramNodeRegisterRef>(reg_num);
return true;
} }
void FPOProgramASTVisitorResolveRegisterRefs::Visit( void FPOProgramASTVisitorResolveRegisterRefs::Visit(
@ -357,17 +389,6 @@ void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeUnaryOp *node) {
} }
} }
class NodeAllocator {
public:
template <typename T, typename... Args> T *makeNode(Args &&... args) {
void *new_node_mem = m_alloc.Allocate(sizeof(T), alignof(T));
return new (new_node_mem) T(std::forward<Args>(args)...);
}
private:
llvm::BumpPtrAllocator m_alloc;
};
} // namespace } // namespace
static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program, static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
@ -427,8 +448,7 @@ static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
} }
if (cur.startswith("$")) { if (cur.startswith("$")) {
// token is register ref eval_stack.push_back(alloc.makeNode<FPOProgramNodeSymbol>(cur));
eval_stack.push_back(alloc.makeNode<FPOProgramNodeRegisterRef>(cur));
continue; continue;
} }
@ -488,7 +508,7 @@ static FPOProgramNode *ParseFPOProgram(llvm::StringRef program,
// check & resolve assignment program // check & resolve assignment program
FPOProgramASTVisitorResolveRegisterRefs resolver(dependent_programs, FPOProgramASTVisitorResolveRegisterRefs resolver(dependent_programs,
arch_type); arch_type, alloc);
if (!resolver.Resolve(rvalue_ast)) { if (!resolver.Resolve(rvalue_ast)) {
return nullptr; return nullptr;
} }