[Lldb-commits] [lldb] r359560 - PostfixExpression: Introduce InitialValueNode

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Tue Apr 30 06:33:19 PDT 2019


Author: labath
Date: Tue Apr 30 06:33:18 2019
New Revision: 359560

URL: http://llvm.org/viewvc/llvm-project?rev=359560&view=rev
Log:
PostfixExpression: Introduce InitialValueNode

Summary:
This node represents can be used to refer to the initial value, which is
sometimes pushed onto the DWARF stack as the "input" to the DWARF
expression. The typical use case (and the reason why I'm introducing it)
is that the "Canonical Frame Address" is passed this way to the DWARF
expressions computing the values of registers during frame unwind.

The nodes are converted into dwarf by keeping track of DWARF stack depth
an any given point, and then copying the initial value from the bottom
of the stack via the DW_OP_pick opcode. This could be made more
efficient for simple expressions, but here I chose to start with the
most general implementation possible.

Reviewers: amccarth, clayborg, aleksandr.urakov

Subscribers: aprantl, jasonmolenda, lldb-commits, markmentovai

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

Modified:
    lldb/trunk/include/lldb/Symbol/PostfixExpression.h
    lldb/trunk/source/Symbol/PostfixExpression.cpp
    lldb/trunk/unittests/Symbol/PostfixExpressionTest.cpp

Modified: lldb/trunk/include/lldb/Symbol/PostfixExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/PostfixExpression.h?rev=359560&r1=359559&r2=359560&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/PostfixExpression.h (original)
+++ lldb/trunk/include/lldb/Symbol/PostfixExpression.h Tue Apr 30 06:33:18 2019
@@ -29,6 +29,7 @@ class Node {
 public:
   enum Kind {
     BinaryOp,
+    InitialValue,
     Integer,
     Register,
     Symbol,
@@ -73,6 +74,16 @@ private:
   Node *m_right;
 };
 
+/// A node representing the canonical frame address.
+class InitialValueNode: public Node {
+public:
+  InitialValueNode() : Node(InitialValue) {}
+
+  static bool classof(const Node *node) {
+    return node->GetKind() == InitialValue;
+  }
+};
+
 /// A node representing an integer literal.
 class IntegerNode : public Node {
 public:
@@ -153,6 +164,7 @@ protected:
   virtual ~Visitor() = default;
 
   virtual ResultT Visit(BinaryOpNode &binary, Node *&ref) = 0;
+  virtual ResultT Visit(InitialValueNode &val, Node *&ref) = 0;
   virtual ResultT Visit(IntegerNode &integer, Node *&) = 0;
   virtual ResultT Visit(RegisterNode &reg, Node *&) = 0;
   virtual ResultT Visit(SymbolNode &symbol, Node *&ref) = 0;
@@ -164,6 +176,8 @@ protected:
     switch (node->GetKind()) {
     case Node::BinaryOp:
       return Visit(llvm::cast<BinaryOpNode>(*node), node);
+    case Node::InitialValue:
+      return Visit(llvm::cast<InitialValueNode>(*node), node);
     case Node::Integer:
       return Visit(llvm::cast<IntegerNode>(*node), node);
     case Node::Register:
@@ -200,7 +214,10 @@ inline T *MakeNode(llvm::BumpPtrAllocato
 Node *Parse(llvm::StringRef expr, 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.
+/// given stream. The AST should not contain any SymbolNodes. If the expression
+/// contains InitialValueNodes, the generated expression will assume that their
+/// value will be provided as the top value of the initial evaluation stack (as
+/// is the case with the CFA value in register eh_unwind rules).
 void ToDWARF(Node &node, Stream &stream);
 
 } // namespace postfix

Modified: lldb/trunk/source/Symbol/PostfixExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/PostfixExpression.cpp?rev=359560&r1=359559&r2=359560&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/PostfixExpression.cpp (original)
+++ lldb/trunk/source/Symbol/PostfixExpression.cpp Tue Apr 30 06:33:18 2019
@@ -96,8 +96,9 @@ private:
     return Dispatch(binary.Left()) && Dispatch(binary.Right());
   }
 
-  bool Visit(IntegerNode &integer, Node *&) override { return true; }
-  bool Visit(RegisterNode &reg, Node *&) override { return true; }
+  bool Visit(InitialValueNode &, Node *&) override { return true; }
+  bool Visit(IntegerNode &, Node *&) override { return true; }
+  bool Visit(RegisterNode &, Node *&) override { return true; }
 
   bool Visit(SymbolNode &symbol, Node *&ref) override {
     if (Node *replacement = m_replacer(symbol)) {
@@ -125,9 +126,12 @@ public:
 private:
   void Visit(BinaryOpNode &binary, Node *&);
 
+  void Visit(InitialValueNode &val, Node *&);
+
   void Visit(IntegerNode &integer, Node *&) {
     m_out_stream.PutHex8(DW_OP_constu);
     m_out_stream.PutULEB128(integer.GetValue());
+    ++m_stack_depth;
   }
 
   void Visit(RegisterNode &reg, Node *&);
@@ -139,6 +143,15 @@ private:
   void Visit(UnaryOpNode &unary, Node *&);
 
   Stream &m_out_stream;
+
+  /// The number keeping track of the evaluation stack depth at any given
+  /// moment. Used for implementing InitialValueNodes. We start with
+  /// m_stack_depth = 1, assuming that the initial value is already on the
+  /// stack. This initial value will be the value of all InitialValueNodes. If
+  /// the expression does not contain InitialValueNodes, then m_stack_depth is
+  /// not used, and the generated expression will run correctly even without an
+  /// initial value.
+  size_t m_stack_depth = 1;
 };
 } // namespace
 
@@ -166,6 +179,16 @@ void DWARFCodegen::Visit(BinaryOpNode &b
     m_out_stream.PutHex8(DW_OP_and);
     break;
   }
+  --m_stack_depth; // Two pops, one push.
+}
+
+void DWARFCodegen::Visit(InitialValueNode &, Node *&) {
+  // We never go below the initial stack, so we can pick the initial value from
+  // the bottom of the stack at any moment.
+  assert(m_stack_depth >= 1);
+  m_out_stream.PutHex8(DW_OP_pick);
+  m_out_stream.PutHex8(m_stack_depth - 1);
+  ++m_stack_depth;
 }
 
 void DWARFCodegen::Visit(RegisterNode &reg, Node *&) {
@@ -179,6 +202,7 @@ void DWARFCodegen::Visit(RegisterNode &r
     m_out_stream.PutHex8(DW_OP_breg0 + reg_num);
 
   m_out_stream.PutSLEB128(0);
+  ++m_stack_depth;
 }
 
 void DWARFCodegen::Visit(UnaryOpNode &unary, Node *&) {
@@ -189,6 +213,7 @@ void DWARFCodegen::Visit(UnaryOpNode &un
     m_out_stream.PutHex8(DW_OP_deref);
     break;
   }
+  // Stack depth unchanged.
 }
 
 bool postfix::ResolveSymbols(

Modified: lldb/trunk/unittests/Symbol/PostfixExpressionTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Symbol/PostfixExpressionTest.cpp?rev=359560&r1=359559&r2=359560&view=diff
==============================================================================
--- lldb/trunk/unittests/Symbol/PostfixExpressionTest.cpp (original)
+++ lldb/trunk/unittests/Symbol/PostfixExpressionTest.cpp Tue Apr 30 06:33:18 2019
@@ -44,6 +44,8 @@ protected:
                          Dispatch(binary.Left()), Dispatch(binary.Right()));
   }
 
+  std::string Visit(InitialValueNode &, Node *&) override { return "InitialValue"; }
+
   std::string Visit(IntegerNode &integer, Node *&) override {
     return llvm::formatv("int({0})", integer.GetValue());
   }
@@ -105,6 +107,9 @@ static std::string ParseAndGenerateDWARF
   if (!ast)
     return "Parse failed.";
   if (!ResolveSymbols(ast, [&](SymbolNode &symbol) -> Node * {
+        if (symbol.GetName() == "INIT")
+          return MakeNode<InitialValueNode>(alloc);
+
         uint32_t num;
         if (to_integer(symbol.GetName().drop_front(), num))
           return MakeNode<RegisterNode>(alloc, num);
@@ -138,6 +143,17 @@ TEST(PostfixExpression, ToDWARF) {
 
   EXPECT_EQ("DW_OP_bregx 65 0", ParseAndGenerateDWARF("R65"));
 
+  EXPECT_EQ("DW_OP_pick 0x00", ParseAndGenerateDWARF("INIT"));
+
+  EXPECT_EQ("DW_OP_pick 0x00, DW_OP_pick 0x01, DW_OP_plus ",
+            ParseAndGenerateDWARF("INIT INIT +"));
+
+  EXPECT_EQ("DW_OP_breg1 +0, DW_OP_pick 0x01, DW_OP_plus ",
+            ParseAndGenerateDWARF("R1 INIT +"));
+
+  EXPECT_EQ("DW_OP_constu 0x1, DW_OP_pick 0x01, DW_OP_deref , DW_OP_plus ",
+            ParseAndGenerateDWARF("1 INIT ^ +"));
+
   EXPECT_EQ("DW_OP_constu 0x4, DW_OP_constu 0x5, DW_OP_plus ",
             ParseAndGenerateDWARF("4 5 +"));
 




More information about the lldb-commits mailing list