summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Symbol/PostfixExpression.h6
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp60
-rw-r--r--lldb/source/Symbol/PostfixExpression.cpp23
-rw-r--r--lldb/unittests/Symbol/PostfixExpressionTest.cpp83
5 files changed, 97 insertions, 77 deletions
diff --git a/lldb/include/lldb/Symbol/PostfixExpression.h b/lldb/include/lldb/Symbol/PostfixExpression.h
index e3a8587a5f8..fa779331589 100644
--- a/lldb/include/lldb/Symbol/PostfixExpression.h
+++ b/lldb/include/lldb/Symbol/PostfixExpression.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
+#include <vector>
namespace lldb_private {
@@ -211,7 +212,10 @@ inline T *MakeNode(llvm::BumpPtrAllocator &alloc, Args &&... args) {
/// Parse the given postfix expression. The parsed nodes are placed into the
/// provided allocator.
-Node *Parse(llvm::StringRef expr, llvm::BumpPtrAllocator &alloc);
+Node *ParseOneExpression(llvm::StringRef expr, llvm::BumpPtrAllocator &alloc);
+
+std::vector<std::pair<llvm::StringRef, Node *>>
+ParseFPOProgram(llvm::StringRef prog, llvm::BumpPtrAllocator &alloc);
/// Serialize the given expression tree as DWARF. The result is written into the
/// given stream. The AST should not contain any SymbolNodes. If the expression
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
index 494e2d487c7..de535ba8886 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -430,7 +430,7 @@ bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules,
while (auto rule = GetRule(unwind_rules)) {
node_alloc.Reset();
llvm::StringRef lhs = rule->first;
- postfix::Node *rhs = postfix::Parse(rule->second, node_alloc);
+ postfix::Node *rhs = postfix::ParseOneExpression(rule->second, node_alloc);
if (!rhs) {
LLDB_LOG(log, "Could not parse `{0}` as unwind rhs.", rule->second);
return false;
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
index 79dd010ff31..a7bc2351971 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
@@ -51,54 +51,23 @@ static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::A
return npdb::GetLLDBRegisterNumber(arch_type, reg_id);
}
-static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
- llvm::BumpPtrAllocator &alloc,
- llvm::StringRef &register_name,
- Node *&ast) {
- // lvalue of assignment is always first token
- // rvalue program goes next
- std::tie(register_name, program) = getToken(program);
- if (register_name.empty())
- return false;
-
- ast = Parse(program, alloc);
- return ast != nullptr;
-}
-
-static Node *ParseFPOProgram(llvm::StringRef program,
+static Node *ResolveFPOProgram(llvm::StringRef program,
llvm::StringRef register_name,
llvm::Triple::ArchType arch_type,
llvm::BumpPtrAllocator &alloc) {
- llvm::DenseMap<llvm::StringRef, Node *> dependent_programs;
-
- size_t cur = 0;
- while (true) {
- size_t assign_index = program.find('=', cur);
- if (assign_index == llvm::StringRef::npos) {
- llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos);
- if (!tail.trim().empty()) {
- // missing assign operator
- return nullptr;
- }
- break;
- }
- llvm::StringRef assignment_program = program.slice(cur, assign_index);
-
- llvm::StringRef lvalue_name;
- Node *rvalue_ast = nullptr;
- if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name,
- rvalue_ast)) {
- return nullptr;
- }
-
- lldbassert(rvalue_ast);
+ std::vector<std::pair<llvm::StringRef, Node *>> parsed =
+ postfix::ParseFPOProgram(program, alloc);
+ for (auto it = parsed.begin(), end = parsed.end(); it != end; ++it) {
// Emplace valid dependent subtrees to make target assignment independent
// from predecessors. Resolve all other SymbolNodes as registers.
bool success =
- ResolveSymbols(rvalue_ast, [&](SymbolNode &symbol) -> Node * {
- if (Node *node = dependent_programs.lookup(symbol.GetName()))
- return node;
+ ResolveSymbols(it->second, [&](SymbolNode &symbol) -> Node * {
+ for (const auto &pair : llvm::make_range(parsed.begin(), it)) {
+ if (pair.first == symbol.GetName())
+ return pair.second;
+ }
+
uint32_t reg_num =
ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), arch_type);
@@ -110,13 +79,10 @@ static Node *ParseFPOProgram(llvm::StringRef program,
if (!success)
return nullptr;
- if (lvalue_name == register_name) {
+ if (it->first == register_name) {
// found target assignment program - no need to parse further
- return rvalue_ast;
+ return it->second;
}
-
- dependent_programs[lvalue_name] = rvalue_ast;
- cur = assign_index + 1;
}
return nullptr;
@@ -127,7 +93,7 @@ bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression(
llvm::Triple::ArchType arch_type, Stream &stream) {
llvm::BumpPtrAllocator node_alloc;
Node *target_program =
- ParseFPOProgram(program, register_name, arch_type, node_alloc);
+ ResolveFPOProgram(program, register_name, arch_type, node_alloc);
if (target_program == nullptr) {
return false;
}
diff --git a/lldb/source/Symbol/PostfixExpression.cpp b/lldb/source/Symbol/PostfixExpression.cpp
index 148653561a4..8ecd571ed92 100644
--- a/lldb/source/Symbol/PostfixExpression.cpp
+++ b/lldb/source/Symbol/PostfixExpression.cpp
@@ -41,7 +41,8 @@ GetUnaryOpType(llvm::StringRef token) {
return llvm::None;
}
-Node *postfix::Parse(llvm::StringRef expr, llvm::BumpPtrAllocator &alloc) {
+Node *postfix::ParseOneExpression(llvm::StringRef expr,
+ llvm::BumpPtrAllocator &alloc) {
llvm::SmallVector<Node *, 4> stack;
llvm::StringRef token;
@@ -83,6 +84,26 @@ Node *postfix::Parse(llvm::StringRef expr, llvm::BumpPtrAllocator &alloc) {
return stack.back();
}
+std::vector<std::pair<llvm::StringRef, Node *>>
+postfix::ParseFPOProgram(llvm::StringRef prog, llvm::BumpPtrAllocator &alloc) {
+ llvm::SmallVector<llvm::StringRef, 4> exprs;
+ prog.split(exprs, '=');
+ if (exprs.empty() || !exprs.back().trim().empty())
+ return {};
+ exprs.pop_back();
+
+ std::vector<std::pair<llvm::StringRef, Node *>> result;
+ for (llvm::StringRef expr : exprs) {
+ llvm::StringRef lhs;
+ std::tie(lhs, expr) = getToken(expr);
+ Node *rhs = ParseOneExpression(expr, alloc);
+ if (!rhs)
+ return {};
+ result.emplace_back(lhs, rhs);
+ }
+ return result;
+}
+
namespace {
class SymbolResolver : public Visitor<bool> {
public:
diff --git a/lldb/unittests/Symbol/PostfixExpressionTest.cpp b/lldb/unittests/Symbol/PostfixExpressionTest.cpp
index 59c818352c9..e9f78197fac 100644
--- a/lldb/unittests/Symbol/PostfixExpressionTest.cpp
+++ b/lldb/unittests/Symbol/PostfixExpressionTest.cpp
@@ -12,6 +12,7 @@
#include "lldb/Utility/StreamString.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
using namespace lldb_private;
@@ -71,40 +72,68 @@ public:
}
};
-static std::string ParseAndStringify(llvm::StringRef expr) {
+static std::string ParseOneAndStringify(llvm::StringRef expr) {
llvm::BumpPtrAllocator alloc;
- return ASTPrinter::Print(Parse(expr, alloc));
+ return ASTPrinter::Print(ParseOneExpression(expr, alloc));
}
-TEST(PostfixExpression, Parse) {
- EXPECT_EQ("int(47)", ParseAndStringify("47"));
- EXPECT_EQ("$foo", ParseAndStringify("$foo"));
- EXPECT_EQ("+(int(1), int(2))", ParseAndStringify("1 2 +"));
- EXPECT_EQ("-(int(1), int(2))", ParseAndStringify("1 2 -"));
- EXPECT_EQ("@(int(1), int(2))", ParseAndStringify("1 2 @"));
- EXPECT_EQ("+(int(1), +(int(2), int(3)))", ParseAndStringify("1 2 3 + +"));
- EXPECT_EQ("+(+(int(1), int(2)), int(3))", ParseAndStringify("1 2 + 3 +"));
- EXPECT_EQ("^(int(1))", ParseAndStringify("1 ^"));
- EXPECT_EQ("^(^(int(1)))", ParseAndStringify("1 ^ ^"));
- EXPECT_EQ("^(+(int(1), ^(int(2))))", ParseAndStringify("1 2 ^ + ^"));
- EXPECT_EQ("-($foo, int(47))", ParseAndStringify("$foo 47 -"));
- EXPECT_EQ("+(int(47), int(-42))", ParseAndStringify("47 -42 +"));
-
- EXPECT_EQ("nullptr", ParseAndStringify("+"));
- EXPECT_EQ("nullptr", ParseAndStringify("^"));
- EXPECT_EQ("nullptr", ParseAndStringify("1 +"));
- EXPECT_EQ("nullptr", ParseAndStringify("1 2 ^"));
- EXPECT_EQ("nullptr", ParseAndStringify("1 2 3 +"));
- EXPECT_EQ("nullptr", ParseAndStringify("^ 1"));
- EXPECT_EQ("nullptr", ParseAndStringify("+ 1 2"));
- EXPECT_EQ("nullptr", ParseAndStringify("1 + 2"));
- EXPECT_EQ("nullptr", ParseAndStringify("1 2"));
- EXPECT_EQ("nullptr", ParseAndStringify(""));
+TEST(PostfixExpression, ParseOneExpression) {
+ EXPECT_EQ("int(47)", ParseOneAndStringify("47"));
+ EXPECT_EQ("$foo", ParseOneAndStringify("$foo"));
+ EXPECT_EQ("+(int(1), int(2))", ParseOneAndStringify("1 2 +"));
+ EXPECT_EQ("-(int(1), int(2))", ParseOneAndStringify("1 2 -"));
+ EXPECT_EQ("@(int(1), int(2))", ParseOneAndStringify("1 2 @"));
+ EXPECT_EQ("+(int(1), +(int(2), int(3)))", ParseOneAndStringify("1 2 3 + +"));
+ EXPECT_EQ("+(+(int(1), int(2)), int(3))", ParseOneAndStringify("1 2 + 3 +"));
+ EXPECT_EQ("^(int(1))", ParseOneAndStringify("1 ^"));
+ EXPECT_EQ("^(^(int(1)))", ParseOneAndStringify("1 ^ ^"));
+ EXPECT_EQ("^(+(int(1), ^(int(2))))", ParseOneAndStringify("1 2 ^ + ^"));
+ EXPECT_EQ("-($foo, int(47))", ParseOneAndStringify("$foo 47 -"));
+ EXPECT_EQ("+(int(47), int(-42))", ParseOneAndStringify("47 -42 +"));
+
+ EXPECT_EQ("nullptr", ParseOneAndStringify("+"));
+ EXPECT_EQ("nullptr", ParseOneAndStringify("^"));
+ EXPECT_EQ("nullptr", ParseOneAndStringify("1 +"));
+ EXPECT_EQ("nullptr", ParseOneAndStringify("1 2 ^"));
+ EXPECT_EQ("nullptr", ParseOneAndStringify("1 2 3 +"));
+ EXPECT_EQ("nullptr", ParseOneAndStringify("^ 1"));
+ EXPECT_EQ("nullptr", ParseOneAndStringify("+ 1 2"));
+ EXPECT_EQ("nullptr", ParseOneAndStringify("1 + 2"));
+ EXPECT_EQ("nullptr", ParseOneAndStringify("1 2"));
+ EXPECT_EQ("nullptr", ParseOneAndStringify(""));
+}
+
+static std::vector<std::pair<std::string, std::string>>
+ParseFPOAndStringify(llvm::StringRef prog) {
+ llvm::BumpPtrAllocator alloc;
+ std::vector<std::pair<llvm::StringRef, Node *>> parsed =
+ ParseFPOProgram(prog, alloc);
+ auto range = llvm::map_range(
+ parsed, [](const std::pair<llvm::StringRef, Node *> &pair) {
+ return std::make_pair(pair.first, ASTPrinter::Print(pair.second));
+ });
+ return std::vector<std::pair<std::string, std::string>>(range.begin(),
+ range.end());
+}
+
+TEST(PostfixExpression, ParseFPOProgram) {
+ EXPECT_THAT(ParseFPOAndStringify("a 1 ="),
+ testing::ElementsAre(std::make_pair("a", "int(1)")));
+ EXPECT_THAT(ParseFPOAndStringify("a 1 = b 2 3 + ="),
+ testing::ElementsAre(std::make_pair("a", "int(1)"),
+ std::make_pair("b", "+(int(2), int(3))")));
+
+ EXPECT_THAT(ParseFPOAndStringify(""), testing::IsEmpty());
+ EXPECT_THAT(ParseFPOAndStringify("="), testing::IsEmpty());
+ EXPECT_THAT(ParseFPOAndStringify("a 1"), testing::IsEmpty());
+ EXPECT_THAT(ParseFPOAndStringify("a 1 = ="), testing::IsEmpty());
+ EXPECT_THAT(ParseFPOAndStringify("a 1 + ="), testing::IsEmpty());
+ EXPECT_THAT(ParseFPOAndStringify("= a 1 ="), testing::IsEmpty());
}
static std::string ParseAndGenerateDWARF(llvm::StringRef expr) {
llvm::BumpPtrAllocator alloc;
- Node *ast = Parse(expr, alloc);
+ Node *ast = ParseOneExpression(expr, alloc);
if (!ast)
return "Parse failed.";
if (!ResolveSymbols(ast, [&](SymbolNode &symbol) -> Node * {
OpenPOWER on IntegriCloud