diff options
author | Tom Tromey <tom@tromey.com> | 2021-03-08 07:27:57 -0700 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2021-03-08 07:28:41 -0700 |
commit | 1eaebe02cfe78229d78ac27f5bd6651e1c1af863 (patch) | |
tree | 870c2965ac8dada5ed4527853f829c3ddbbaf5a2 /gdb/ax-gdb.c | |
parent | f2a98603a807101722f12b8d7a1aca9651deb133 (diff) | |
download | fsf-binutils-gdb-1eaebe02cfe78229d78ac27f5bd6651e1c1af863.zip fsf-binutils-gdb-1eaebe02cfe78229d78ac27f5bd6651e1c1af863.tar.gz fsf-binutils-gdb-1eaebe02cfe78229d78ac27f5bd6651e1c1af863.tar.bz2 |
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.
Diffstat (limited to 'gdb/ax-gdb.c')
-rw-r--r-- | gdb/ax-gdb.c | 735 |
1 files changed, 3 insertions, 732 deletions
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index d2f50bb..788be52 100644 --- a/gdb/ax-gdb.c +++ b/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); } |