From 9307d17b7a97bd49baf0d877785c43cf203b7cee Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 8 Mar 2021 07:27:57 -0700 Subject: [PATCH] Implement some unary operations 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 * 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 | 11 ++++++++ gdb/ax-gdb.c | 47 +++++++++++++++++++++++++++++++ gdb/eval.c | 8 +++--- gdb/expop.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 4 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 729074bd61d..17281bf5ba4 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2021-03-08 Tom Tromey + + * 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 * ax-gdb.c (comma_operation::do_generate_ax): New method. diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 8d5e4fff903..c87b290397d 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -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"); + } +} + /* Given a single variable and a scope, generate bytecodes to trace diff --git a/gdb/eval.c b/gdb/eval.c index 2d2f881746c..8d75c08541b 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -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) diff --git a/gdb/expop.h b/gdb/expop.h index 2fa5b2f2055..abd914ad574 100644 --- a/gdb/expop.h +++ b/gdb/expop.h @@ -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 +class unop_operation + : public maybe_constant_operation +{ +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 +class usual_ax_unop_operation + : public unop_operation +{ + using unop_operation::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; +using unary_neg_operation = usual_ax_unop_operation; +using unary_complement_operation + = usual_ax_unop_operation; +using unary_logical_not_operation + = usual_ax_unop_operation; + } /* namespace expr */ #endif /* EXPOP_H */ -- 2.30.2