This revision was automatically updated to reflect the committed changes.
labath marked an inline comment as done.
Closed by commit rL369894: Postfix: move more code out of the PDB plugin 
(authored by labath, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66634/new/

https://reviews.llvm.org/D66634

Files:
  lldb/trunk/include/lldb/Symbol/PostfixExpression.h
  lldb/trunk/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
  
lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
  lldb/trunk/source/Symbol/PostfixExpression.cpp
  lldb/trunk/unittests/Symbol/PostfixExpressionTest.cpp

Index: lldb/trunk/unittests/Symbol/PostfixExpressionTest.cpp
===================================================================
--- lldb/trunk/unittests/Symbol/PostfixExpressionTest.cpp
+++ lldb/trunk/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 @@
   }
 };
 
-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 * {
Index: lldb/trunk/source/Symbol/PostfixExpression.cpp
===================================================================
--- lldb/trunk/source/Symbol/PostfixExpression.cpp
+++ lldb/trunk/source/Symbol/PostfixExpression.cpp
@@ -41,7 +41,8 @@
   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 @@
   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:
Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
@@ -51,54 +51,23 @@
   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 @@
     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 @@
     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;
   }
Index: lldb/trunk/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ lldb/trunk/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -430,7 +430,7 @@
   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;
Index: lldb/trunk/include/lldb/Symbol/PostfixExpression.h
===================================================================
--- lldb/trunk/include/lldb/Symbol/PostfixExpression.h
+++ lldb/trunk/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 @@
 
 /// 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
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to