Implement the "&&" and "||" operators
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:28 +0000 (07:28 -0700)
This implements the "&&" and "||" operators.

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

* expop.h (class logical_and_operation)
(class logical_or_operation): New.
* eval.c (logical_and_operation::evaluate)
(logical_or_operation::evaluate): New methods.
* ax-gdb.c (logical_and_operation::do_generate_ax)
(logical_or_operation::do_generate_ax): New methods.

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

index fcacb6db16c0ce2a2084c16af1203711bae5622e..f91477acc113728fcde37fec26ca376ce1d02a6e 100644 (file)
@@ -1,3 +1,12 @@
+2021-03-08  Tom Tromey  <tom@tromey.com>
+
+       * expop.h (class logical_and_operation)
+       (class logical_or_operation): New.
+       * eval.c (logical_and_operation::evaluate)
+       (logical_or_operation::evaluate): New methods.
+       * ax-gdb.c (logical_and_operation::do_generate_ax)
+       (logical_or_operation::do_generate_ax): New methods.
+
 2021-03-08  Tom Tromey  <tom@tromey.com>
 
        * m2-lang.c (eval_op_m2_high, eval_op_m2_subscript): No longer
index bdf4a6dc39a25a95a321dd09e248eaa51d6f0f40..8ec3dd7cc3d5f36d02995c4967c2cab34fe2261a 100644 (file)
@@ -2693,6 +2693,62 @@ var_value_operation::do_generate_ax (struct expression *exp,
     }
 }
 
+void
+logical_and_operation::do_generate_ax (struct expression *exp,
+                                      struct agent_expr *ax,
+                                      struct axs_value *value,
+                                      struct type *cast_type)
+{
+  struct axs_value value1, value2;
+  int if1, go1, if2, go2, end;
+
+  /* Generate the obvious sequence of tests and jumps.  */
+  std::get<0> (m_storage)->generate_ax (exp, ax, &value1);
+  gen_usual_unary (ax, &value1);
+  if1 = ax_goto (ax, aop_if_goto);
+  go1 = ax_goto (ax, aop_goto);
+  ax_label (ax, if1, ax->len);
+  std::get<1> (m_storage)->generate_ax (exp, ax, &value2);
+  gen_usual_unary (ax, &value2);
+  if2 = ax_goto (ax, aop_if_goto);
+  go2 = ax_goto (ax, aop_goto);
+  ax_label (ax, if2, ax->len);
+  ax_const_l (ax, 1);
+  end = ax_goto (ax, aop_goto);
+  ax_label (ax, go1, ax->len);
+  ax_label (ax, go2, ax->len);
+  ax_const_l (ax, 0);
+  ax_label (ax, end, ax->len);
+  value->kind = axs_rvalue;
+  value->type = builtin_type (ax->gdbarch)->builtin_int;
+}
+
+void
+logical_or_operation::do_generate_ax (struct expression *exp,
+                                     struct agent_expr *ax,
+                                     struct axs_value *value,
+                                     struct type *cast_type)
+{
+  struct axs_value value1, value2;
+  int if1, if2, end;
+
+  /* Generate the obvious sequence of tests and jumps.  */
+  std::get<0> (m_storage)->generate_ax (exp, ax, &value1);
+  gen_usual_unary (ax, &value1);
+  if1 = ax_goto (ax, aop_if_goto);
+  std::get<1> (m_storage)->generate_ax (exp, ax, &value2);
+  gen_usual_unary (ax, &value2);
+  if2 = ax_goto (ax, aop_if_goto);
+  ax_const_l (ax, 0);
+  end = ax_goto (ax, aop_goto);
+  ax_label (ax, if1, ax->len);
+  ax_label (ax, if2, ax->len);
+  ax_const_l (ax, 1);
+  ax_label (ax, end, ax->len);
+  value->kind = axs_rvalue;
+  value->type = builtin_type (ax->gdbarch)->builtin_int;
+}
+
 }
 
 /* This handles the middle-to-right-side of code generation for binary
index 655e4efa13fdc4acd2c71d7d6e5066e1d7fc734a..44384130f6c12eb0e6f28706d47e45389e1140e1 100644 (file)
@@ -2486,6 +2486,69 @@ multi_subscript_operation::evaluate (struct type *expect_type,
                               gdb::make_array_view (argvec, values.size ()));
 }
 
+value *
+logical_and_operation::evaluate (struct type *expect_type,
+                                struct expression *exp,
+                                enum noside noside)
+{
+  value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+  if (noside == EVAL_SKIP)
+    return eval_skip_value (exp);
+
+  value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp,
+                                                  EVAL_AVOID_SIDE_EFFECTS);
+
+  if (binop_user_defined_p (BINOP_LOGICAL_AND, arg1, arg2))
+    {
+      arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+      return value_x_binop (arg1, arg2, BINOP_LOGICAL_AND, OP_NULL, noside);
+    }
+  else
+    {
+      int tem = value_logical_not (arg1);
+      if (!tem)
+       {
+         arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+         tem = value_logical_not (arg2);
+       }
+      struct type *type = language_bool_type (exp->language_defn,
+                                             exp->gdbarch);
+      return value_from_longest (type, !tem);
+    }
+}
+
+value *
+logical_or_operation::evaluate (struct type *expect_type,
+                               struct expression *exp,
+                               enum noside noside)
+{
+  value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+  if (noside == EVAL_SKIP)
+    return eval_skip_value (exp);
+
+  value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp,
+                                                  EVAL_AVOID_SIDE_EFFECTS);
+
+  if (binop_user_defined_p (BINOP_LOGICAL_OR, arg1, arg2))
+    {
+      arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+      return value_x_binop (arg1, arg2, BINOP_LOGICAL_OR, OP_NULL, noside);
+    }
+  else
+    {
+      int tem = value_logical_not (arg1);
+      if (tem)
+       {
+         arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+         tem = value_logical_not (arg2);
+       }
+
+      struct type *type = language_bool_type (exp->language_defn,
+                                             exp->gdbarch);
+      return value_from_longest (type, !tem);
+    }
+}
+
 }
 
 struct value *
index 6b1a8753b971ac2b2bf5d51c33d166aefa9968c5..7850c457adbae987bf9b70bc09f59ea2358ad76d 100644 (file)
@@ -1982,6 +1982,54 @@ public:
   { return MULTI_SUBSCRIPT; }
 };
 
+/* The "&&" operator.  */
+class logical_and_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return BINOP_LOGICAL_AND; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* The "||" operator.  */
+class logical_or_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return BINOP_LOGICAL_OR; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
 } /* namespace expr */
 
 #endif /* EXPOP_H */