Remove union exp_element
This removes union exp_element functions that either create such elements or walk them. struct expression no longer holds exp_elements. A couple of language_defn methods are also removed, as they are obsolete. Note that this patch also removes the print_expression code. The only in-tree caller of this was from dump_prefix_expression, which is only called when expression debugging is enabled. Implementing this would involve a fair amount of code, and it seems to me that prefix dumping is preferable anyway, as it is unambiguous. So, I have not reimplemented this feature. gdb/ChangeLog 2021-03-08 Tom Tromey <tom@tromey.com> * value.h (evaluate_subexp_with_coercion): Don't declare. * parse.c (exp_descriptor_standard): Remove. (expr_builder::expr_builder, expr_builder::release): Update. (expression::expression): Remove size_t parameter. (expression::~expression): Simplify. (expression::resize): Remove. (write_exp_elt, write_exp_elt_opcode, write_exp_elt_sym) (write_exp_elt_msym, write_exp_elt_block, write_exp_elt_objfile) (write_exp_elt_longcst, write_exp_elt_floatcst) (write_exp_elt_type, write_exp_elt_intern, write_exp_string) (write_exp_string_vector, write_exp_bitstring): Remove. * p-lang.h (class pascal_language) <opcode_print_table, op_print_tab>: Remove. * p-lang.c (pascal_language::op_print_tab): Remove. * opencl-lang.c (class opencl_language) <opcode_print_table>: Remove. * objc-lang.c (objc_op_print_tab): Remove. (class objc_language) <opcode_print_table>: Remove. * m2-lang.h (class m2_language) <opcode_print_table, op_print_tab>: Remove. * m2-lang.c (m2_language::op_print_tab): Remove. * language.h (struct language_defn) <post_parser, expression_ops, opcode_print_table>: Remove. * language.c (language_defn::expression_ops) (auto_or_unknown_language::opcode_print_table): Remove. * go-lang.h (class go_language) <opcode_print_table, op_print_tab>: Remove. * go-lang.c (go_language::op_print_tab): Remove. * f-lang.h (class f_language) <opcode_print_table>: Remove <op_print_tab>: Remove. * f-lang.c (f_language::op_print_tab): Remove. * expression.h (union exp_element): Remove. (struct expression): Remove size_t parameter from constructor. <resize>: Remove. <first_opcode>: Update. <nelts, elts>: Remove. (EXP_ELEM_TO_BYTES, BYTES_TO_EXP_ELEM): Remove. (evaluate_subexp_standard, print_expression, op_string) (dump_raw_expression): Don't declare. * expprint.c (print_expression, print_subexp) (print_subexp_funcall, print_subexp_standard, op_string) (dump_raw_expression, dump_subexp, dump_subexp_body) (dump_subexp_body_funcall, dump_subexp_body_standard): Remove. (dump_prefix_expression): Update. * eval.c (evaluate_subexp): Remove. (evaluate_expression, evaluate_type): Update. (evaluate_subexpression_type): Remove. (fetch_subexp_value): Remove "pc" parameter. Update. (extract_field_op, evaluate_struct_tuple, evaluate_funcall) (evaluate_subexp_standard, evaluate_subexp_for_address) (evaluate_subexp_with_coercion, evaluate_subexp_for_sizeof) (evaluate_subexp_for_cast): Remove. (parse_and_eval_type): Update. * dtrace-probe.c (dtrace_probe::compile_to_ax): Update. * d-lang.c (d_op_print_tab): Remove. (class d_language) <opcode_print_table>: Remove. * c-lang.h (c_op_print_tab): Don't declare. * c-lang.c (c_op_print_tab): Remove. (class c_language, class cplus_language, class asm_language, class minimal_language) <opcode_print_table>: Remove. * breakpoint.c (update_watchpoint, watchpoint_check) (watchpoint_exp_is_const, watch_command_1): Update. * ax-gdb.h (union exp_element): Don't declare. * ax-gdb.c (const_var_ref, const_expr, maybe_const_expr) (gen_repeat, gen_sizeof, gen_expr_for_cast, gen_expr) (gen_expr_binop_rest): Remove. (gen_trace_for_expr, gen_eval_for_expr, gen_printf): Update. * ada-lang.c (ada_op_print_tab): Remove. (class ada_language) <post_parser, opcode_print_table>: Remove.
This commit is contained in:
parent
f2a98603a8
commit
1eaebe02cf
33 changed files with 147 additions and 5316 deletions
|
@ -1,3 +1,75 @@
|
|||
2021-03-08 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* value.h (evaluate_subexp_with_coercion): Don't declare.
|
||||
* parse.c (exp_descriptor_standard): Remove.
|
||||
(expr_builder::expr_builder, expr_builder::release): Update.
|
||||
(expression::expression): Remove size_t parameter.
|
||||
(expression::~expression): Simplify.
|
||||
(expression::resize): Remove.
|
||||
(write_exp_elt, write_exp_elt_opcode, write_exp_elt_sym)
|
||||
(write_exp_elt_msym, write_exp_elt_block, write_exp_elt_objfile)
|
||||
(write_exp_elt_longcst, write_exp_elt_floatcst)
|
||||
(write_exp_elt_type, write_exp_elt_intern, write_exp_string)
|
||||
(write_exp_string_vector, write_exp_bitstring): Remove.
|
||||
* p-lang.h (class pascal_language) <opcode_print_table,
|
||||
op_print_tab>: Remove.
|
||||
* p-lang.c (pascal_language::op_print_tab): Remove.
|
||||
* opencl-lang.c (class opencl_language) <opcode_print_table>:
|
||||
Remove.
|
||||
* objc-lang.c (objc_op_print_tab): Remove.
|
||||
(class objc_language) <opcode_print_table>: Remove.
|
||||
* m2-lang.h (class m2_language) <opcode_print_table,
|
||||
op_print_tab>: Remove.
|
||||
* m2-lang.c (m2_language::op_print_tab): Remove.
|
||||
* language.h (struct language_defn) <post_parser, expression_ops,
|
||||
opcode_print_table>: Remove.
|
||||
* language.c (language_defn::expression_ops)
|
||||
(auto_or_unknown_language::opcode_print_table): Remove.
|
||||
* go-lang.h (class go_language) <opcode_print_table,
|
||||
op_print_tab>: Remove.
|
||||
* go-lang.c (go_language::op_print_tab): Remove.
|
||||
* f-lang.h (class f_language) <opcode_print_table>: Remove
|
||||
<op_print_tab>: Remove.
|
||||
* f-lang.c (f_language::op_print_tab): Remove.
|
||||
* expression.h (union exp_element): Remove.
|
||||
(struct expression): Remove size_t parameter from constructor.
|
||||
<resize>: Remove.
|
||||
<first_opcode>: Update.
|
||||
<nelts, elts>: Remove.
|
||||
(EXP_ELEM_TO_BYTES, BYTES_TO_EXP_ELEM): Remove.
|
||||
(evaluate_subexp_standard, print_expression, op_string)
|
||||
(dump_raw_expression): Don't declare.
|
||||
* expprint.c (print_expression, print_subexp)
|
||||
(print_subexp_funcall, print_subexp_standard, op_string)
|
||||
(dump_raw_expression, dump_subexp, dump_subexp_body)
|
||||
(dump_subexp_body_funcall, dump_subexp_body_standard): Remove.
|
||||
(dump_prefix_expression): Update.
|
||||
* eval.c (evaluate_subexp): Remove.
|
||||
(evaluate_expression, evaluate_type): Update.
|
||||
(evaluate_subexpression_type): Remove.
|
||||
(fetch_subexp_value): Remove "pc" parameter. Update.
|
||||
(extract_field_op, evaluate_struct_tuple, evaluate_funcall)
|
||||
(evaluate_subexp_standard, evaluate_subexp_for_address)
|
||||
(evaluate_subexp_with_coercion, evaluate_subexp_for_sizeof)
|
||||
(evaluate_subexp_for_cast): Remove.
|
||||
(parse_and_eval_type): Update.
|
||||
* dtrace-probe.c (dtrace_probe::compile_to_ax): Update.
|
||||
* d-lang.c (d_op_print_tab): Remove.
|
||||
(class d_language) <opcode_print_table>: Remove.
|
||||
* c-lang.h (c_op_print_tab): Don't declare.
|
||||
* c-lang.c (c_op_print_tab): Remove.
|
||||
(class c_language, class cplus_language, class asm_language, class
|
||||
minimal_language) <opcode_print_table>: Remove.
|
||||
* breakpoint.c (update_watchpoint, watchpoint_check)
|
||||
(watchpoint_exp_is_const, watch_command_1): Update.
|
||||
* ax-gdb.h (union exp_element): Don't declare.
|
||||
* ax-gdb.c (const_var_ref, const_expr, maybe_const_expr)
|
||||
(gen_repeat, gen_sizeof, gen_expr_for_cast, gen_expr)
|
||||
(gen_expr_binop_rest): Remove.
|
||||
(gen_trace_for_expr, gen_eval_for_expr, gen_printf): Update.
|
||||
* ada-lang.c (ada_op_print_tab): Remove.
|
||||
(class ada_language) <post_parser, opcode_print_table>: Remove.
|
||||
|
||||
2021-03-08 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* go-lang.c (go_language::expression_ops): Don't declare.
|
||||
|
|
|
@ -12652,43 +12652,6 @@ info_exceptions_command (const char *regexp, int from_tty)
|
|||
printf_filtered ("%s: %s\n", info.name, paddress (gdbarch, info.addr));
|
||||
}
|
||||
|
||||
/* Table mapping opcodes into strings for printing operators
|
||||
and precedences of the operators. */
|
||||
|
||||
static const struct op_print ada_op_print_tab[] = {
|
||||
{":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"or else", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
|
||||
{"and then", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
|
||||
{"or", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
|
||||
{"xor", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
|
||||
{"and", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
|
||||
{"=", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{"/=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{">>", BINOP_RSH, PREC_SHIFT, 0},
|
||||
{"<<", BINOP_LSH, PREC_SHIFT, 0},
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"&", BINOP_CONCAT, PREC_ADD, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"rem", BINOP_REM, PREC_MUL, 0},
|
||||
{"mod", BINOP_MOD, PREC_MUL, 0},
|
||||
{"**", BINOP_EXP, PREC_REPEAT, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"+", UNOP_PLUS, PREC_PREFIX, 0},
|
||||
{"not ", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"not ", UNOP_COMPLEMENT, PREC_PREFIX, 0},
|
||||
{"abs ", UNOP_ABS, PREC_PREFIX, 0},
|
||||
{".all", UNOP_IND, PREC_SUFFIX, 1},
|
||||
{"'access", UNOP_ADDR, PREC_SUFFIX, 1},
|
||||
{"'size", OP_ATR_SIZE, PREC_SUFFIX, 1},
|
||||
{NULL, OP_NULL, PREC_SUFFIX, 0}
|
||||
};
|
||||
|
||||
/* Language vector */
|
||||
|
||||
|
@ -13275,22 +13238,6 @@ public:
|
|||
return ada_parse (ps);
|
||||
}
|
||||
|
||||
/* See language.h.
|
||||
|
||||
Same as evaluate_type (*EXP), but resolves ambiguous symbol references
|
||||
(marked by OP_VAR_VALUE nodes in which the symbol has an undefined
|
||||
namespace) and converts operators that are user-defined into
|
||||
appropriate function calls. If CONTEXT_TYPE is non-null, it provides
|
||||
a preferred result type [at the moment, only type void has any
|
||||
effect---causing procedures to be preferred over functions in calls].
|
||||
A null CONTEXT_TYPE indicates that a non-void return type is
|
||||
preferred. May change (expand) *EXP. */
|
||||
|
||||
void post_parser (expression_up *expp, struct parser_state *ps)
|
||||
const override
|
||||
{
|
||||
}
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
void emitchar (int ch, struct type *chtype,
|
||||
|
@ -13353,11 +13300,6 @@ public:
|
|||
const struct lang_varobj_ops *varobj_ops () const override
|
||||
{ return &ada_varobj_ops; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return ada_op_print_tab; }
|
||||
|
||||
protected:
|
||||
/* See language.h. */
|
||||
|
||||
|
|
735
gdb/ax-gdb.c
735
gdb/ax-gdb.c
|
@ -70,14 +70,9 @@
|
|||
/* Prototypes for local functions. */
|
||||
|
||||
/* There's a standard order to the arguments of these functions:
|
||||
union exp_element ** --- pointer into expression
|
||||
struct agent_expr * --- agent expression buffer to generate code into
|
||||
struct axs_value * --- describes value left on top of stack */
|
||||
|
||||
static struct value *const_var_ref (struct symbol *var);
|
||||
static struct value *const_expr (union exp_element **pc);
|
||||
static struct value *maybe_const_expr (union exp_element **pc);
|
||||
|
||||
static void gen_traced_pop (struct agent_expr *, struct axs_value *);
|
||||
|
||||
static void gen_sign_extend (struct agent_expr *, struct type *);
|
||||
|
@ -148,123 +143,13 @@ static void gen_struct_ref (struct agent_expr *ax,
|
|||
const char *operand_name);
|
||||
static void gen_static_field (struct agent_expr *ax, struct axs_value *value,
|
||||
struct type *type, int fieldno);
|
||||
static void gen_repeat (struct expression *exp, union exp_element **pc,
|
||||
struct agent_expr *ax, struct axs_value *value);
|
||||
static void gen_sizeof (struct expression *exp, union exp_element **pc,
|
||||
struct agent_expr *ax, struct axs_value *value,
|
||||
struct type *size_type);
|
||||
static void gen_expr_binop_rest (struct expression *exp,
|
||||
enum exp_opcode op, union exp_element **pc,
|
||||
struct agent_expr *ax,
|
||||
struct axs_value *value,
|
||||
struct axs_value *value1,
|
||||
struct axs_value *value2);
|
||||
static void gen_expr_binop_rest (struct expression *exp,
|
||||
enum exp_opcode op,
|
||||
struct agent_expr *ax,
|
||||
struct axs_value *value,
|
||||
struct axs_value *value1,
|
||||
struct axs_value *value2);
|
||||
|
||||
|
||||
/* Detecting constant expressions. */
|
||||
|
||||
/* If the variable reference at *PC is a constant, return its value.
|
||||
Otherwise, return zero.
|
||||
|
||||
Hey, Wally! How can a variable reference be a constant?
|
||||
|
||||
Well, Beav, this function really handles the OP_VAR_VALUE operator,
|
||||
not specifically variable references. GDB uses OP_VAR_VALUE to
|
||||
refer to any kind of symbolic reference: function names, enum
|
||||
elements, and goto labels are all handled through the OP_VAR_VALUE
|
||||
operator, even though they're constants. It makes sense given the
|
||||
situation.
|
||||
|
||||
Gee, Wally, don'cha wonder sometimes if data representations that
|
||||
subvert commonly accepted definitions of terms in favor of heavily
|
||||
context-specific interpretations are really just a tool of the
|
||||
programming hegemony to preserve their power and exclude the
|
||||
proletariat? */
|
||||
|
||||
static struct value *
|
||||
const_var_ref (struct symbol *var)
|
||||
{
|
||||
struct type *type = SYMBOL_TYPE (var);
|
||||
|
||||
switch (SYMBOL_CLASS (var))
|
||||
{
|
||||
case LOC_CONST:
|
||||
return value_from_longest (type, (LONGEST) SYMBOL_VALUE (var));
|
||||
|
||||
case LOC_LABEL:
|
||||
return value_from_pointer (type, (CORE_ADDR) SYMBOL_VALUE_ADDRESS (var));
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If the expression starting at *PC has a constant value, return it.
|
||||
Otherwise, return zero. If we return a value, then *PC will be
|
||||
advanced to the end of it. If we return zero, *PC could be
|
||||
anywhere. */
|
||||
static struct value *
|
||||
const_expr (union exp_element **pc)
|
||||
{
|
||||
enum exp_opcode op = (*pc)->opcode;
|
||||
struct value *v1;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case OP_LONG:
|
||||
{
|
||||
struct type *type = (*pc)[1].type;
|
||||
LONGEST k = (*pc)[2].longconst;
|
||||
|
||||
(*pc) += 4;
|
||||
return value_from_longest (type, k);
|
||||
}
|
||||
|
||||
case OP_VAR_VALUE:
|
||||
{
|
||||
struct value *v = const_var_ref ((*pc)[2].symbol);
|
||||
|
||||
(*pc) += 4;
|
||||
return v;
|
||||
}
|
||||
|
||||
/* We could add more operators in here. */
|
||||
|
||||
case UNOP_NEG:
|
||||
(*pc)++;
|
||||
v1 = const_expr (pc);
|
||||
if (v1)
|
||||
return value_neg (v1);
|
||||
else
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Like const_expr, but guarantee also that *PC is undisturbed if the
|
||||
expression is not constant. */
|
||||
static struct value *
|
||||
maybe_const_expr (union exp_element **pc)
|
||||
{
|
||||
union exp_element *tentative_pc = *pc;
|
||||
struct value *v = const_expr (&tentative_pc);
|
||||
|
||||
/* If we got a value, then update the real PC. */
|
||||
if (v)
|
||||
*pc = tentative_pc;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/* Generating bytecode from GDB expressions: general assumptions */
|
||||
|
@ -1691,592 +1576,8 @@ gen_aggregate_elt_ref (struct agent_expr *ax, struct axs_value *value,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
static void
|
||||
gen_repeat (struct expression *exp, union exp_element **pc,
|
||||
struct agent_expr *ax, struct axs_value *value)
|
||||
{
|
||||
struct axs_value value1;
|
||||
|
||||
/* We don't want to turn this into an rvalue, so no conversions
|
||||
here. */
|
||||
gen_expr (exp, pc, 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. */
|
||||
{
|
||||
struct value *v = const_expr (pc);
|
||||
int length;
|
||||
|
||||
if (!v)
|
||||
error (_("Right operand of `@' must be a "
|
||||
"constant, in agent expressions."));
|
||||
if (value_type (v)->code () != TYPE_CODE_INT)
|
||||
error (_("Right operand of `@' must be an integer."));
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Emit code for the `sizeof' operator.
|
||||
*PC should point at the start of the operand expression; we advance it
|
||||
to the first instruction after the operand. */
|
||||
static void
|
||||
gen_sizeof (struct expression *exp, union exp_element **pc,
|
||||
struct agent_expr *ax, struct axs_value *value,
|
||||
struct type *size_type)
|
||||
{
|
||||
/* We don't care about the value of the operand expression; we only
|
||||
care about its type. However, in the current arrangement, the
|
||||
only way to find an expression's type is to generate code for it.
|
||||
So we generate code for the operand, and then throw it away,
|
||||
replacing it with code that simply pushes its size. */
|
||||
int start = ax->len;
|
||||
|
||||
gen_expr (exp, pc, ax, value);
|
||||
|
||||
/* Throw away the code we just generated. */
|
||||
ax->len = start;
|
||||
|
||||
ax_const_l (ax, TYPE_LENGTH (value->type));
|
||||
value->kind = axs_rvalue;
|
||||
value->type = size_type;
|
||||
}
|
||||
|
||||
|
||||
/* Generate bytecode for a cast to TO_TYPE. Advance *PC over the
|
||||
subexpression. */
|
||||
|
||||
static void
|
||||
gen_expr_for_cast (struct expression *exp, union exp_element **pc,
|
||||
struct agent_expr *ax, struct axs_value *value,
|
||||
struct type *to_type)
|
||||
{
|
||||
enum exp_opcode op = (*pc)[0].opcode;
|
||||
|
||||
/* Don't let symbols be handled with gen_expr because that throws an
|
||||
"unknown type" error for no-debug data symbols. Instead, we want
|
||||
the cast to reinterpret such symbols. */
|
||||
if (op == OP_VAR_MSYM_VALUE || op == OP_VAR_VALUE)
|
||||
{
|
||||
if (op == OP_VAR_VALUE)
|
||||
{
|
||||
gen_var_ref (ax, value, (*pc)[2].symbol);
|
||||
|
||||
if (value->optimized_out)
|
||||
error (_("`%s' has been optimized out, cannot use"),
|
||||
(*pc)[2].symbol->print_name ());
|
||||
}
|
||||
else
|
||||
gen_msym_var_ref (ax, value, (*pc)[2].msymbol, (*pc)[1].objfile);
|
||||
if (value->type->code () == TYPE_CODE_ERROR)
|
||||
value->type = to_type;
|
||||
(*pc) += 4;
|
||||
}
|
||||
else
|
||||
gen_expr (exp, pc, ax, value);
|
||||
gen_cast (ax, value, to_type);
|
||||
}
|
||||
|
||||
/* Generating bytecode from GDB expressions: general recursive thingy */
|
||||
|
||||
/* XXX: i18n */
|
||||
/* A gen_expr function written by a Gen-X'er guy.
|
||||
Append code for the subexpression of EXPR starting at *POS_P to AX. */
|
||||
void
|
||||
gen_expr (struct expression *exp, union exp_element **pc,
|
||||
struct agent_expr *ax, struct axs_value *value)
|
||||
{
|
||||
/* Used to hold the descriptions of operand expressions. */
|
||||
struct axs_value value1, value2, value3;
|
||||
enum exp_opcode op = (*pc)[0].opcode, op2;
|
||||
int if1, go1, if2, go2, end;
|
||||
struct type *int_type = builtin_type (ax->gdbarch)->builtin_int;
|
||||
|
||||
/* If we're looking at a constant expression, just push its value. */
|
||||
{
|
||||
struct value *v = maybe_const_expr (pc);
|
||||
|
||||
if (v)
|
||||
{
|
||||
ax_const_l (ax, value_as_long (v));
|
||||
value->kind = axs_rvalue;
|
||||
value->type = check_typedef (value_type (v));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, go ahead and generate code for it. */
|
||||
switch (op)
|
||||
{
|
||||
/* Binary arithmetic operators. */
|
||||
case BINOP_ADD:
|
||||
case BINOP_SUB:
|
||||
case BINOP_MUL:
|
||||
case BINOP_DIV:
|
||||
case BINOP_REM:
|
||||
case BINOP_LSH:
|
||||
case BINOP_RSH:
|
||||
case BINOP_SUBSCRIPT:
|
||||
case BINOP_BITWISE_AND:
|
||||
case BINOP_BITWISE_IOR:
|
||||
case BINOP_BITWISE_XOR:
|
||||
case BINOP_EQUAL:
|
||||
case BINOP_NOTEQUAL:
|
||||
case BINOP_LESS:
|
||||
case BINOP_GTR:
|
||||
case BINOP_LEQ:
|
||||
case BINOP_GEQ:
|
||||
(*pc)++;
|
||||
gen_expr (exp, pc, ax, &value1);
|
||||
gen_usual_unary (ax, &value1);
|
||||
gen_expr_binop_rest (exp, op, pc, ax, value, &value1, &value2);
|
||||
break;
|
||||
|
||||
case BINOP_LOGICAL_AND:
|
||||
(*pc)++;
|
||||
/* Generate the obvious sequence of tests and jumps. */
|
||||
gen_expr (exp, pc, 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);
|
||||
gen_expr (exp, pc, 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 = int_type;
|
||||
break;
|
||||
|
||||
case BINOP_LOGICAL_OR:
|
||||
(*pc)++;
|
||||
/* Generate the obvious sequence of tests and jumps. */
|
||||
gen_expr (exp, pc, ax, &value1);
|
||||
gen_usual_unary (ax, &value1);
|
||||
if1 = ax_goto (ax, aop_if_goto);
|
||||
gen_expr (exp, pc, 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 = int_type;
|
||||
break;
|
||||
|
||||
case TERNOP_COND:
|
||||
(*pc)++;
|
||||
gen_expr (exp, pc, ax, &value1);
|
||||
gen_usual_unary (ax, &value1);
|
||||
/* For (A ? B : C), it's easiest to generate subexpression
|
||||
bytecodes in order, but if_goto jumps on true, so we invert
|
||||
the sense of A. Then we can do B by dropping through, and
|
||||
jump to do C. */
|
||||
gen_logical_not (ax, &value1, int_type);
|
||||
if1 = ax_goto (ax, aop_if_goto);
|
||||
gen_expr (exp, pc, ax, &value2);
|
||||
gen_usual_unary (ax, &value2);
|
||||
end = ax_goto (ax, aop_goto);
|
||||
ax_label (ax, if1, ax->len);
|
||||
gen_expr (exp, pc, ax, &value3);
|
||||
gen_usual_unary (ax, &value3);
|
||||
ax_label (ax, end, ax->len);
|
||||
/* This is arbitrary - what if B and C are incompatible types? */
|
||||
value->type = value2.type;
|
||||
value->kind = value2.kind;
|
||||
break;
|
||||
|
||||
case BINOP_ASSIGN:
|
||||
(*pc)++;
|
||||
if ((*pc)[0].opcode == OP_INTERNALVAR)
|
||||
{
|
||||
const char *name = internalvar_name ((*pc)[1].internalvar);
|
||||
struct trace_state_variable *tsv;
|
||||
|
||||
(*pc) += 3;
|
||||
gen_expr (exp, pc, ax, value);
|
||||
tsv = find_trace_state_variable (name);
|
||||
if (tsv)
|
||||
{
|
||||
ax_tsv (ax, aop_setv, tsv->number);
|
||||
if (ax->tracing)
|
||||
ax_tsv (ax, aop_tracev, tsv->number);
|
||||
}
|
||||
else
|
||||
error (_("$%s is not a trace state variable, "
|
||||
"may not assign to it"), name);
|
||||
}
|
||||
else
|
||||
error (_("May only assign to trace state variables"));
|
||||
break;
|
||||
|
||||
case BINOP_ASSIGN_MODIFY:
|
||||
(*pc)++;
|
||||
op2 = (*pc)[0].opcode;
|
||||
(*pc)++;
|
||||
(*pc)++;
|
||||
if ((*pc)[0].opcode == OP_INTERNALVAR)
|
||||
{
|
||||
const char *name = internalvar_name ((*pc)[1].internalvar);
|
||||
struct trace_state_variable *tsv;
|
||||
|
||||
(*pc) += 3;
|
||||
tsv = find_trace_state_variable (name);
|
||||
if (tsv)
|
||||
{
|
||||
/* The tsv will be the left half of the binary operation. */
|
||||
ax_tsv (ax, aop_getv, tsv->number);
|
||||
if (ax->tracing)
|
||||
ax_tsv (ax, aop_tracev, tsv->number);
|
||||
/* Trace state variables are always 64-bit integers. */
|
||||
value1.kind = axs_rvalue;
|
||||
value1.type = builtin_type (ax->gdbarch)->builtin_long_long;
|
||||
/* Now do right half of expression. */
|
||||
gen_expr_binop_rest (exp, op2, pc, ax, value, &value1, &value2);
|
||||
/* We have a result of the binary op, set the tsv. */
|
||||
ax_tsv (ax, aop_setv, tsv->number);
|
||||
if (ax->tracing)
|
||||
ax_tsv (ax, aop_tracev, tsv->number);
|
||||
}
|
||||
else
|
||||
error (_("$%s is not a trace state variable, "
|
||||
"may not assign to it"), name);
|
||||
}
|
||||
else
|
||||
error (_("May only assign to trace state variables"));
|
||||
break;
|
||||
|
||||
/* Note that we need to be a little subtle about generating code
|
||||
for comma. In C, we can do some optimizations here because
|
||||
we know the left operand is only being evaluated for effect.
|
||||
However, if the tracing kludge is in effect, then we always
|
||||
need to evaluate the left hand side fully, so that all the
|
||||
variables it mentions get traced. */
|
||||
case BINOP_COMMA:
|
||||
(*pc)++;
|
||||
gen_expr (exp, pc, ax, &value1);
|
||||
/* Don't just dispose of the left operand. We might be tracing,
|
||||
in which case we want to emit code to trace it if it's an
|
||||
lvalue. */
|
||||
gen_traced_pop (ax, &value1);
|
||||
gen_expr (exp, pc, ax, value);
|
||||
/* It's the consumer's responsibility to trace the right operand. */
|
||||
break;
|
||||
|
||||
case OP_LONG: /* some integer constant */
|
||||
{
|
||||
struct type *type = (*pc)[1].type;
|
||||
LONGEST k = (*pc)[2].longconst;
|
||||
|
||||
(*pc) += 4;
|
||||
gen_int_literal (ax, value, k, type);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_VAR_VALUE:
|
||||
gen_var_ref (ax, value, (*pc)[2].symbol);
|
||||
|
||||
if (value->optimized_out)
|
||||
error (_("`%s' has been optimized out, cannot use"),
|
||||
(*pc)[2].symbol->print_name ());
|
||||
|
||||
if (value->type->code () == TYPE_CODE_ERROR)
|
||||
error_unknown_type ((*pc)[2].symbol->print_name ());
|
||||
|
||||
(*pc) += 4;
|
||||
break;
|
||||
|
||||
case OP_VAR_MSYM_VALUE:
|
||||
gen_msym_var_ref (ax, value, (*pc)[2].msymbol, (*pc)[1].objfile);
|
||||
|
||||
if (value->type->code () == TYPE_CODE_ERROR)
|
||||
error_unknown_type ((*pc)[2].msymbol->linkage_name ());
|
||||
|
||||
(*pc) += 4;
|
||||
break;
|
||||
|
||||
case OP_REGISTER:
|
||||
{
|
||||
const char *name = &(*pc)[2].string;
|
||||
int reg;
|
||||
|
||||
(*pc) += 4 + BYTES_TO_EXP_ELEM ((*pc)[1].longconst + 1);
|
||||
reg = user_reg_map_name_to_regnum (ax->gdbarch, name, strlen (name));
|
||||
if (reg == -1)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("Register $%s not available"), name);
|
||||
/* No support for tracing user registers yet. */
|
||||
if (reg >= gdbarch_num_cooked_regs (ax->gdbarch))
|
||||
error (_("'%s' is a user-register; "
|
||||
"GDB cannot yet trace user-register contents."),
|
||||
name);
|
||||
value->kind = axs_lvalue_register;
|
||||
value->u.reg = reg;
|
||||
value->type = register_type (ax->gdbarch, reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_INTERNALVAR:
|
||||
{
|
||||
struct internalvar *var = (*pc)[1].internalvar;
|
||||
const char *name = internalvar_name (var);
|
||||
struct trace_state_variable *tsv;
|
||||
|
||||
(*pc) += 3;
|
||||
tsv = find_trace_state_variable (name);
|
||||
if (tsv)
|
||||
{
|
||||
ax_tsv (ax, aop_getv, tsv->number);
|
||||
if (ax->tracing)
|
||||
ax_tsv (ax, aop_tracev, tsv->number);
|
||||
/* Trace state variables are always 64-bit integers. */
|
||||
value->kind = axs_rvalue;
|
||||
value->type = builtin_type (ax->gdbarch)->builtin_long_long;
|
||||
}
|
||||
else if (! compile_internalvar_to_ax (var, ax, value))
|
||||
error (_("$%s is not a trace state variable; GDB agent "
|
||||
"expressions cannot use convenience variables."), name);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Weirdo operator: see comments for gen_repeat for details. */
|
||||
case BINOP_REPEAT:
|
||||
/* Note that gen_repeat handles its own argument evaluation. */
|
||||
(*pc)++;
|
||||
gen_repeat (exp, pc, ax, value);
|
||||
break;
|
||||
|
||||
case UNOP_CAST:
|
||||
{
|
||||
struct type *type = (*pc)[1].type;
|
||||
|
||||
(*pc) += 3;
|
||||
gen_expr_for_cast (exp, pc, ax, value, type);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNOP_CAST_TYPE:
|
||||
{
|
||||
int offset;
|
||||
struct value *val;
|
||||
struct type *type;
|
||||
|
||||
++*pc;
|
||||
offset = *pc - exp->elts;
|
||||
val = evaluate_subexp (NULL, exp, &offset, EVAL_AVOID_SIDE_EFFECTS);
|
||||
type = value_type (val);
|
||||
*pc = &exp->elts[offset];
|
||||
gen_expr_for_cast (exp, pc, ax, value, type);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNOP_MEMVAL:
|
||||
{
|
||||
struct type *type = check_typedef ((*pc)[1].type);
|
||||
|
||||
(*pc) += 3;
|
||||
gen_expr (exp, pc, ax, value);
|
||||
|
||||
/* If we have an axs_rvalue or an axs_lvalue_memory, then we
|
||||
already have the right value on the stack. For
|
||||
axs_lvalue_register, we must convert. */
|
||||
if (value->kind == axs_lvalue_register)
|
||||
require_rvalue (ax, value);
|
||||
|
||||
value->type = type;
|
||||
value->kind = axs_lvalue_memory;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNOP_MEMVAL_TYPE:
|
||||
{
|
||||
int offset;
|
||||
struct value *val;
|
||||
struct type *type;
|
||||
|
||||
++*pc;
|
||||
offset = *pc - exp->elts;
|
||||
val = evaluate_subexp (NULL, exp, &offset, EVAL_AVOID_SIDE_EFFECTS);
|
||||
type = value_type (val);
|
||||
*pc = &exp->elts[offset];
|
||||
|
||||
gen_expr (exp, pc, ax, value);
|
||||
|
||||
/* If we have an axs_rvalue or an axs_lvalue_memory, then we
|
||||
already have the right value on the stack. For
|
||||
axs_lvalue_register, we must convert. */
|
||||
if (value->kind == axs_lvalue_register)
|
||||
require_rvalue (ax, value);
|
||||
|
||||
value->type = type;
|
||||
value->kind = axs_lvalue_memory;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNOP_PLUS:
|
||||
(*pc)++;
|
||||
/* + FOO is equivalent to 0 + FOO, which can be optimized. */
|
||||
gen_expr (exp, pc, ax, value);
|
||||
gen_usual_unary (ax, value);
|
||||
break;
|
||||
|
||||
case UNOP_NEG:
|
||||
(*pc)++;
|
||||
/* -FOO is equivalent to 0 - FOO. */
|
||||
gen_int_literal (ax, &value1, 0,
|
||||
builtin_type (ax->gdbarch)->builtin_int);
|
||||
gen_usual_unary (ax, &value1); /* shouldn't do much */
|
||||
gen_expr (exp, pc, 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_LOGICAL_NOT:
|
||||
(*pc)++;
|
||||
gen_expr (exp, pc, ax, value);
|
||||
gen_usual_unary (ax, value);
|
||||
gen_logical_not (ax, value, int_type);
|
||||
break;
|
||||
|
||||
case UNOP_COMPLEMENT:
|
||||
(*pc)++;
|
||||
gen_expr (exp, pc, ax, value);
|
||||
gen_usual_unary (ax, value);
|
||||
gen_integral_promotions (ax, value);
|
||||
gen_complement (ax, value);
|
||||
break;
|
||||
|
||||
case UNOP_IND:
|
||||
(*pc)++;
|
||||
gen_expr (exp, pc, ax, value);
|
||||
gen_usual_unary (ax, value);
|
||||
if (!pointer_type (value->type))
|
||||
error (_("Argument of unary `*' is not a pointer."));
|
||||
gen_deref (value);
|
||||
break;
|
||||
|
||||
case UNOP_ADDR:
|
||||
(*pc)++;
|
||||
gen_expr (exp, pc, ax, value);
|
||||
gen_address_of (value);
|
||||
break;
|
||||
|
||||
case UNOP_SIZEOF:
|
||||
(*pc)++;
|
||||
/* Notice that gen_sizeof handles its own operand, unlike most
|
||||
of the other unary operator functions. This is because we
|
||||
have to throw away the code we generate. */
|
||||
gen_sizeof (exp, pc, ax, value,
|
||||
builtin_type (ax->gdbarch)->builtin_int);
|
||||
break;
|
||||
|
||||
case STRUCTOP_STRUCT:
|
||||
case STRUCTOP_PTR:
|
||||
{
|
||||
int length = (*pc)[1].longconst;
|
||||
const char *name = &(*pc)[2].string;
|
||||
|
||||
(*pc) += 4 + BYTES_TO_EXP_ELEM (length + 1);
|
||||
gen_expr (exp, pc, ax, value);
|
||||
if (op == STRUCTOP_STRUCT)
|
||||
gen_struct_ref (ax, value, name, ".", "structure or union");
|
||||
else if (op == STRUCTOP_PTR)
|
||||
gen_struct_ref (ax, value, name, "->",
|
||||
"pointer to a structure or union");
|
||||
else
|
||||
/* If this `if' chain doesn't handle it, then the case list
|
||||
shouldn't mention it, and we shouldn't be here. */
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("gen_expr: unhandled struct case"));
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_THIS:
|
||||
{
|
||||
struct symbol *sym, *func;
|
||||
const struct block *b;
|
||||
const struct language_defn *lang;
|
||||
|
||||
b = block_for_pc (ax->scope);
|
||||
func = block_linkage_function (b);
|
||||
lang = language_def (func->language ());
|
||||
|
||||
sym = lookup_language_this (lang, b).symbol;
|
||||
if (!sym)
|
||||
error (_("no `%s' found"), lang->name_of_this ());
|
||||
|
||||
gen_var_ref (ax, value, sym);
|
||||
|
||||
if (value->optimized_out)
|
||||
error (_("`%s' has been optimized out, cannot use"),
|
||||
sym->print_name ());
|
||||
|
||||
(*pc) += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_SCOPE:
|
||||
{
|
||||
struct type *type = (*pc)[1].type;
|
||||
int length = longest_to_int ((*pc)[2].longconst);
|
||||
const char *name = &(*pc)[3].string;
|
||||
int found;
|
||||
|
||||
found = gen_aggregate_elt_ref (ax, value, type, name);
|
||||
if (!found)
|
||||
error (_("There is no field named %s"), name);
|
||||
(*pc) += 5 + BYTES_TO_EXP_ELEM (length + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_TYPE:
|
||||
case OP_TYPEOF:
|
||||
case OP_DECLTYPE:
|
||||
error (_("Attempt to use a type name as an expression."));
|
||||
|
||||
default:
|
||||
error (_("Unsupported operator %s (%d) in expression."),
|
||||
op_name (op), op);
|
||||
}
|
||||
}
|
||||
|
||||
namespace expr
|
||||
{
|
||||
|
||||
|
@ -2901,19 +2202,6 @@ gen_expr_binop_rest (struct expression *exp,
|
|||
}
|
||||
}
|
||||
|
||||
/* Variant of gen_expr_binop_rest that first generates the
|
||||
right-hand-side. */
|
||||
|
||||
static void
|
||||
gen_expr_binop_rest (struct expression *exp,
|
||||
enum exp_opcode op, union exp_element **pc,
|
||||
struct agent_expr *ax, struct axs_value *value,
|
||||
struct axs_value *value1, struct axs_value *value2)
|
||||
{
|
||||
gen_expr (exp, pc, ax, value2);
|
||||
gen_expr_binop_rest (exp, op, ax, value, value1, value2);
|
||||
}
|
||||
|
||||
/* A helper function that emits a binop based on two operations. */
|
||||
|
||||
void
|
||||
|
@ -3057,17 +2345,12 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr,
|
|||
int trace_string)
|
||||
{
|
||||
agent_expr_up ax (new agent_expr (expr->gdbarch, scope));
|
||||
union exp_element *pc;
|
||||
struct axs_value value;
|
||||
|
||||
pc = expr->elts;
|
||||
ax->tracing = 1;
|
||||
ax->trace_string = trace_string;
|
||||
value.optimized_out = 0;
|
||||
if (expr->op != nullptr)
|
||||
expr->op->generate_ax (expr, ax.get (), &value);
|
||||
else
|
||||
gen_expr (expr, &pc, ax.get (), &value);
|
||||
expr->op->generate_ax (expr, ax.get (), &value);
|
||||
|
||||
/* Make sure we record the final object, and get rid of it. */
|
||||
gen_traced_pop (ax.get (), &value);
|
||||
|
@ -3089,16 +2372,11 @@ agent_expr_up
|
|||
gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
|
||||
{
|
||||
agent_expr_up ax (new agent_expr (expr->gdbarch, scope));
|
||||
union exp_element *pc;
|
||||
struct axs_value value;
|
||||
|
||||
pc = expr->elts;
|
||||
ax->tracing = 0;
|
||||
value.optimized_out = 0;
|
||||
if (expr->op != nullptr)
|
||||
expr->op->generate_ax (expr, ax.get (), &value);
|
||||
else
|
||||
gen_expr (expr, &pc, ax.get (), &value);
|
||||
expr->op->generate_ax (expr, ax.get (), &value);
|
||||
|
||||
require_rvalue (ax.get (), &value);
|
||||
|
||||
|
@ -3140,7 +2418,6 @@ gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch,
|
|||
int nargs, struct expression **exprs)
|
||||
{
|
||||
agent_expr_up ax (new agent_expr (gdbarch, scope));
|
||||
union exp_element *pc;
|
||||
struct axs_value value;
|
||||
int tem;
|
||||
|
||||
|
@ -3152,13 +2429,7 @@ gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch,
|
|||
for (tem = nargs - 1; tem >= 0; --tem)
|
||||
{
|
||||
value.optimized_out = 0;
|
||||
if (exprs[tem]->op != nullptr)
|
||||
exprs[tem]->op->generate_ax (exprs[tem], ax.get (), &value);
|
||||
else
|
||||
{
|
||||
pc = exprs[tem]->elts;
|
||||
gen_expr (exprs[tem], &pc, ax.get (), &value);
|
||||
}
|
||||
exprs[tem]->op->generate_ax (exprs[tem], ax.get (), &value);
|
||||
require_rvalue (ax.get (), &value);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "ax.h" /* For agent_expr_up. */
|
||||
|
||||
struct expression;
|
||||
union exp_element;
|
||||
|
||||
/* Types and enums */
|
||||
|
||||
|
|
118
gdb/breakpoint.c
118
gdb/breakpoint.c
|
@ -1898,12 +1898,11 @@ update_watchpoint (struct watchpoint *b, int reparse)
|
|||
}
|
||||
else if (within_current_scope && b->exp)
|
||||
{
|
||||
int pc = 0;
|
||||
std::vector<value_ref_ptr> val_chain;
|
||||
struct value *v, *result;
|
||||
struct program_space *frame_pspace;
|
||||
|
||||
fetch_subexp_value (b->exp.get (), &pc, b->exp->op.get (), &v, &result,
|
||||
fetch_subexp_value (b->exp.get (), b->exp->op.get (), &v, &result,
|
||||
&val_chain, false);
|
||||
|
||||
/* Avoid setting b->val if it's already set. The meaning of
|
||||
|
@ -5012,7 +5011,6 @@ watchpoint_check (bpstat bs)
|
|||
free_all_values. We can't call free_all_values because we
|
||||
might be in the middle of evaluating a function call. */
|
||||
|
||||
int pc = 0;
|
||||
struct value *mark;
|
||||
struct value *new_val;
|
||||
|
||||
|
@ -5023,7 +5021,7 @@ watchpoint_check (bpstat bs)
|
|||
return WP_VALUE_CHANGED;
|
||||
|
||||
mark = value_mark ();
|
||||
fetch_subexp_value (b->exp.get (), &pc, b->exp->op.get (), &new_val,
|
||||
fetch_subexp_value (b->exp.get (), b->exp->op.get (), &new_val,
|
||||
NULL, NULL, false);
|
||||
|
||||
if (b->val_bitsize != 0)
|
||||
|
@ -10124,112 +10122,7 @@ break_range_command (const char *arg, int from_tty)
|
|||
static bool
|
||||
watchpoint_exp_is_const (const struct expression *exp)
|
||||
{
|
||||
if (exp->op != nullptr)
|
||||
return exp->op->constant_p ();
|
||||
|
||||
int i = exp->nelts;
|
||||
|
||||
while (i > 0)
|
||||
{
|
||||
int oplenp, argsp;
|
||||
|
||||
/* We are only interested in the descriptor of each element. */
|
||||
operator_length (exp, i, &oplenp, &argsp);
|
||||
i -= oplenp;
|
||||
|
||||
switch (exp->elts[i].opcode)
|
||||
{
|
||||
case BINOP_ADD:
|
||||
case BINOP_SUB:
|
||||
case BINOP_MUL:
|
||||
case BINOP_DIV:
|
||||
case BINOP_REM:
|
||||
case BINOP_MOD:
|
||||
case BINOP_LSH:
|
||||
case BINOP_RSH:
|
||||
case BINOP_LOGICAL_AND:
|
||||
case BINOP_LOGICAL_OR:
|
||||
case BINOP_BITWISE_AND:
|
||||
case BINOP_BITWISE_IOR:
|
||||
case BINOP_BITWISE_XOR:
|
||||
case BINOP_EQUAL:
|
||||
case BINOP_NOTEQUAL:
|
||||
case BINOP_LESS:
|
||||
case BINOP_GTR:
|
||||
case BINOP_LEQ:
|
||||
case BINOP_GEQ:
|
||||
case BINOP_REPEAT:
|
||||
case BINOP_COMMA:
|
||||
case BINOP_EXP:
|
||||
case BINOP_MIN:
|
||||
case BINOP_MAX:
|
||||
case BINOP_INTDIV:
|
||||
case BINOP_CONCAT:
|
||||
case TERNOP_COND:
|
||||
case TERNOP_SLICE:
|
||||
|
||||
case OP_LONG:
|
||||
case OP_FLOAT:
|
||||
case OP_LAST:
|
||||
case OP_COMPLEX:
|
||||
case OP_STRING:
|
||||
case OP_ARRAY:
|
||||
case OP_TYPE:
|
||||
case OP_TYPEOF:
|
||||
case OP_DECLTYPE:
|
||||
case OP_TYPEID:
|
||||
case OP_NAME:
|
||||
case OP_OBJC_NSSTRING:
|
||||
|
||||
case UNOP_NEG:
|
||||
case UNOP_LOGICAL_NOT:
|
||||
case UNOP_COMPLEMENT:
|
||||
case UNOP_ADDR:
|
||||
case UNOP_HIGH:
|
||||
case UNOP_CAST:
|
||||
|
||||
case UNOP_CAST_TYPE:
|
||||
case UNOP_REINTERPRET_CAST:
|
||||
case UNOP_DYNAMIC_CAST:
|
||||
/* Unary, binary and ternary operators: We have to check
|
||||
their operands. If they are constant, then so is the
|
||||
result of that operation. For instance, if A and B are
|
||||
determined to be constants, then so is "A + B".
|
||||
|
||||
UNOP_IND is one exception to the rule above, because the
|
||||
value of *ADDR is not necessarily a constant, even when
|
||||
ADDR is. */
|
||||
break;
|
||||
|
||||
case OP_VAR_VALUE:
|
||||
/* Check whether the associated symbol is a constant.
|
||||
|
||||
We use SYMBOL_CLASS rather than TYPE_CONST because it's
|
||||
possible that a buggy compiler could mark a variable as
|
||||
constant even when it is not, and TYPE_CONST would return
|
||||
true in this case, while SYMBOL_CLASS wouldn't.
|
||||
|
||||
We also have to check for function symbols because they
|
||||
are always constant. */
|
||||
{
|
||||
struct symbol *s = exp->elts[i + 2].symbol;
|
||||
|
||||
if (SYMBOL_CLASS (s) != LOC_BLOCK
|
||||
&& SYMBOL_CLASS (s) != LOC_CONST
|
||||
&& SYMBOL_CLASS (s) != LOC_CONST_BYTES)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The default action is to return 0 because we are using
|
||||
the optimistic approach here: If we don't know something,
|
||||
then it is not a constant. */
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return exp->op->constant_p ();
|
||||
}
|
||||
|
||||
/* Watchpoint destructor. */
|
||||
|
@ -10730,7 +10623,6 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
|
|||
const char *cond_end = NULL;
|
||||
enum bptype bp_type;
|
||||
int thread = -1;
|
||||
int pc = 0;
|
||||
/* Flag to indicate whether we are going to use masks for
|
||||
the hardware watchpoint. */
|
||||
bool use_mask = false;
|
||||
|
@ -10847,8 +10739,8 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
|
|||
exp_valid_block = tracker.block ();
|
||||
struct value *mark = value_mark ();
|
||||
struct value *val_as_value = nullptr;
|
||||
fetch_subexp_value (exp.get (), &pc, exp->op.get (), &val_as_value, &result,
|
||||
NULL, just_location);
|
||||
fetch_subexp_value (exp.get (), exp->op.get (), &val_as_value, &result, NULL,
|
||||
just_location);
|
||||
|
||||
if (val_as_value != NULL && just_location)
|
||||
{
|
||||
|
|
59
gdb/c-lang.c
59
gdb/c-lang.c
|
@ -740,45 +740,6 @@ c_is_string_type_p (struct type *type)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Table mapping opcodes into strings for printing operators
|
||||
and precedences of the operators. */
|
||||
|
||||
const struct op_print c_op_print_tab[] =
|
||||
{
|
||||
{",", BINOP_COMMA, PREC_COMMA, 0},
|
||||
{"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
|
||||
{"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
|
||||
{"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
|
||||
{"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
|
||||
{"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
|
||||
{"==", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{">>", BINOP_RSH, PREC_SHIFT, 0},
|
||||
{"<<", BINOP_LSH, PREC_SHIFT, 0},
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"%", BINOP_REM, PREC_MUL, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{"+", UNOP_PLUS, PREC_PREFIX, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
|
||||
{"*", UNOP_IND, PREC_PREFIX, 0},
|
||||
{"&", UNOP_ADDR, PREC_PREFIX, 0},
|
||||
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
|
||||
{"alignof ", UNOP_ALIGNOF, PREC_PREFIX, 0},
|
||||
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
|
||||
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
|
||||
{NULL, OP_NULL, PREC_PREFIX, 0}
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
|
@ -886,11 +847,6 @@ public:
|
|||
|
||||
enum macro_expansion macro_expansion () const override
|
||||
{ return macro_expansion_c; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return c_op_print_tab; }
|
||||
};
|
||||
|
||||
/* Single instance of the C language class. */
|
||||
|
@ -1065,11 +1021,6 @@ public:
|
|||
const struct lang_varobj_ops *varobj_ops () const override
|
||||
{ return &cplus_varobj_ops; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return c_op_print_tab; }
|
||||
|
||||
protected:
|
||||
|
||||
/* See language.h. */
|
||||
|
@ -1140,11 +1091,6 @@ public:
|
|||
|
||||
enum macro_expansion macro_expansion () const override
|
||||
{ return macro_expansion_c; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return c_op_print_tab; }
|
||||
};
|
||||
|
||||
/* The single instance of the ASM language class. */
|
||||
|
@ -1197,11 +1143,6 @@ public:
|
|||
|
||||
enum macro_expansion macro_expansion () const override
|
||||
{ return macro_expansion_c; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return c_op_print_tab; }
|
||||
};
|
||||
|
||||
/* The single instance of the minimal language class. */
|
||||
|
|
|
@ -106,8 +106,6 @@ extern void c_language_arch_info (struct gdbarch *gdbarch,
|
|||
extern void c_emit_char (int c, struct type *type,
|
||||
struct ui_file *stream, int quoter);
|
||||
|
||||
extern const struct op_print c_op_print_tab[];
|
||||
|
||||
/* These are in c-typeprint.c: */
|
||||
|
||||
extern void c_type_print_base (struct type *, struct ui_file *,
|
||||
|
|
43
gdb/d-lang.c
43
gdb/d-lang.c
|
@ -57,44 +57,6 @@ d_demangle (const char *symbol, int options)
|
|||
return gdb_demangle (symbol, options | DMGL_DLANG);
|
||||
}
|
||||
|
||||
/* Table mapping opcodes into strings for printing operators
|
||||
and precedences of the operators. */
|
||||
static const struct op_print d_op_print_tab[] =
|
||||
{
|
||||
{",", BINOP_COMMA, PREC_COMMA, 0},
|
||||
{"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
|
||||
{"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
|
||||
{"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
|
||||
{"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
|
||||
{"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
|
||||
{"==", BINOP_EQUAL, PREC_ORDER, 0},
|
||||
{"!=", BINOP_NOTEQUAL, PREC_ORDER, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{">>", BINOP_RSH, PREC_SHIFT, 0},
|
||||
{"<<", BINOP_LSH, PREC_SHIFT, 0},
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"~", BINOP_CONCAT, PREC_ADD, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"%", BINOP_REM, PREC_MUL, 0},
|
||||
{"^^", BINOP_EXP, PREC_REPEAT, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
|
||||
{"*", UNOP_IND, PREC_PREFIX, 0},
|
||||
{"&", UNOP_ADDR, PREC_PREFIX, 0},
|
||||
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
|
||||
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
|
||||
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
|
||||
{NULL, OP_NULL, PREC_PREFIX, 0}
|
||||
};
|
||||
|
||||
/* Class representing the D language. */
|
||||
|
||||
class d_language : public language_defn
|
||||
|
@ -216,11 +178,6 @@ public:
|
|||
|
||||
const char *name_of_this () const override
|
||||
{ return "this"; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return d_op_print_tab; }
|
||||
};
|
||||
|
||||
/* Single instance of the D language class. */
|
||||
|
|
|
@ -725,17 +725,9 @@ dtrace_probe::compile_to_ax (struct agent_expr *expr, struct axs_value *value,
|
|||
unsigned n)
|
||||
{
|
||||
struct dtrace_probe_arg *arg;
|
||||
union exp_element *pc;
|
||||
|
||||
arg = this->get_arg_by_number (n, expr->gdbarch);
|
||||
|
||||
if (arg->expr->op != nullptr)
|
||||
arg->expr->op->generate_ax (arg->expr.get (), expr, value);
|
||||
else
|
||||
{
|
||||
pc = arg->expr->elts;
|
||||
gen_expr (arg->expr.get (), &pc, expr, value);
|
||||
}
|
||||
arg->expr->op->generate_ax (arg->expr.get (), expr, value);
|
||||
|
||||
require_rvalue (expr, value);
|
||||
value->type = arg->type;
|
||||
|
|
1624
gdb/eval.c
1624
gdb/eval.c
File diff suppressed because it is too large
Load diff
1117
gdb/expprint.c
1117
gdb/expprint.c
File diff suppressed because it is too large
Load diff
|
@ -40,21 +40,6 @@ enum innermost_block_tracker_type
|
|||
DEF_ENUM_FLAGS_TYPE (enum innermost_block_tracker_type,
|
||||
innermost_block_tracker_types);
|
||||
|
||||
/* Definitions for saved C expressions. */
|
||||
|
||||
/* An expression is represented as a vector of union exp_element's.
|
||||
Each exp_element is an opcode, except that some opcodes cause
|
||||
the following exp_element to be treated as a long or double constant
|
||||
or as a variable. The opcodes are obeyed, using a stack for temporaries.
|
||||
The value is left on the temporary stack at the end. */
|
||||
|
||||
/* When it is necessary to include a string,
|
||||
it can occupy as many exp_elements as it needs.
|
||||
We find the length of the string using strlen,
|
||||
divide to find out how many exp_elements are used up,
|
||||
and skip that many. Strings, like numbers, are indicated
|
||||
by the preceding opcode. */
|
||||
|
||||
enum exp_opcode : uint8_t
|
||||
{
|
||||
#define OP(name) name ,
|
||||
|
@ -212,37 +197,17 @@ make_operation (Arg... args)
|
|||
|
||||
}
|
||||
|
||||
union exp_element
|
||||
{
|
||||
enum exp_opcode opcode;
|
||||
struct symbol *symbol;
|
||||
struct minimal_symbol *msymbol;
|
||||
LONGEST longconst;
|
||||
gdb_byte floatconst[16];
|
||||
/* Really sizeof (union exp_element) characters (or less for the last
|
||||
element of a string). */
|
||||
char string;
|
||||
struct type *type;
|
||||
struct internalvar *internalvar;
|
||||
const struct block *block;
|
||||
struct objfile *objfile;
|
||||
};
|
||||
|
||||
struct expression
|
||||
{
|
||||
expression (const struct language_defn *, struct gdbarch *, size_t);
|
||||
expression (const struct language_defn *, struct gdbarch *);
|
||||
~expression ();
|
||||
DISABLE_COPY_AND_ASSIGN (expression);
|
||||
|
||||
void resize (size_t);
|
||||
|
||||
/* Return the opcode for the outermost sub-expression of this
|
||||
expression. */
|
||||
enum exp_opcode first_opcode () const
|
||||
{
|
||||
if (op != nullptr)
|
||||
return op->opcode ();
|
||||
return elts[0].opcode;
|
||||
return op->opcode ();
|
||||
}
|
||||
|
||||
/* Evaluate the expression. EXPECT_TYPE is the context type of the
|
||||
|
@ -255,20 +220,10 @@ struct expression
|
|||
/* Architecture it was parsed in. */
|
||||
struct gdbarch *gdbarch;
|
||||
expr::operation_up op;
|
||||
int nelts = 0;
|
||||
union exp_element *elts;
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<expression> expression_up;
|
||||
|
||||
/* Macros for converting between number of expression elements and bytes
|
||||
to store that many expression elements. */
|
||||
|
||||
#define EXP_ELEM_TO_BYTES(elements) \
|
||||
((elements) * sizeof (union exp_element))
|
||||
#define BYTES_TO_EXP_ELEM(bytes) \
|
||||
(((bytes) + sizeof (union exp_element) - 1) / sizeof (union exp_element))
|
||||
|
||||
/* From parse.c */
|
||||
|
||||
class innermost_block_tracker;
|
||||
|
@ -289,9 +244,6 @@ extern expression_up parse_exp_1 (const char **, CORE_ADDR pc,
|
|||
|
||||
/* From eval.c */
|
||||
|
||||
extern struct value *evaluate_subexp_standard
|
||||
(struct type *, struct expression *, int *, enum noside);
|
||||
|
||||
/* Evaluate a function call. The function to be called is in CALLEE and
|
||||
the arguments passed to the function are in ARGVEC.
|
||||
FUNCTION_NAME is the name of the function, if known.
|
||||
|
@ -307,14 +259,8 @@ extern struct value *evaluate_subexp_do_call (expression *exp,
|
|||
|
||||
/* From expprint.c */
|
||||
|
||||
extern void print_expression (struct expression *, struct ui_file *);
|
||||
|
||||
extern const char *op_name (enum exp_opcode opcode);
|
||||
|
||||
extern const char *op_string (enum exp_opcode);
|
||||
|
||||
extern void dump_raw_expression (struct expression *,
|
||||
struct ui_file *, const char *);
|
||||
extern void dump_prefix_expression (struct expression *, struct ui_file *);
|
||||
|
||||
/* In an OP_RANGE expression, either bound could be empty, indicating
|
||||
|
|
28
gdb/f-lang.c
28
gdb/f-lang.c
|
@ -103,34 +103,6 @@ f_language::get_encoding (struct type *type)
|
|||
|
||||
|
||||
|
||||
/* Table of operators and their precedences for printing expressions. */
|
||||
|
||||
const struct op_print f_language::op_print_tab[] =
|
||||
{
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"+", UNOP_PLUS, PREC_PREFIX, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"DIV", BINOP_INTDIV, PREC_MUL, 0},
|
||||
{"MOD", BINOP_REM, PREC_MUL, 0},
|
||||
{"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{".OR.", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
|
||||
{".AND.", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
|
||||
{".NOT.", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{".EQ.", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{".NE.", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{".LE.", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{".GE.", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{".GT.", BINOP_GTR, PREC_ORDER, 0},
|
||||
{".LT.", BINOP_LESS, PREC_ORDER, 0},
|
||||
{"**", UNOP_IND, PREC_PREFIX, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{NULL, OP_NULL, PREC_REPEAT, 0}
|
||||
};
|
||||
|
||||
|
||||
/* A helper function for the "bound" intrinsics that checks that TYPE
|
||||
is an array. LBOUND_P is true for lower bound; this is used for
|
||||
the error message, if any. */
|
||||
|
|
|
@ -218,11 +218,6 @@ public:
|
|||
enum array_ordering array_ordering () const override
|
||||
{ return array_column_major; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return op_print_tab; }
|
||||
|
||||
protected:
|
||||
|
||||
/* See language.h. */
|
||||
|
@ -231,10 +226,6 @@ protected:
|
|||
(const lookup_name_info &lookup_name) const override;
|
||||
|
||||
private:
|
||||
/* Table of opcode data for use by OPCODE_PRINT_TABLE member function. */
|
||||
|
||||
static const struct op_print op_print_tab[];
|
||||
|
||||
/* Return the encoding that should be used for the character type
|
||||
TYPE. */
|
||||
|
||||
|
|
|
@ -444,44 +444,6 @@ go_block_package_name (const struct block *block)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* See go-lang.h.
|
||||
|
||||
TODO(dje): &^ ? */
|
||||
|
||||
const struct op_print go_language::op_print_tab[] =
|
||||
{
|
||||
{",", BINOP_COMMA, PREC_COMMA, 0},
|
||||
{"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
|
||||
{"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
|
||||
{"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
|
||||
{"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
|
||||
{"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
|
||||
{"==", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{">>", BINOP_RSH, PREC_SHIFT, 0},
|
||||
{"<<", BINOP_LSH, PREC_SHIFT, 0},
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"%", BINOP_REM, PREC_MUL, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"^", UNOP_COMPLEMENT, PREC_PREFIX, 0},
|
||||
{"*", UNOP_IND, PREC_PREFIX, 0},
|
||||
{"&", UNOP_ADDR, PREC_PREFIX, 0},
|
||||
{"unsafe.Sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
|
||||
{"++", UNOP_POSTINCREMENT, PREC_SUFFIX, 0},
|
||||
{"--", UNOP_POSTDECREMENT, PREC_SUFFIX, 0},
|
||||
{NULL, OP_NULL, PREC_SUFFIX, 0}
|
||||
};
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
void
|
||||
|
|
|
@ -134,18 +134,6 @@ public:
|
|||
|
||||
bool store_sym_names_in_linkage_form_p () const override
|
||||
{ return true; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return op_print_tab; }
|
||||
|
||||
private:
|
||||
|
||||
/* Table of opcode data for use by OPCODE_PRINT_TABLE member function. */
|
||||
|
||||
static const struct op_print op_print_tab[];
|
||||
|
||||
};
|
||||
|
||||
#endif /* !defined (GO_LANG_H) */
|
||||
|
|
|
@ -774,14 +774,6 @@ language_defn::varobj_ops () const
|
|||
return &c_varobj_ops;
|
||||
}
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct exp_descriptor *
|
||||
language_defn::expression_ops () const
|
||||
{
|
||||
return &exp_descriptor_standard;
|
||||
}
|
||||
|
||||
/* Parent class for both the "auto" and "unknown" languages. These two
|
||||
pseudo-languages are very similar so merging their implementations like
|
||||
this makes sense. */
|
||||
|
@ -901,18 +893,6 @@ public:
|
|||
|
||||
const char *name_of_this () const override
|
||||
{ return "this"; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{
|
||||
static const struct op_print unk_op_print_tab[] =
|
||||
{
|
||||
{NULL, OP_NULL, PREC_NULL, 0}
|
||||
};
|
||||
|
||||
return unk_op_print_tab;
|
||||
}
|
||||
};
|
||||
|
||||
/* Class representing the fake "auto" language. */
|
||||
|
|
|
@ -515,17 +515,6 @@ struct language_defn
|
|||
|
||||
virtual int parser (struct parser_state *ps) const;
|
||||
|
||||
/* Given an expression *EXPP created by prefixifying the result of
|
||||
la_parser, perform any remaining processing necessary to complete its
|
||||
translation. *EXPP may change; la_post_parser is responsible for
|
||||
releasing its previous contents, if necessary. */
|
||||
|
||||
virtual void post_parser (expression_up *expp, struct parser_state *ps)
|
||||
const
|
||||
{
|
||||
/* By default the post-parser does nothing. */
|
||||
}
|
||||
|
||||
/* Print the character CH (of type CHTYPE) on STREAM as part of the
|
||||
contents of a literal string whose delimiter is QUOTER. */
|
||||
|
||||
|
@ -642,15 +631,6 @@ struct language_defn
|
|||
|
||||
virtual const struct lang_varobj_ops *varobj_ops () const;
|
||||
|
||||
/* Definitions related to expression printing, prefixifying, and
|
||||
dumping. */
|
||||
|
||||
virtual const struct exp_descriptor *expression_ops () const;
|
||||
|
||||
/* Table for printing expressions. */
|
||||
|
||||
virtual const struct op_print *opcode_print_table () const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
/* This is the overridable part of the GET_SYMBOL_NAME_MATCHER method.
|
||||
|
|
|
@ -113,43 +113,6 @@ eval_op_m2_subscript (struct type *expect_type, struct expression *exp,
|
|||
|
||||
|
||||
|
||||
/* Table of operators and their precedences for printing expressions. */
|
||||
|
||||
const struct op_print m2_language::op_print_tab[] =
|
||||
{
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"+", UNOP_PLUS, PREC_PREFIX, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"DIV", BINOP_INTDIV, PREC_MUL, 0},
|
||||
{"MOD", BINOP_REM, PREC_MUL, 0},
|
||||
{":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
|
||||
{"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
|
||||
{"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"=", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{"<>", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{"^", UNOP_IND, PREC_PREFIX, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{"CAP", UNOP_CAP, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"CHR", UNOP_CHR, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"ORD", UNOP_ORD, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"FLOAT", UNOP_FLOAT, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"HIGH", UNOP_HIGH, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"MAX", UNOP_MAX, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"MIN", UNOP_MIN, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"ODD", UNOP_ODD, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"TRUNC", UNOP_TRUNC, PREC_BUILTIN_FUNCTION, 0},
|
||||
{NULL, OP_NULL, PREC_BUILTIN_FUNCTION, 0}
|
||||
};
|
||||
|
||||
|
||||
/* Single instance of the M2 language. */
|
||||
|
||||
static m2_language m2_language_defn;
|
||||
|
|
|
@ -147,15 +147,6 @@ public:
|
|||
|
||||
bool range_checking_on_by_default () const override
|
||||
{ return true; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return op_print_tab; }
|
||||
|
||||
private:
|
||||
/* Table of opcode data for use by OPCODE_PRINT_TABLE member function. */
|
||||
static const struct op_print op_print_tab[];
|
||||
};
|
||||
|
||||
#endif /* M2_LANG_H */
|
||||
|
|
|
@ -282,44 +282,6 @@ objc_demangle (const char *mangled, int options)
|
|||
return NULL; /* Not an objc mangled name. */
|
||||
}
|
||||
|
||||
|
||||
/* Table mapping opcodes into strings for printing operators
|
||||
and precedences of the operators. */
|
||||
|
||||
static const struct op_print objc_op_print_tab[] =
|
||||
{
|
||||
{",", BINOP_COMMA, PREC_COMMA, 0},
|
||||
{"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
|
||||
{"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
|
||||
{"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
|
||||
{"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
|
||||
{"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
|
||||
{"==", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{">>", BINOP_RSH, PREC_SHIFT, 0},
|
||||
{"<<", BINOP_LSH, PREC_SHIFT, 0},
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"%", BINOP_REM, PREC_MUL, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
|
||||
{"*", UNOP_IND, PREC_PREFIX, 0},
|
||||
{"&", UNOP_ADDR, PREC_PREFIX, 0},
|
||||
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
|
||||
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
|
||||
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
|
||||
{NULL, OP_NULL, PREC_NULL, 0}
|
||||
};
|
||||
|
||||
/* Class representing the Objective-C language. */
|
||||
|
||||
class objc_language : public language_defn
|
||||
|
@ -421,11 +383,6 @@ public:
|
|||
|
||||
enum macro_expansion macro_expansion () const override
|
||||
{ return macro_expansion_c; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return objc_op_print_tab; }
|
||||
};
|
||||
|
||||
/* Single instance of the class representing the Objective-C language. */
|
||||
|
|
|
@ -973,11 +973,6 @@ public:
|
|||
|
||||
enum macro_expansion macro_expansion () const override
|
||||
{ return macro_expansion_c; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return c_op_print_tab; }
|
||||
};
|
||||
|
||||
/* Single instance of the OpenCL language class. */
|
||||
|
|
34
gdb/p-lang.c
34
gdb/p-lang.c
|
@ -185,40 +185,6 @@ pascal_language::printchar (int c, struct type *type,
|
|||
|
||||
|
||||
|
||||
/* Table mapping opcodes into strings for printing operators
|
||||
and precedences of the operators. */
|
||||
|
||||
const struct op_print pascal_language::op_print_tab[] =
|
||||
{
|
||||
{",", BINOP_COMMA, PREC_COMMA, 0},
|
||||
{":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"or", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
|
||||
{"xor", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
|
||||
{"and", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
|
||||
{"=", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{"<>", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{"shr", BINOP_RSH, PREC_SHIFT, 0},
|
||||
{"shl", BINOP_LSH, PREC_SHIFT, 0},
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"div", BINOP_INTDIV, PREC_MUL, 0},
|
||||
{"mod", BINOP_REM, PREC_MUL, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"not", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"^", UNOP_IND, PREC_SUFFIX, 1},
|
||||
{"@", UNOP_ADDR, PREC_PREFIX, 0},
|
||||
{"sizeof", UNOP_SIZEOF, PREC_PREFIX, 0},
|
||||
{NULL, OP_NULL, PREC_PREFIX, 0}
|
||||
};
|
||||
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
void pascal_language::language_arch_info
|
||||
|
|
|
@ -154,17 +154,8 @@ public:
|
|||
bool range_checking_on_by_default () const override
|
||||
{ return true; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return op_print_tab; }
|
||||
|
||||
private:
|
||||
|
||||
/* Table of opcode data for use by OPCODE_PRINT_TABLE member function. */
|
||||
|
||||
static const struct op_print op_print_tab[];
|
||||
|
||||
/* Print the character C on STREAM as part of the contents of a literal
|
||||
string. IN_QUOTES is reset to 0 if a char is written with #4 notation. */
|
||||
|
||||
|
|
978
gdb/parse.c
978
gdb/parse.c
File diff suppressed because it is too large
Load diff
|
@ -71,29 +71,15 @@ struct expr_builder
|
|||
expout->op = std::move (op);
|
||||
}
|
||||
|
||||
/* The size of the expression above. */
|
||||
|
||||
size_t expout_size;
|
||||
|
||||
/* The expression related to this parser state. */
|
||||
|
||||
expression_up expout;
|
||||
|
||||
/* The number of elements already in the expression. This is used
|
||||
to know where to put new elements. */
|
||||
|
||||
size_t expout_ptr;
|
||||
};
|
||||
|
||||
/* This is used for expression completion. */
|
||||
|
||||
struct expr_completion_state
|
||||
{
|
||||
/* The index of the last struct expression directly before a '.' or
|
||||
'->'. This is set when parsing and is only used when completing a
|
||||
field name. It is -1 if no dereference operation was found. */
|
||||
int expout_last_struct = -1;
|
||||
|
||||
/* The last struct expression directly before a '.' or '->'. This
|
||||
is set when parsing and is only used when completing a field
|
||||
name. It is nullptr if no dereference operation was found. */
|
||||
|
@ -157,11 +143,6 @@ struct parser_state : public expr_builder
|
|||
return val;
|
||||
}
|
||||
|
||||
/* Mark the current index as the starting location of a structure
|
||||
expression. This is used when completing on field names. */
|
||||
|
||||
void mark_struct_expression ();
|
||||
|
||||
/* Mark the given operation as the starting location of a structure
|
||||
expression. This is used when completing on field names. */
|
||||
|
||||
|
@ -376,173 +357,13 @@ struct objc_class_str
|
|||
int theclass;
|
||||
};
|
||||
|
||||
/* Reverse an expression from suffix form (in which it is constructed)
|
||||
to prefix form (in which we can conveniently print or execute it).
|
||||
Ordinarily this always returns -1. However, if LAST_STRUCT
|
||||
is not -1 (i.e., we are trying to complete a field name), it will
|
||||
return the index of the subexpression which is the left-hand-side
|
||||
of the struct operation at LAST_STRUCT. */
|
||||
|
||||
extern int prefixify_expression (struct expression *expr,
|
||||
int last_struct = -1);
|
||||
|
||||
extern void write_exp_elt_opcode (struct expr_builder *, enum exp_opcode);
|
||||
|
||||
extern void write_exp_elt_sym (struct expr_builder *, struct symbol *);
|
||||
|
||||
extern void write_exp_elt_longcst (struct expr_builder *, LONGEST);
|
||||
|
||||
extern void write_exp_elt_floatcst (struct expr_builder *, const gdb_byte *);
|
||||
|
||||
extern void write_exp_elt_type (struct expr_builder *, struct type *);
|
||||
|
||||
extern void write_exp_elt_intern (struct expr_builder *, struct internalvar *);
|
||||
|
||||
extern void write_exp_string (struct expr_builder *, struct stoken);
|
||||
|
||||
void write_exp_string_vector (struct expr_builder *, int type,
|
||||
struct stoken_vector *vec);
|
||||
|
||||
extern void write_exp_bitstring (struct expr_builder *, struct stoken);
|
||||
|
||||
extern void write_exp_elt_block (struct expr_builder *, const struct block *);
|
||||
|
||||
extern void write_exp_elt_objfile (struct expr_builder *,
|
||||
struct objfile *objfile);
|
||||
|
||||
extern void write_exp_msymbol (struct expr_builder *,
|
||||
struct bound_minimal_symbol);
|
||||
|
||||
extern void write_dollar_variable (struct parser_state *, struct stoken str);
|
||||
|
||||
/* Write a reference to a symbol to the expression being built in PS.
|
||||
NAME is the name of the symbol to write; SYM is the symbol. If SYM
|
||||
is nullptr (meaning the 'symbol' member), a minimal symbol will be
|
||||
searched for and used if available. Throws an exception if SYM is
|
||||
nullptr and no minimal symbol can be found. */
|
||||
|
||||
extern void write_exp_symbol_reference (struct parser_state *ps,
|
||||
const char *name,
|
||||
struct block_symbol sym);
|
||||
|
||||
extern const char *find_template_name_end (const char *);
|
||||
|
||||
extern std::string copy_name (struct stoken);
|
||||
|
||||
extern int dump_subexp (struct expression *, struct ui_file *, int);
|
||||
|
||||
extern int dump_subexp_body_standard (struct expression *,
|
||||
struct ui_file *, int);
|
||||
|
||||
/* Dump (to STREAM) a function call like expression at position ELT in the
|
||||
expression array EXP. Return a new value for ELT just after the
|
||||
function call expression. */
|
||||
|
||||
extern int dump_subexp_body_funcall (struct expression *exp,
|
||||
struct ui_file *stream, int elt);
|
||||
|
||||
extern void operator_length (const struct expression *, int, int *, int *);
|
||||
|
||||
extern void operator_length_standard (const struct expression *, int, int *,
|
||||
int *);
|
||||
|
||||
extern int operator_check_standard (struct expression *exp, int pos,
|
||||
int (*objfile_func)
|
||||
(struct objfile *objfile, void *data),
|
||||
void *data);
|
||||
|
||||
extern bool parse_float (const char *p, int len,
|
||||
const struct type *type, gdb_byte *data);
|
||||
|
||||
/* These codes indicate operator precedences for expression printing,
|
||||
least tightly binding first. */
|
||||
/* Adding 1 to a precedence value is done for binary operators,
|
||||
on the operand which is more tightly bound, so that operators
|
||||
of equal precedence within that operand will get parentheses. */
|
||||
/* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
|
||||
they are used as the "surrounding precedence" to force
|
||||
various kinds of things to be parenthesized. */
|
||||
enum precedence
|
||||
{
|
||||
PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_LOGICAL_OR,
|
||||
PREC_LOGICAL_AND, PREC_BITWISE_IOR, PREC_BITWISE_AND, PREC_BITWISE_XOR,
|
||||
PREC_EQUAL, PREC_ORDER, PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
|
||||
PREC_HYPER, PREC_PREFIX, PREC_SUFFIX, PREC_BUILTIN_FUNCTION
|
||||
};
|
||||
|
||||
/* Table mapping opcodes into strings for printing operators
|
||||
and precedences of the operators. */
|
||||
|
||||
struct op_print
|
||||
{
|
||||
const char *string;
|
||||
enum exp_opcode opcode;
|
||||
/* Precedence of operator. These values are used only by comparisons. */
|
||||
enum precedence precedence;
|
||||
|
||||
/* For a binary operator: 1 iff right associate.
|
||||
For a unary operator: 1 iff postfix. */
|
||||
int right_assoc;
|
||||
};
|
||||
|
||||
/* Information needed to print, prefixify, and evaluate expressions for
|
||||
a given language. */
|
||||
|
||||
struct exp_descriptor
|
||||
{
|
||||
/* Print subexpression. */
|
||||
void (*print_subexp) (struct expression *, int *, struct ui_file *,
|
||||
enum precedence);
|
||||
|
||||
/* Returns number of exp_elements needed to represent an operator and
|
||||
the number of subexpressions it takes. */
|
||||
void (*operator_length) (const struct expression*, int, int*, int *);
|
||||
|
||||
/* Call OBJFILE_FUNC for any objfile found being referenced by the
|
||||
single operator of EXP at position POS. Operator parameters are
|
||||
located at positive (POS + number) offsets in EXP. OBJFILE_FUNC
|
||||
should never be called with NULL OBJFILE. OBJFILE_FUNC should
|
||||
get passed an arbitrary caller supplied DATA pointer. If it
|
||||
returns non-zero value then (any other) non-zero value should be
|
||||
immediately returned to the caller. Otherwise zero should be
|
||||
returned. */
|
||||
int (*operator_check) (struct expression *exp, int pos,
|
||||
int (*objfile_func) (struct objfile *objfile,
|
||||
void *data),
|
||||
void *data);
|
||||
|
||||
/* Dump the rest of this (prefix) expression after the operator
|
||||
itself has been printed. See dump_subexp_body_standard in
|
||||
(expprint.c). */
|
||||
int (*dump_subexp_body) (struct expression *, struct ui_file *, int);
|
||||
|
||||
/* Evaluate an expression. */
|
||||
struct value *(*evaluate_exp) (struct type *, struct expression *,
|
||||
int *, enum noside);
|
||||
};
|
||||
|
||||
|
||||
/* Default descriptor containing standard definitions of all
|
||||
elements. */
|
||||
extern const struct exp_descriptor exp_descriptor_standard;
|
||||
|
||||
/* Functions used by language-specific extended operators to (recursively)
|
||||
print/dump subexpressions. */
|
||||
|
||||
extern void print_subexp (struct expression *, int *, struct ui_file *,
|
||||
enum precedence);
|
||||
|
||||
extern void print_subexp_standard (struct expression *, int *,
|
||||
struct ui_file *, enum precedence);
|
||||
|
||||
/* Print a function call like expression to STREAM. This is called as a
|
||||
helper function by which point the expression node identifying this as a
|
||||
function call has already been stripped off and POS should point to the
|
||||
number of function call arguments. EXP is the object containing the
|
||||
list of expression elements. */
|
||||
|
||||
extern void print_subexp_funcall (struct expression *exp, int *pos,
|
||||
struct ui_file *stream);
|
||||
|
||||
/* Function used to avoid direct calls to fprintf
|
||||
in the code generated by the bison parser. */
|
||||
|
|
|
@ -2488,33 +2488,24 @@ ppc_linux_nat_target::check_condition (CORE_ADDR watch_addr,
|
|||
struct expression *cond,
|
||||
CORE_ADDR *data_value, int *len)
|
||||
{
|
||||
int pc = 1, num_accesses_left, num_accesses_right;
|
||||
int num_accesses_left, num_accesses_right;
|
||||
struct value *left_val, *right_val;
|
||||
std::vector<value_ref_ptr> left_chain, right_chain;
|
||||
|
||||
if (cond->first_opcode () != BINOP_EQUAL)
|
||||
expr::equal_operation *eqop
|
||||
= dynamic_cast<expr::equal_operation *> (cond->op.get ());
|
||||
if (eqop == nullptr)
|
||||
return 0;
|
||||
expr::operation *lhs = eqop->get_lhs ();
|
||||
expr::operation *rhs = eqop->get_rhs ();
|
||||
|
||||
expr::operation *lhs = nullptr;
|
||||
expr::operation *rhs = nullptr;
|
||||
if (cond->op != nullptr)
|
||||
{
|
||||
expr::equal_operation *eqop
|
||||
= dynamic_cast<expr::equal_operation *> (cond->op.get ());
|
||||
if (eqop != nullptr)
|
||||
{
|
||||
lhs = eqop->get_lhs ();
|
||||
rhs = eqop->get_rhs ();
|
||||
}
|
||||
}
|
||||
|
||||
fetch_subexp_value (cond, &pc, lhs, &left_val, NULL, &left_chain, false);
|
||||
fetch_subexp_value (cond, lhs, &left_val, NULL, &left_chain, false);
|
||||
num_accesses_left = num_memory_accesses (left_chain);
|
||||
|
||||
if (left_val == NULL || num_accesses_left < 0)
|
||||
return 0;
|
||||
|
||||
fetch_subexp_value (cond, &pc, rhs, &right_val, NULL, &right_chain, false);
|
||||
fetch_subexp_value (cond, rhs, &right_val, NULL, &right_chain, false);
|
||||
num_accesses_right = num_memory_accesses (right_chain);
|
||||
|
||||
if (right_val == NULL || num_accesses_right < 0)
|
||||
|
|
|
@ -1375,14 +1375,8 @@ set_command (const char *exp, int from_tty)
|
|||
{
|
||||
expression_up expr = parse_expression (exp);
|
||||
|
||||
enum exp_opcode opcode = OP_NULL;
|
||||
if (expr->op != nullptr)
|
||||
opcode = expr->op->opcode ();
|
||||
else if (expr->nelts >= 1)
|
||||
opcode = expr->elts[0].opcode;
|
||||
|
||||
if (opcode != OP_NULL)
|
||||
switch (opcode)
|
||||
switch (expr->op->opcode ())
|
||||
{
|
||||
case UNOP_PREINCREMENT:
|
||||
case UNOP_POSTINCREMENT:
|
||||
|
|
|
@ -209,11 +209,6 @@ public:
|
|||
bool range_checking_on_by_default () const override
|
||||
{ return true; }
|
||||
|
||||
/* See language.h. */
|
||||
|
||||
const struct op_print *opcode_print_table () const override
|
||||
{ return c_op_print_tab; }
|
||||
|
||||
private:
|
||||
|
||||
/* Helper for value_print_inner, arguments are as for that function.
|
||||
|
|
|
@ -1441,15 +1441,10 @@ stap_probe::compile_to_ax (struct agent_expr *expr, struct axs_value *value,
|
|||
unsigned n)
|
||||
{
|
||||
struct stap_probe_arg *arg;
|
||||
union exp_element *pc;
|
||||
|
||||
arg = this->get_arg_by_number (n, expr->gdbarch);
|
||||
|
||||
pc = arg->aexpr->elts;
|
||||
if (arg->aexpr->op != nullptr)
|
||||
arg->aexpr->op->generate_ax (arg->aexpr.get (), expr, value);
|
||||
else
|
||||
gen_expr (arg->aexpr.get (), &pc, expr, value);
|
||||
arg->aexpr->op->generate_ax (arg->aexpr.get (), expr, value);
|
||||
|
||||
require_rvalue (expr, value);
|
||||
value->type = arg->atype;
|
||||
|
|
|
@ -691,15 +691,10 @@ validate_actionline (const char *line, struct breakpoint *b)
|
|||
if (exp->first_opcode () == OP_VAR_VALUE)
|
||||
{
|
||||
symbol *sym;
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
expr::var_value_operation *vvop
|
||||
= (dynamic_cast<expr::var_value_operation *>
|
||||
(exp->op.get ()));
|
||||
sym = vvop->get_symbol ();
|
||||
}
|
||||
else
|
||||
sym = exp->elts[2].symbol;
|
||||
expr::var_value_operation *vvop
|
||||
= (dynamic_cast<expr::var_value_operation *>
|
||||
(exp->op.get ()));
|
||||
sym = vvop->get_symbol ();
|
||||
|
||||
if (SYMBOL_CLASS (sym) == LOC_CONST)
|
||||
{
|
||||
|
@ -1395,16 +1390,10 @@ encode_actions_1 (struct command_line *action,
|
|||
{
|
||||
case OP_REGISTER:
|
||||
{
|
||||
const char *name;
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
expr::register_operation *regop
|
||||
= (dynamic_cast<expr::register_operation *>
|
||||
(exp->op.get ()));
|
||||
name = regop->get_name ();
|
||||
}
|
||||
else
|
||||
name = &exp->elts[2].string;
|
||||
expr::register_operation *regop
|
||||
= (dynamic_cast<expr::register_operation *>
|
||||
(exp->op.get ()));
|
||||
const char *name = regop->get_name ();
|
||||
|
||||
i = user_reg_map_name_to_regnum (target_gdbarch (),
|
||||
name, strlen (name));
|
||||
|
@ -1424,16 +1413,10 @@ encode_actions_1 (struct command_line *action,
|
|||
/* Safe because we know it's a simple expression. */
|
||||
tempval = evaluate_expression (exp.get ());
|
||||
addr = value_address (tempval);
|
||||
struct type *type;
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
expr::unop_memval_operation *memop
|
||||
= (dynamic_cast<expr::unop_memval_operation *>
|
||||
(exp->op.get ()));
|
||||
type = memop->get_type ();
|
||||
}
|
||||
else
|
||||
type = exp->elts[1].type;
|
||||
expr::unop_memval_operation *memop
|
||||
= (dynamic_cast<expr::unop_memval_operation *>
|
||||
(exp->op.get ()));
|
||||
struct type *type = memop->get_type ();
|
||||
/* Initialize the TYPE_LENGTH if it is a typedef. */
|
||||
check_typedef (type);
|
||||
collect->add_memrange (target_gdbarch (),
|
||||
|
@ -1447,17 +1430,10 @@ encode_actions_1 (struct command_line *action,
|
|||
|
||||
case OP_VAR_VALUE:
|
||||
{
|
||||
struct symbol *sym;
|
||||
|
||||
if (exp->op != nullptr)
|
||||
{
|
||||
expr::var_value_operation *vvo
|
||||
= (dynamic_cast<expr::var_value_operation *>
|
||||
(exp->op.get ()));
|
||||
sym = vvo->get_symbol ();
|
||||
}
|
||||
else
|
||||
sym = exp->elts[2].symbol;
|
||||
expr::var_value_operation *vvo
|
||||
= (dynamic_cast<expr::var_value_operation *>
|
||||
(exp->op.get ()));
|
||||
struct symbol *sym = vvo->get_symbol ();
|
||||
const char *name = sym->natural_name ();
|
||||
|
||||
collect->collect_symbol (sym,
|
||||
|
|
30
gdb/value.c
30
gdb/value.c
|
@ -2015,29 +2015,19 @@ init_if_undefined_command (const char* args, int from_tty)
|
|||
/* Validate the expression.
|
||||
Was the expression an assignment?
|
||||
Or even an expression at all? */
|
||||
if ((expr->nelts == 0 && expr->op == nullptr)
|
||||
|| expr->first_opcode () != BINOP_ASSIGN)
|
||||
if (expr->op == nullptr || expr->first_opcode () != BINOP_ASSIGN)
|
||||
error (_("Init-if-undefined requires an assignment expression."));
|
||||
|
||||
/* Extract the variable from the parsed expression.
|
||||
In the case of an assign the lvalue will be in elts[1] and elts[2]. */
|
||||
if (expr->op == nullptr)
|
||||
/* Extract the variable from the parsed expression. */
|
||||
expr::assign_operation *assign
|
||||
= dynamic_cast<expr::assign_operation *> (expr->op.get ());
|
||||
if (assign != nullptr)
|
||||
{
|
||||
if (expr->elts[1].opcode == OP_INTERNALVAR)
|
||||
intvar = expr->elts[2].internalvar;
|
||||
}
|
||||
else
|
||||
{
|
||||
expr::assign_operation *assign
|
||||
= dynamic_cast<expr::assign_operation *> (expr->op.get ());
|
||||
if (assign != nullptr)
|
||||
{
|
||||
expr::operation *lhs = assign->get_lhs ();
|
||||
expr::internalvar_operation *ivarop
|
||||
= dynamic_cast<expr::internalvar_operation *> (lhs);
|
||||
if (ivarop != nullptr)
|
||||
intvar = ivarop->get_internalvar ();
|
||||
}
|
||||
expr::operation *lhs = assign->get_lhs ();
|
||||
expr::internalvar_operation *ivarop
|
||||
= dynamic_cast<expr::internalvar_operation *> (lhs);
|
||||
if (ivarop != nullptr)
|
||||
intvar = ivarop->get_internalvar ();
|
||||
}
|
||||
|
||||
if (intvar == nullptr)
|
||||
|
|
14
gdb/value.h
14
gdb/value.h
|
@ -914,13 +914,6 @@ extern struct value *evaluate_expression (struct expression *exp,
|
|||
|
||||
extern struct value *evaluate_type (struct expression *exp);
|
||||
|
||||
extern struct value *evaluate_subexp (struct type *expect_type,
|
||||
struct expression *exp,
|
||||
int *pos, enum noside noside);
|
||||
|
||||
extern struct value *evaluate_subexpression_type (struct expression *exp,
|
||||
int subexp);
|
||||
|
||||
extern value *evaluate_var_value (enum noside noside, const block *blk,
|
||||
symbol *var);
|
||||
|
||||
|
@ -931,17 +924,12 @@ extern value *evaluate_var_msym_value (enum noside noside,
|
|||
extern value *eval_skip_value (expression *exp);
|
||||
|
||||
namespace expr { class operation; };
|
||||
extern void fetch_subexp_value (struct expression *exp, int *pc,
|
||||
extern void fetch_subexp_value (struct expression *exp,
|
||||
expr::operation *op,
|
||||
struct value **valp, struct value **resultp,
|
||||
std::vector<value_ref_ptr> *val_chain,
|
||||
bool preserve_errors);
|
||||
|
||||
extern const char *extract_field_op (struct expression *exp, int *subexp);
|
||||
|
||||
extern struct value *evaluate_subexp_with_coercion (struct expression *,
|
||||
int *, enum noside);
|
||||
|
||||
extern struct value *parse_and_eval (const char *exp);
|
||||
|
||||
extern struct value *parse_to_comma_and_eval (const char **expp);
|
||||
|
|
Loading…
Add table
Reference in a new issue