Implement some unary operations
authorTom Tromey <tom@tromey.com>
Mon, 8 Mar 2021 14:27:57 +0000 (07:27 -0700)
committerTom Tromey <tom@tromey.com>
Mon, 8 Mar 2021 14:28:20 +0000 (07:28 -0700)
This introduces a couple of new template classes and then uses them to
implement some simple unary operations.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

* expop.h (unary_ftype): New typedef.
(unop_operation, usual_ax_binop_operation): New templates.
(unary_plus_operation, unary_neg_operation)
(unary_complement_operation, unary_logical_not_operation): New
typedefs.
* eval.c (eval_op_plus, eval_op_neg, eval_op_complement)
(eval_op_lognot): No longer static.
* ax-gdb.c (gen_expr_unop): New function.

gdb/ChangeLog
gdb/ax-gdb.c
gdb/eval.c
gdb/expop.h

index 729074bd61d019a9267838eac9488ca55e9eb5be..17281bf5ba49496a80c0ff36bff5ac3c64c8613b 100644 (file)
@@ -1,3 +1,14 @@
+2021-03-08  Tom Tromey  <tom@tromey.com>
+
+       * expop.h (unary_ftype): New typedef.
+       (unop_operation, usual_ax_binop_operation): New templates.
+       (unary_plus_operation, unary_neg_operation)
+       (unary_complement_operation, unary_logical_not_operation): New
+       typedefs.
+       * eval.c (eval_op_plus, eval_op_neg, eval_op_complement)
+       (eval_op_lognot): No longer static.
+       * ax-gdb.c (gen_expr_unop): New function.
+
 2021-03-08  Tom Tromey  <tom@tromey.com>
 
        * ax-gdb.c (comma_operation::do_generate_ax): New method.
index 8d5e4fff9033728aefa575cf2a47d77b9e9f7728..c87b290397d113d09be4cef5a53e32f0525d8e08 100644 (file)
@@ -2694,6 +2694,53 @@ gen_expr_structop (struct expression *exp,
     internal_error (__FILE__, __LINE__,
                    _("gen_expr: unhandled struct case"));
 }
+
+/* A helper function that emits a unary operation.  */
+
+void
+gen_expr_unop (struct expression *exp,
+              enum exp_opcode op,
+              expr::operation *lhs,
+              struct agent_expr *ax, struct axs_value *value)
+{
+  struct axs_value value1, value2;
+
+  switch (op)
+    {
+    case UNOP_NEG:
+      gen_int_literal (ax, &value1, 0,
+                      builtin_type (ax->gdbarch)->builtin_int);
+      gen_usual_unary (ax, &value1);   /* shouldn't do much */
+      lhs->generate_ax (exp, ax, &value2);
+      gen_usual_unary (ax, &value2);
+      gen_usual_arithmetic (ax, &value1, &value2);
+      gen_binop (ax, value, &value1, &value2, aop_sub, aop_sub, 1, "negation");
+      break;
+
+    case UNOP_PLUS:
+      /* + FOO is equivalent to 0 + FOO, which can be optimized.  */
+      lhs->generate_ax (exp, ax, value);
+      gen_usual_unary (ax, value);
+      break;
+
+    case UNOP_LOGICAL_NOT:
+      lhs->generate_ax (exp, ax, value);
+      gen_usual_unary (ax, value);
+      gen_logical_not (ax, value,  builtin_type (ax->gdbarch)->builtin_int);
+      break;
+
+    case UNOP_COMPLEMENT:
+      lhs->generate_ax (exp, ax, value);
+      gen_usual_unary (ax, value);
+      gen_integral_promotions (ax, value);
+      gen_complement (ax, value);
+      break;
+
+    default:
+      gdb_assert_not_reached ("invalid case in gen_expr_unop");
+    }
+}
+
 \f
 
 /* Given a single variable and a scope, generate bytecodes to trace
index 2d2f881746c1dbbaefe86b0ae2b172472c9361d3..8d75c08541bbdf296fdfb6c01d0a61325e69317f 100644 (file)
@@ -1754,7 +1754,7 @@ eval_op_repeat (struct type *expect_type, struct expression *exp,
 
 /* A helper function for UNOP_PLUS.  */
 
-static struct value *
+struct value *
 eval_op_plus (struct type *expect_type, struct expression *exp,
              enum noside noside, enum exp_opcode op,
              struct value *arg1)
@@ -1772,7 +1772,7 @@ eval_op_plus (struct type *expect_type, struct expression *exp,
 
 /* A helper function for UNOP_NEG.  */
 
-static struct value *
+struct value *
 eval_op_neg (struct type *expect_type, struct expression *exp,
             enum noside noside, enum exp_opcode op,
             struct value *arg1)
@@ -1790,7 +1790,7 @@ eval_op_neg (struct type *expect_type, struct expression *exp,
 
 /* A helper function for UNOP_COMPLEMENT.  */
 
-static struct value *
+struct value *
 eval_op_complement (struct type *expect_type, struct expression *exp,
                    enum noside noside, enum exp_opcode op,
                    struct value *arg1)
@@ -1808,7 +1808,7 @@ eval_op_complement (struct type *expect_type, struct expression *exp,
 
 /* A helper function for UNOP_LOGICAL_NOT.  */
 
-static struct value *
+struct value *
 eval_op_lognot (struct type *expect_type, struct expression *exp,
                enum noside noside, enum exp_opcode op,
                struct value *arg1)
index 2fa5b2f205525041afa76f6780e3748fccfc70ab..abd914ad574cf4643641433739a36a8c7f08bd50 100644 (file)
@@ -40,6 +40,10 @@ extern void gen_expr_structop (struct expression *exp,
                               expr::operation *lhs,
                               const char *name,
                               struct agent_expr *ax, struct axs_value *value);
+extern void gen_expr_unop (struct expression *exp,
+                          enum exp_opcode op,
+                          expr::operation *lhs,
+                          struct agent_expr *ax, struct axs_value *value);
 
 extern struct value *eval_op_scope (struct type *expect_type,
                                    struct expression *exp,
@@ -140,6 +144,24 @@ extern struct value *eval_op_repeat (struct type *expect_type,
                                     enum noside noside, enum exp_opcode op,
                                     struct value *arg1,
                                     struct value *arg2);
+extern struct value *eval_op_plus (struct type *expect_type,
+                                  struct expression *exp,
+                                  enum noside noside, enum exp_opcode op,
+                                  struct value *arg1);
+extern struct value *eval_op_neg (struct type *expect_type,
+                                 struct expression *exp,
+                                 enum noside noside, enum exp_opcode op,
+                                 struct value *arg1);
+extern struct value *eval_op_complement (struct type *expect_type,
+                                        struct expression *exp,
+                                        enum noside noside,
+                                        enum exp_opcode op,
+                                        struct value *arg1);
+extern struct value *eval_op_lognot (struct type *expect_type,
+                                    struct expression *exp,
+                                    enum noside noside,
+                                    enum exp_opcode op,
+                                    struct value *arg1);
 
 namespace expr
 {
@@ -1239,6 +1261,61 @@ protected:
     override;
 };
 
+typedef struct value *unary_ftype (struct type *expect_type,
+                                  struct expression *exp,
+                                  enum noside noside, enum exp_opcode op,
+                                  struct value *arg1);
+
+/* Base class for unary operations.  */
+template<enum exp_opcode OP, unary_ftype FUNC>
+class unop_operation
+  : public maybe_constant_operation<operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+    return FUNC (expect_type, exp, noside, OP, val);
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP; }
+};
+
+/* Unary operations that can also be turned into agent expressions in
+   the "usual" way.  */
+template<enum exp_opcode OP, unary_ftype FUNC>
+class usual_ax_unop_operation
+  : public unop_operation<OP, FUNC>
+{
+  using unop_operation<OP, FUNC>::unop_operation;
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override
+  {
+    gen_expr_unop (exp, OP,
+                  std::get<0> (this->m_storage).get (),
+                  ax, value);
+  }
+};
+
+using unary_plus_operation = usual_ax_unop_operation<UNOP_PLUS, eval_op_plus>;
+using unary_neg_operation = usual_ax_unop_operation<UNOP_NEG, eval_op_neg>;
+using unary_complement_operation
+     = usual_ax_unop_operation<UNOP_COMPLEMENT, eval_op_complement>;
+using unary_logical_not_operation
+     = usual_ax_unop_operation<UNOP_LOGICAL_NOT, eval_op_lognot>;
+
 } /* namespace expr */
 
 #endif /* EXPOP_H */