Introduce repeat_operation

This adds class repeat_operation, which implements BINOP_REPEAT.

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

	* expop.h (class repeat_operation): New.
	* eval.c (eval_op_repeat): No longer static.  Remove "op"
	parameter.
	(evaluate_subexp_standard): Update.
	* ax-gdb.c (repeat_operation::do_generate_ax): New method.
This commit is contained in:
Tom Tromey
2021-03-08 07:27:57 -07:00
parent 46916f2bcb
commit d4eff4c122
4 changed files with 81 additions and 3 deletions

View File

@ -1,3 +1,11 @@
2021-03-08 Tom Tromey <tom@tromey.com>
* expop.h (class repeat_operation): New.
* eval.c (eval_op_repeat): No longer static. Remove "op"
parameter.
(evaluate_subexp_standard): Update.
* ax-gdb.c (repeat_operation::do_generate_ax): New method.
2021-03-08 Tom Tromey <tom@tromey.com>
* expop.h (class comparison_operation): New.

View File

@ -2419,6 +2419,56 @@ ternop_cond_operation::do_generate_ax (struct expression *exp,
value->kind = value2.kind;
}
/* Generate code for GDB's magical `repeat' operator.
LVALUE @ INT creates an array INT elements long, and whose elements
have the same type as LVALUE, located in memory so that LVALUE is
its first element. For example, argv[0]@argc gives you the array
of command-line arguments.
Unfortunately, because we have to know the types before we actually
have a value for the expression, we can't implement this perfectly
without changing the type system, having values that occupy two
stack slots, doing weird things with sizeof, etc. So we require
the right operand to be a constant expression. */
void
repeat_operation::do_generate_ax (struct expression *exp,
struct agent_expr *ax,
struct axs_value *value,
struct type *cast_type)
{
struct axs_value value1;
/* We don't want to turn this into an rvalue, so no conversions
here. */
std::get<0> (m_storage)->generate_ax (exp, ax, &value1);
if (value1.kind != axs_lvalue_memory)
error (_("Left operand of `@' must be an object in memory."));
/* Evaluate the length; it had better be a constant. */
if (!std::get<1> (m_storage)->constant_p ())
error (_("Right operand of `@' must be a "
"constant, in agent expressions."));
struct value *v
= std::get<1> (m_storage)->evaluate (nullptr, exp,
EVAL_AVOID_SIDE_EFFECTS);
if (value_type (v)->code () != TYPE_CODE_INT)
error (_("Right operand of `@' must be an integer."));
int length = value_as_long (v);
if (length <= 0)
error (_("Right operand of `@' must be positive."));
/* The top of the stack is already the address of the object, so
all we need to do is frob the type of the lvalue. */
/* FIXME-type-allocation: need a way to free this type when we are
done with it. */
struct type *array
= lookup_array_range_type (value1.type, 0, length - 1);
value->kind = axs_lvalue_memory;
value->type = array;
}
}
/* This handles the middle-to-right-side of code generation for binary

View File

@ -1732,9 +1732,9 @@ eval_op_leq (struct type *expect_type, struct expression *exp,
/* A helper function for BINOP_REPEAT. */
static struct value *
struct value *
eval_op_repeat (struct type *expect_type, struct expression *exp,
enum noside noside,
enum noside noside, enum exp_opcode op,
struct value *arg1, struct value *arg2)
{
if (noside == EVAL_SKIP)
@ -2946,7 +2946,7 @@ evaluate_subexp_standard (struct type *expect_type,
case BINOP_REPEAT:
arg1 = evaluate_subexp (nullptr, exp, pos, noside);
arg2 = evaluate_subexp (nullptr, exp, pos, noside);
return eval_op_repeat (expect_type, exp, noside, arg1, arg2);
return eval_op_repeat (expect_type, exp, noside, op, arg1, arg2);
case BINOP_COMMA:
evaluate_subexp (nullptr, exp, pos, noside);

View File

@ -135,6 +135,11 @@ extern struct value *eval_op_leq (struct type *expect_type,
enum noside noside, enum exp_opcode op,
struct value *arg1,
struct value *arg2);
extern struct value *eval_op_repeat (struct type *expect_type,
struct expression *exp,
enum noside noside, enum exp_opcode op,
struct value *arg1,
struct value *arg2);
namespace expr
{
@ -1188,6 +1193,21 @@ using gtr_operation = comparison_operation<BINOP_GTR, eval_op_gtr>;
using geq_operation = comparison_operation<BINOP_GEQ, eval_op_geq>;
using leq_operation = comparison_operation<BINOP_LEQ, eval_op_leq>;
/* Implement the GDB '@' repeat operator. */
class repeat_operation
: public binop_operation<BINOP_REPEAT, eval_op_repeat>
{
using binop_operation<BINOP_REPEAT, eval_op_repeat>::binop_operation;
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 */