X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fax-gdb.c;h=75aa7ca62b2bfe3a14c334695949298babc5667d;hb=be636754b785aa5b042991267c851af18ed5b6a9;hp=18b7e31c4d413273cfec2b334ea7e4afac99591f;hpb=a9762ec78a53fbe9209fe1654db42df0cd328d50;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 18b7e31c4d..75aa7ca62b 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -1,6 +1,6 @@ /* GDB-specific functions for operating on agent expressions. - Copyright (C) 1998, 1999, 2000, 2001, 2003, 2007 + Copyright (C) 1998, 1999, 2000, 2001, 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +22,7 @@ #include "symtab.h" #include "symfile.h" #include "gdbtypes.h" +#include "language.h" #include "value.h" #include "expression.h" #include "command.h" @@ -33,6 +34,11 @@ #include "gdb_string.h" #include "block.h" #include "regcache.h" +#include "user-regs.h" +#include "language.h" +#include "dictionary.h" +#include "breakpoint.h" +#include "tracepoint.h" /* To make sense of this file, you should read doc/agentexpr.texi. Then look at the types and enums in ax-gdb.h. For the code itself, @@ -71,11 +77,11 @@ static void gen_fetch (struct agent_expr *, struct type *); static void gen_left_shift (struct agent_expr *, int); -static void gen_frame_args_address (struct agent_expr *); -static void gen_frame_locals_address (struct agent_expr *); +static void gen_frame_args_address (struct gdbarch *, struct agent_expr *); +static void gen_frame_locals_address (struct gdbarch *, struct agent_expr *); static void gen_offset (struct agent_expr *ax, int offset); static void gen_sym_offset (struct agent_expr *, struct symbol *); -static void gen_var_ref (struct agent_expr *ax, +static void gen_var_ref (struct gdbarch *, struct agent_expr *ax, struct axs_value *value, struct symbol *var); @@ -85,52 +91,63 @@ static void gen_int_literal (struct agent_expr *ax, static void require_rvalue (struct agent_expr *ax, struct axs_value *value); -static void gen_usual_unary (struct agent_expr *ax, struct axs_value *value); +static void gen_usual_unary (struct expression *exp, struct agent_expr *ax, + struct axs_value *value); static int type_wider_than (struct type *type1, struct type *type2); static struct type *max_type (struct type *type1, struct type *type2); static void gen_conversion (struct agent_expr *ax, struct type *from, struct type *to); static int is_nontrivial_conversion (struct type *from, struct type *to); -static void gen_usual_arithmetic (struct agent_expr *ax, +static void gen_usual_arithmetic (struct expression *exp, + struct agent_expr *ax, struct axs_value *value1, struct axs_value *value2); -static void gen_integral_promotions (struct agent_expr *ax, +static void gen_integral_promotions (struct expression *exp, + struct agent_expr *ax, struct axs_value *value); static void gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type); static void gen_scale (struct agent_expr *ax, enum agent_op op, struct type *type); -static void gen_add (struct agent_expr *ax, - struct axs_value *value, - struct axs_value *value1, - struct axs_value *value2, char *name); -static void gen_sub (struct agent_expr *ax, - struct axs_value *value, - struct axs_value *value1, struct axs_value *value2); +static void gen_ptradd (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2); +static void gen_ptrsub (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2); +static void gen_ptrdiff (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2, + struct type *result_type); static void gen_binop (struct agent_expr *ax, struct axs_value *value, struct axs_value *value1, struct axs_value *value2, enum agent_op op, enum agent_op op_unsigned, int may_carry, char *name); -static void gen_logical_not (struct agent_expr *ax, struct axs_value *value); +static void gen_logical_not (struct agent_expr *ax, struct axs_value *value, + struct type *result_type); static void gen_complement (struct agent_expr *ax, struct axs_value *value); static void gen_deref (struct agent_expr *, struct axs_value *); static void gen_address_of (struct agent_expr *, struct axs_value *); static int find_field (struct type *type, char *name); -static void gen_bitfield_ref (struct agent_expr *ax, +static void gen_bitfield_ref (struct expression *exp, struct agent_expr *ax, struct axs_value *value, struct type *type, int start, int end); -static void gen_struct_ref (struct agent_expr *ax, +static void gen_struct_ref (struct expression *exp, struct agent_expr *ax, struct axs_value *value, char *field, char *operator_name, char *operand_name); -static void gen_repeat (union exp_element **pc, +static void gen_repeat (struct expression *exp, union exp_element **pc, struct agent_expr *ax, struct axs_value *value); -static void gen_sizeof (union exp_element **pc, - struct agent_expr *ax, struct axs_value *value); -static void gen_expr (union exp_element **pc, +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 (struct expression *exp, union exp_element **pc, struct agent_expr *ax, struct axs_value *value); +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 agent_command (char *exp, int from_tty); @@ -319,7 +336,7 @@ gen_traced_pop (struct agent_expr *ax, struct axs_value *value) case axs_lvalue_memory: { - int length = TYPE_LENGTH (value->type); + int length = TYPE_LENGTH (check_typedef (value->type)); /* There's no point in trying to use a trace_quick bytecode here, since "trace_quick SIZE pop" is three bytes, whereas @@ -386,6 +403,7 @@ gen_fetch (struct agent_expr *ax, struct type *type) switch (TYPE_CODE (type)) { case TYPE_CODE_PTR: + case TYPE_CODE_REF: case TYPE_CODE_ENUM: case TYPE_CODE_INT: case TYPE_CODE_CHAR: @@ -454,12 +472,12 @@ gen_left_shift (struct agent_expr *ax, int distance) /* Generate code to push the base address of the argument portion of the top stack frame. */ static void -gen_frame_args_address (struct agent_expr *ax) +gen_frame_args_address (struct gdbarch *gdbarch, struct agent_expr *ax) { int frame_reg; LONGEST frame_offset; - gdbarch_virtual_frame_pointer (current_gdbarch, + gdbarch_virtual_frame_pointer (gdbarch, ax->scope, &frame_reg, &frame_offset); ax_reg (ax, frame_reg); gen_offset (ax, frame_offset); @@ -469,12 +487,12 @@ gen_frame_args_address (struct agent_expr *ax) /* Generate code to push the base address of the locals portion of the top stack frame. */ static void -gen_frame_locals_address (struct agent_expr *ax) +gen_frame_locals_address (struct gdbarch *gdbarch, struct agent_expr *ax) { int frame_reg; LONGEST frame_offset; - gdbarch_virtual_frame_pointer (current_gdbarch, + gdbarch_virtual_frame_pointer (gdbarch, ax->scope, &frame_reg, &frame_offset); ax_reg (ax, frame_reg); gen_offset (ax, frame_offset); @@ -519,7 +537,8 @@ gen_sym_offset (struct agent_expr *ax, struct symbol *var) symbol VAR. Set VALUE to describe the result. */ static void -gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var) +gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax, + struct axs_value *value, struct symbol *var) { /* Dereference any typedefs. */ value->type = check_typedef (SYMBOL_TYPE (var)); @@ -549,30 +568,22 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var) break; case LOC_ARG: /* var lives in argument area of frame */ - gen_frame_args_address (ax); + gen_frame_args_address (gdbarch, ax); gen_sym_offset (ax, var); value->kind = axs_lvalue_memory; break; case LOC_REF_ARG: /* As above, but the frame slot really holds the address of the variable. */ - gen_frame_args_address (ax); + gen_frame_args_address (gdbarch, ax); gen_sym_offset (ax, var); /* Don't assume any particular pointer size. */ - gen_fetch (ax, lookup_pointer_type (builtin_type_void)); + gen_fetch (ax, builtin_type (gdbarch)->builtin_data_ptr); value->kind = axs_lvalue_memory; break; case LOC_LOCAL: /* var lives in locals area of frame */ - case LOC_LOCAL_ARG: - gen_frame_locals_address (ax); - gen_sym_offset (ax, var); - value->kind = axs_lvalue_memory; - break; - - case LOC_BASEREG: /* relative to some base register */ - case LOC_BASEREG_ARG: - ax_reg (ax, SYMBOL_BASEREG (var)); + gen_frame_locals_address (gdbarch, ax); gen_sym_offset (ax, var); value->kind = axs_lvalue_memory; break; @@ -588,27 +599,26 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var) break; case LOC_REGISTER: - case LOC_REGPARM: /* Don't generate any code at all; in the process of treating this as an lvalue or rvalue, the caller will generate the right code. */ value->kind = axs_lvalue_register; - value->u.reg = SYMBOL_VALUE (var); + value->u.reg = SYMBOL_REGISTER_OPS (var)->register_number (var, gdbarch); break; /* A lot like LOC_REF_ARG, but the pointer lives directly in a - register, not on the stack. Simpler than LOC_REGISTER and - LOC_REGPARM, because it's just like any other case where the - thing has a real address. */ + register, not on the stack. Simpler than LOC_REGISTER + because it's just like any other case where the thing + has a real address. */ case LOC_REGPARM_ADDR: - ax_reg (ax, SYMBOL_VALUE (var)); + ax_reg (ax, SYMBOL_REGISTER_OPS (var)->register_number (var, gdbarch)); value->kind = axs_lvalue_memory; break; case LOC_UNRESOLVED: { struct minimal_symbol *msym - = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (var), NULL, NULL); + = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (var), NULL, NULL); if (!msym) error (_("Couldn't resolve symbol `%s'."), SYMBOL_PRINT_NAME (var)); @@ -619,13 +629,12 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var) break; case LOC_COMPUTED: - case LOC_COMPUTED_ARG: /* FIXME: cagney/2004-01-26: It should be possible to - unconditionally call the SYMBOL_OPS method when available. + unconditionally call the SYMBOL_COMPUTED_OPS method when available. Unfortunately DWARF 2 stores the frame-base (instead of the function) location in a function's symbol. Oops! For the moment enable this when/where applicable. */ - SYMBOL_OPS (var)->tracepoint_var_ref (var, ax, value); + SYMBOL_COMPUTED_OPS (var)->tracepoint_var_ref (var, gdbarch, ax, value); break; case LOC_OPTIMIZED_OUT: @@ -650,7 +659,7 @@ gen_int_literal (struct agent_expr *ax, struct axs_value *value, LONGEST k, { ax_const_l (ax, k); value->kind = axs_rvalue; - value->type = type; + value->type = check_typedef (type); } @@ -706,7 +715,8 @@ require_rvalue (struct agent_expr *ax, struct axs_value *value) lvalue through unchanged, and let `+' raise an error. */ static void -gen_usual_unary (struct agent_expr *ax, struct axs_value *value) +gen_usual_unary (struct expression *exp, struct agent_expr *ax, + struct axs_value *value) { /* We don't have to generate any code for the usual integral conversions, since values are always represented as full-width on @@ -741,7 +751,7 @@ gen_usual_unary (struct agent_expr *ax, struct axs_value *value) /* If the value is an enum, call it an integer. */ case TYPE_CODE_ENUM: - value->type = builtin_type_int; + value->type = builtin_type (exp->gdbarch)->builtin_int; break; } @@ -826,8 +836,8 @@ is_nontrivial_conversion (struct type *from, struct type *to) and promotes each argument to that type. *VALUE1 and *VALUE2 describe the values as they are passed in, and as they are left. */ static void -gen_usual_arithmetic (struct agent_expr *ax, struct axs_value *value1, - struct axs_value *value2) +gen_usual_arithmetic (struct expression *exp, struct agent_expr *ax, + struct axs_value *value1, struct axs_value *value2) { /* Do the usual binary conversions. */ if (TYPE_CODE (value1->type) == TYPE_CODE_INT @@ -838,7 +848,7 @@ gen_usual_arithmetic (struct agent_expr *ax, struct axs_value *value1, unsigned type is considered "wider" than an n-bit signed type. Promote to the "wider" of the two types, and always promote at least to int. */ - struct type *target = max_type (builtin_type_int, + struct type *target = max_type (builtin_type (exp->gdbarch)->builtin_int, max_type (value1->type, value2->type)); /* Deal with value2, on the top of the stack. */ @@ -854,7 +864,7 @@ gen_usual_arithmetic (struct agent_expr *ax, struct axs_value *value1, ax_simple (ax, aop_swap); } - value1->type = value2->type = target; + value1->type = value2->type = check_typedef (target); } } @@ -863,17 +873,20 @@ gen_usual_arithmetic (struct agent_expr *ax, struct axs_value *value1, the value on the top of the stack, as described by VALUE. Assume the value has integral type. */ static void -gen_integral_promotions (struct agent_expr *ax, struct axs_value *value) +gen_integral_promotions (struct expression *exp, struct agent_expr *ax, + struct axs_value *value) { - if (!type_wider_than (value->type, builtin_type_int)) + const struct builtin_type *builtin = builtin_type (exp->gdbarch); + + if (!type_wider_than (value->type, builtin->builtin_int)) { - gen_conversion (ax, value->type, builtin_type_int); - value->type = builtin_type_int; + gen_conversion (ax, value->type, builtin->builtin_int); + value->type = builtin->builtin_int; } - else if (!type_wider_than (value->type, builtin_type_unsigned_int)) + else if (!type_wider_than (value->type, builtin->builtin_unsigned_int)) { - gen_conversion (ax, value->type, builtin_type_unsigned_int); - value->type = builtin_type_unsigned_int; + gen_conversion (ax, value->type, builtin->builtin_unsigned_int); + value->type = builtin->builtin_unsigned_int; } } @@ -891,6 +904,7 @@ gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type) switch (TYPE_CODE (type)) { case TYPE_CODE_PTR: + case TYPE_CODE_REF: /* It's implementation-defined, and I'll bet this is what GCC does. */ break; @@ -905,9 +919,8 @@ gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type) /* We don't have to worry about the size of the value, because all our integral values are fully sign-extended, and when casting pointers we can do anything we like. Is there any - way for us to actually know what GCC actually does with a - cast like this? */ - value->type = type; + way for us to know what GCC actually does with a cast like + this? */ break; case TYPE_CODE_INT: @@ -947,105 +960,60 @@ gen_scale (struct agent_expr *ax, enum agent_op op, struct type *type) } -/* Generate code for an addition; non-trivial because we deal with - pointer arithmetic. We set VALUE to describe the result value; we - assume VALUE1 and VALUE2 describe the two operands, and that - they've undergone the usual binary conversions. Used by both - BINOP_ADD and BINOP_SUBSCRIPT. NAME is used in error messages. */ +/* Generate code for pointer arithmetic PTR + INT. */ static void -gen_add (struct agent_expr *ax, struct axs_value *value, - struct axs_value *value1, struct axs_value *value2, char *name) +gen_ptradd (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2) { - /* Is it INT+PTR? */ - if (TYPE_CODE (value1->type) == TYPE_CODE_INT - && TYPE_CODE (value2->type) == TYPE_CODE_PTR) - { - /* Swap the values and proceed normally. */ - ax_simple (ax, aop_swap); - gen_scale (ax, aop_mul, value2->type); - ax_simple (ax, aop_add); - gen_extend (ax, value2->type); /* Catch overflow. */ - value->type = value2->type; - } + gdb_assert (pointer_type (value1->type)); + gdb_assert (TYPE_CODE (value2->type) == TYPE_CODE_INT); - /* Is it PTR+INT? */ - else if (TYPE_CODE (value1->type) == TYPE_CODE_PTR - && TYPE_CODE (value2->type) == TYPE_CODE_INT) - { - gen_scale (ax, aop_mul, value1->type); - ax_simple (ax, aop_add); - gen_extend (ax, value1->type); /* Catch overflow. */ - value->type = value1->type; - } + gen_scale (ax, aop_mul, value1->type); + ax_simple (ax, aop_add); + gen_extend (ax, value1->type); /* Catch overflow. */ + value->type = value1->type; + value->kind = axs_rvalue; +} - /* Must be number + number; the usual binary conversions will have - brought them both to the same width. */ - else if (TYPE_CODE (value1->type) == TYPE_CODE_INT - && TYPE_CODE (value2->type) == TYPE_CODE_INT) - { - ax_simple (ax, aop_add); - gen_extend (ax, value1->type); /* Catch overflow. */ - value->type = value1->type; - } - else - error (_("Invalid combination of types in %s."), name); +/* Generate code for pointer arithmetic PTR - INT. */ +static void +gen_ptrsub (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2) +{ + gdb_assert (pointer_type (value1->type)); + gdb_assert (TYPE_CODE (value2->type) == TYPE_CODE_INT); + gen_scale (ax, aop_mul, value1->type); + ax_simple (ax, aop_sub); + gen_extend (ax, value1->type); /* Catch overflow. */ + value->type = value1->type; value->kind = axs_rvalue; } -/* Generate code for an addition; non-trivial because we have to deal - with pointer arithmetic. We set VALUE to describe the result - value; we assume VALUE1 and VALUE2 describe the two operands, and - that they've undergone the usual binary conversions. */ +/* Generate code for pointer arithmetic PTR - PTR. */ static void -gen_sub (struct agent_expr *ax, struct axs_value *value, - struct axs_value *value1, struct axs_value *value2) +gen_ptrdiff (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2, + struct type *result_type) { - if (TYPE_CODE (value1->type) == TYPE_CODE_PTR) - { - /* Is it PTR - INT? */ - if (TYPE_CODE (value2->type) == TYPE_CODE_INT) - { - gen_scale (ax, aop_mul, value1->type); - ax_simple (ax, aop_sub); - gen_extend (ax, value1->type); /* Catch overflow. */ - value->type = value1->type; - } + gdb_assert (pointer_type (value1->type)); + gdb_assert (pointer_type (value2->type)); - /* Is it PTR - PTR? Strictly speaking, the types ought to - match, but this is what the normal GDB expression evaluator - tests for. */ - else if (TYPE_CODE (value2->type) == TYPE_CODE_PTR - && (TYPE_LENGTH (TYPE_TARGET_TYPE (value1->type)) - == TYPE_LENGTH (TYPE_TARGET_TYPE (value2->type)))) - { - ax_simple (ax, aop_sub); - gen_scale (ax, aop_div_unsigned, value1->type); - value->type = builtin_type_long; /* FIXME --- should be ptrdiff_t */ - } - else - error (_("\ + if (TYPE_LENGTH (TYPE_TARGET_TYPE (value1->type)) + != TYPE_LENGTH (TYPE_TARGET_TYPE (value2->type))) + error (_("\ First argument of `-' is a pointer, but second argument is neither\n\ an integer nor a pointer of the same type.")); - } - - /* Must be number + number. */ - else if (TYPE_CODE (value1->type) == TYPE_CODE_INT - && TYPE_CODE (value2->type) == TYPE_CODE_INT) - { - ax_simple (ax, aop_sub); - gen_extend (ax, value1->type); /* Catch overflow. */ - value->type = value1->type; - } - - else - error (_("Invalid combination of types in subtraction.")); + ax_simple (ax, aop_sub); + gen_scale (ax, aop_div_unsigned, value1->type); + value->type = result_type; value->kind = axs_rvalue; } + /* Generate code for a binary operator that doesn't do pointer magic. We set VALUE to describe the result value; we assume VALUE1 and VALUE2 describe the two operands, and that they've undergone the @@ -1072,15 +1040,15 @@ gen_binop (struct agent_expr *ax, struct axs_value *value, static void -gen_logical_not (struct agent_expr *ax, struct axs_value *value) +gen_logical_not (struct agent_expr *ax, struct axs_value *value, + struct type *result_type) { if (TYPE_CODE (value->type) != TYPE_CODE_INT && TYPE_CODE (value->type) != TYPE_CODE_PTR) error (_("Invalid type of operand to `!'.")); - gen_usual_unary (ax, value); ax_simple (ax, aop_log_not); - value->type = builtin_type_int; + value->type = result_type; } @@ -1090,8 +1058,6 @@ gen_complement (struct agent_expr *ax, struct axs_value *value) if (TYPE_CODE (value->type) != TYPE_CODE_INT) error (_("Invalid type of operand to `~'.")); - gen_usual_unary (ax, value); - gen_integral_promotions (ax, value); ax_simple (ax, aop_bit_not); gen_extend (ax, value->type); } @@ -1106,7 +1072,7 @@ gen_deref (struct agent_expr *ax, struct axs_value *value) { /* The caller should check the type, because several operators use this, and we don't know what error message to generate. */ - if (TYPE_CODE (value->type) != TYPE_CODE_PTR) + if (!pointer_type (value->type)) internal_error (__FILE__, __LINE__, _("gen_deref: expected a pointer")); @@ -1116,6 +1082,8 @@ gen_deref (struct agent_expr *ax, struct axs_value *value) T" to "T", and mark the value as an lvalue in memory. Leave it to the consumer to actually dereference it. */ value->type = check_typedef (TYPE_TARGET_TYPE (value->type)); + if (TYPE_CODE (value->type) == TYPE_CODE_VOID) + error (_("Attempt to dereference a generic pointer.")); value->kind = ((TYPE_CODE (value->type) == TYPE_CODE_FUNC) ? axs_rvalue : axs_lvalue_memory); } @@ -1193,8 +1161,9 @@ find_field (struct type *type, char *name) starting and one-past-ending *bit* numbers of the field within the structure. */ static void -gen_bitfield_ref (struct agent_expr *ax, struct axs_value *value, - struct type *type, int start, int end) +gen_bitfield_ref (struct expression *exp, struct agent_expr *ax, + struct axs_value *value, struct type *type, + int start, int end) { /* Note that ops[i] fetches 8 << i bits. */ static enum agent_op ops[] @@ -1320,7 +1289,7 @@ gen_bitfield_ref (struct agent_expr *ax, struct axs_value *value, the sign/zero extension will wipe them out. - If we're in the interior of the word, then there is no garbage on either end, because the ref operators zero-extend. */ - if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) + if (gdbarch_byte_order (exp->gdbarch) == BFD_ENDIAN_BIG) gen_left_shift (ax, end - (offset + op_size)); else gen_left_shift (ax, offset - start); @@ -1354,7 +1323,8 @@ gen_bitfield_ref (struct agent_expr *ax, struct axs_value *value, the operator being compiled, and OPERAND_NAME is the kind of thing it operates on; we use them in error messages. */ static void -gen_struct_ref (struct agent_expr *ax, struct axs_value *value, char *field, +gen_struct_ref (struct expression *exp, struct agent_expr *ax, + struct axs_value *value, char *field, char *operator_name, char *operand_name) { struct type *type; @@ -1363,9 +1333,9 @@ gen_struct_ref (struct agent_expr *ax, struct axs_value *value, char *field, /* Follow pointers until we reach a non-pointer. These aren't the C semantics, but they're what the normal GDB evaluator does, so we should at least be consistent. */ - while (TYPE_CODE (value->type) == TYPE_CODE_PTR) + while (pointer_type (value->type)) { - gen_usual_unary (ax, value); + require_rvalue (ax, value); gen_deref (ax, value); } type = check_typedef (value->type); @@ -1385,7 +1355,7 @@ gen_struct_ref (struct agent_expr *ax, struct axs_value *value, char *field, /* Is this a bitfield? */ if (TYPE_FIELD_PACKED (type, i)) - gen_bitfield_ref (ax, value, TYPE_FIELD_TYPE (type, i), + gen_bitfield_ref (exp, ax, value, TYPE_FIELD_TYPE (type, i), TYPE_FIELD_BITPOS (type, i), (TYPE_FIELD_BITPOS (type, i) + TYPE_FIELD_BITSIZE (type, i))); @@ -1410,13 +1380,13 @@ gen_struct_ref (struct agent_expr *ax, struct axs_value *value, char *field, stack slots, doing weird things with sizeof, etc. So we require the right operand to be a constant expression. */ static void -gen_repeat (union exp_element **pc, struct agent_expr *ax, - struct axs_value *value) +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 (pc, ax, &value1); + gen_expr (exp, pc, ax, &value1); if (value1.kind != axs_lvalue_memory) error (_("Left operand of `@' must be an object in memory.")); @@ -1438,9 +1408,8 @@ gen_repeat (union exp_element **pc, struct agent_expr *ax, { /* FIXME-type-allocation: need a way to free this type when we are done with it. */ - struct type *range - = create_range_type (0, builtin_type_int, 0, length - 1); - struct type *array = create_array_type (0, value1.type, range); + struct type *array + = lookup_array_range_type (value1.type, 0, length - 1); value->kind = axs_lvalue_memory; value->type = array; @@ -1453,8 +1422,9 @@ gen_repeat (union exp_element **pc, struct agent_expr *ax, *PC should point at the start of the operand expression; we advance it to the first instruction after the operand. */ static void -gen_sizeof (union exp_element **pc, struct agent_expr *ax, - struct axs_value *value) +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 @@ -1462,14 +1432,14 @@ gen_sizeof (union exp_element **pc, struct agent_expr *ax, 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 (pc, ax, value); + 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 = builtin_type_int; + value->type = size_type; } @@ -1479,12 +1449,13 @@ gen_sizeof (union exp_element **pc, struct agent_expr *ax, /* A gen_expr function written by a Gen-X'er guy. Append code for the subexpression of EXPR starting at *POS_P to AX. */ static void -gen_expr (union exp_element **pc, struct agent_expr *ax, - struct axs_value *value) +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; - enum exp_opcode op = (*pc)[0].opcode; + struct axs_value value1, value2, value3; + enum exp_opcode op = (*pc)[0].opcode, op2; + int if1, go1, if2, go2, end; /* If we're looking at a constant expression, just push its value. */ { @@ -1512,59 +1483,137 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, 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 (pc, ax, &value1); - gen_usual_unary (ax, &value1); - gen_expr (pc, ax, &value2); - gen_usual_unary (ax, &value2); - gen_usual_arithmetic (ax, &value1, &value2); - switch (op) - { - case BINOP_ADD: - gen_add (ax, value, &value1, &value2, "addition"); - break; - case BINOP_SUB: - gen_sub (ax, value, &value1, &value2); - break; - case BINOP_MUL: - gen_binop (ax, value, &value1, &value2, - aop_mul, aop_mul, 1, "multiplication"); - break; - case BINOP_DIV: - gen_binop (ax, value, &value1, &value2, - aop_div_signed, aop_div_unsigned, 1, "division"); - break; - case BINOP_REM: - gen_binop (ax, value, &value1, &value2, - aop_rem_signed, aop_rem_unsigned, 1, "remainder"); - break; - case BINOP_SUBSCRIPT: - gen_add (ax, value, &value1, &value2, "array subscripting"); - if (TYPE_CODE (value->type) != TYPE_CODE_PTR) - error (_("Invalid combination of types in array subscripting.")); - gen_deref (ax, value); - break; - case BINOP_BITWISE_AND: - gen_binop (ax, value, &value1, &value2, - aop_bit_and, aop_bit_and, 0, "bitwise and"); - break; + gen_expr (exp, pc, ax, &value1); + gen_usual_unary (exp, ax, &value1); + gen_expr_binop_rest (exp, op, pc, ax, value, &value1, &value2); + break; - case BINOP_BITWISE_IOR: - gen_binop (ax, value, &value1, &value2, - aop_bit_or, aop_bit_or, 0, "bitwise or"); - break; + case BINOP_LOGICAL_AND: + (*pc)++; + /* Generate the obvious sequence of tests and jumps. */ + gen_expr (exp, pc, ax, &value1); + gen_usual_unary (exp, 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 (exp, 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 = language_bool_type (exp->language_defn, exp->gdbarch); + break; - case BINOP_BITWISE_XOR: - gen_binop (ax, value, &value1, &value2, - aop_bit_xor, aop_bit_xor, 0, "bitwise exclusive-or"); - break; + case BINOP_LOGICAL_OR: + (*pc)++; + /* Generate the obvious sequence of tests and jumps. */ + gen_expr (exp, pc, ax, &value1); + gen_usual_unary (exp, ax, &value1); + if1 = ax_goto (ax, aop_if_goto); + gen_expr (exp, pc, ax, &value2); + gen_usual_unary (exp, 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 = language_bool_type (exp->language_defn, exp->gdbarch); + break; - default: - /* We should only list operators in the outer case statement - that we actually handle in the inner case statement. */ - internal_error (__FILE__, __LINE__, - _("gen_expr: op case sets don't match")); + case TERNOP_COND: + (*pc)++; + gen_expr (exp, pc, ax, &value1); + gen_usual_unary (exp, 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, + language_bool_type (exp->language_defn, exp->gdbarch)); + if1 = ax_goto (ax, aop_if_goto); + gen_expr (exp, pc, ax, &value2); + gen_usual_unary (exp, ax, &value2); + end = ax_goto (ax, aop_goto); + ax_label (ax, if1, ax->len); + gen_expr (exp, pc, ax, &value3); + gen_usual_unary (exp, ax, &value3); + ax_label (ax, end, ax->len); + /* This is arbitary - 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) + { + 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 (trace_kludge) + 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) + { + 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 (trace_kludge) + ax_tsv (ax, aop_tracev, tsv->number); + /* Trace state variables are always 64-bit integers. */ + value1.kind = axs_rvalue; + value1.type = builtin_type (exp->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 (trace_kludge) + 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 @@ -1575,12 +1624,12 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, variables it mentions get traced. */ case BINOP_COMMA: (*pc)++; - gen_expr (pc, ax, &value1); + 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 (pc, ax, value); + gen_expr (exp, pc, ax, value); /* It's the consumer's responsibility to trace the right operand. */ break; @@ -1594,7 +1643,7 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, break; case OP_VAR_VALUE: - gen_var_ref (ax, value, (*pc)[2].symbol); + gen_var_ref (exp->gdbarch, ax, value, (*pc)[2].symbol); (*pc) += 4; break; @@ -1603,32 +1652,52 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, const char *name = &(*pc)[2].string; int reg; (*pc) += 4 + BYTES_TO_EXP_ELEM ((*pc)[1].longconst + 1); - reg = frame_map_name_to_regnum (deprecated_safe_get_selected_frame (), - name, strlen (name)); + reg = user_reg_map_name_to_regnum (exp->gdbarch, name, strlen (name)); if (reg == -1) internal_error (__FILE__, __LINE__, _("Register $%s not available"), name); + if (reg >= gdbarch_num_regs (exp->gdbarch)) + error (_("'%s' is a pseudo-register; " + "GDB cannot yet trace pseudoregister contents."), + name); value->kind = axs_lvalue_register; value->u.reg = reg; - value->type = register_type (current_gdbarch, reg); + value->type = register_type (exp->gdbarch, reg); } break; case OP_INTERNALVAR: - error (_("GDB agent expressions cannot use convenience variables.")); + { + const char *name = internalvar_name ((*pc)[1].internalvar); + struct trace_state_variable *tsv; + (*pc) += 3; + tsv = find_trace_state_variable (name); + if (tsv) + { + ax_tsv (ax, aop_getv, tsv->number); + if (trace_kludge) + ax_tsv (ax, aop_tracev, tsv->number); + /* Trace state variables are always 64-bit integers. */ + value->kind = axs_rvalue; + value->type = builtin_type (exp->gdbarch)->builtin_long_long; + } + else + 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 (pc, ax, value); + gen_repeat (exp, pc, ax, value); break; case UNOP_CAST: { struct type *type = (*pc)[1].type; (*pc) += 3; - gen_expr (pc, ax, value); + gen_expr (exp, pc, ax, value); gen_cast (ax, value, type); } break; @@ -1637,7 +1706,7 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, { struct type *type = check_typedef ((*pc)[1].type); (*pc) += 3; - gen_expr (pc, ax, value); + gen_expr (exp, pc, ax, value); /* I'm not sure I understand UNOP_MEMVAL entirely. I think it's just a hack for dealing with minsyms; you take some integer constant, pretend it's the address of an lvalue of @@ -1654,45 +1723,50 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, case UNOP_PLUS: (*pc)++; /* + FOO is equivalent to 0 + FOO, which can be optimized. */ - gen_expr (pc, ax, value); - gen_usual_unary (ax, value); + gen_expr (exp, pc, ax, value); + gen_usual_unary (exp, ax, value); break; case UNOP_NEG: (*pc)++; /* -FOO is equivalent to 0 - FOO. */ - gen_int_literal (ax, &value1, (LONGEST) 0, builtin_type_int); - gen_usual_unary (ax, &value1); /* shouldn't do much */ - gen_expr (pc, ax, &value2); - gen_usual_unary (ax, &value2); - gen_usual_arithmetic (ax, &value1, &value2); - gen_sub (ax, value, &value1, &value2); + gen_int_literal (ax, &value1, 0, + builtin_type (exp->gdbarch)->builtin_int); + gen_usual_unary (exp, ax, &value1); /* shouldn't do much */ + gen_expr (exp, pc, ax, &value2); + gen_usual_unary (exp, ax, &value2); + gen_usual_arithmetic (exp, ax, &value1, &value2); + gen_binop (ax, value, &value1, &value2, aop_sub, aop_sub, 1, "negation"); break; case UNOP_LOGICAL_NOT: (*pc)++; - gen_expr (pc, ax, value); - gen_logical_not (ax, value); + gen_expr (exp, pc, ax, value); + gen_usual_unary (exp, ax, value); + gen_logical_not (ax, value, + language_bool_type (exp->language_defn, exp->gdbarch)); break; case UNOP_COMPLEMENT: (*pc)++; - gen_expr (pc, ax, value); + gen_expr (exp, pc, ax, value); + gen_usual_unary (exp, ax, value); + gen_integral_promotions (exp, ax, value); gen_complement (ax, value); break; case UNOP_IND: (*pc)++; - gen_expr (pc, ax, value); - gen_usual_unary (ax, value); - if (TYPE_CODE (value->type) != TYPE_CODE_PTR) + gen_expr (exp, pc, ax, value); + gen_usual_unary (exp, ax, value); + if (!pointer_type (value->type)) error (_("Argument of unary `*' is not a pointer.")); gen_deref (ax, value); break; case UNOP_ADDR: (*pc)++; - gen_expr (pc, ax, value); + gen_expr (exp, pc, ax, value); gen_address_of (ax, value); break; @@ -1701,7 +1775,8 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, /* 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 (pc, ax, value); + gen_sizeof (exp, pc, ax, value, + builtin_type (exp->gdbarch)->builtin_int); break; case STRUCTOP_STRUCT: @@ -1711,11 +1786,11 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, char *name = &(*pc)[2].string; (*pc) += 4 + BYTES_TO_EXP_ELEM (length + 1); - gen_expr (pc, ax, value); + gen_expr (exp, pc, ax, value); if (op == STRUCTOP_STRUCT) - gen_struct_ref (ax, value, name, ".", "structure or union"); + gen_struct_ref (exp, ax, value, name, ".", "structure or union"); else if (op == STRUCTOP_PTR) - gen_struct_ref (ax, value, name, "->", + gen_struct_ref (exp, ax, value, name, "->", "pointer to a structure or union"); else /* If this `if' chain doesn't handle it, then the case list @@ -1725,6 +1800,27 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, } break; + case OP_THIS: + { + char *this_name; + struct symbol *func, *sym; + struct block *b; + + func = block_linkage_function (block_for_pc (ax->scope)); + this_name = language_def (SYMBOL_LANGUAGE (func))->la_name_of_this; + b = SYMBOL_BLOCK_VALUE (func); + + /* Calling lookup_block_symbol is necessary to get the LOC_REGISTER + symbol instead of the LOC_ARG one (if both exist). */ + sym = lookup_block_symbol (b, this_name, NULL, VAR_DOMAIN); + if (!sym) + error (_("no `%s' found"), this_name); + + gen_var_ref (exp->gdbarch, ax, value, sym); + (*pc) += 2; + } + break; + case OP_TYPE: error (_("Attempt to use a type name as an expression.")); @@ -1732,60 +1828,188 @@ gen_expr (union exp_element **pc, struct agent_expr *ax, error (_("Unsupported operator in expression.")); } } - +/* This handles the middle-to-right-side of code generation for binary + expressions, which is shared between regular binary operations and + assign-modify (+= and friends) expressions. */ -/* Generating bytecode from GDB expressions: driver */ - -/* Given a GDB expression EXPR, produce a string of agent bytecode - which computes its value. Return the agent expression, and set - *VALUE to describe its type, and whether it's an lvalue or rvalue. */ -struct agent_expr * -expr_to_agent (struct expression *expr, struct axs_value *value) +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) { - struct cleanup *old_chain = 0; - struct agent_expr *ax = new_agent_expr (0); - union exp_element *pc; + gen_expr (exp, pc, ax, value2); + gen_usual_unary (exp, ax, value2); + gen_usual_arithmetic (exp, ax, value1, value2); + switch (op) + { + case BINOP_ADD: + if (TYPE_CODE (value1->type) == TYPE_CODE_INT + && pointer_type (value2->type)) + { + /* Swap the values and proceed normally. */ + ax_simple (ax, aop_swap); + gen_ptradd (ax, value, value2, value1); + } + else if (pointer_type (value1->type) + && TYPE_CODE (value2->type) == TYPE_CODE_INT) + gen_ptradd (ax, value, value1, value2); + else + gen_binop (ax, value, value1, value2, + aop_add, aop_add, 1, "addition"); + break; + case BINOP_SUB: + if (pointer_type (value1->type) + && TYPE_CODE (value2->type) == TYPE_CODE_INT) + gen_ptrsub (ax,value, value1, value2); + else if (pointer_type (value1->type) + && pointer_type (value2->type)) + /* FIXME --- result type should be ptrdiff_t */ + gen_ptrdiff (ax, value, value1, value2, + builtin_type (exp->gdbarch)->builtin_long); + else + gen_binop (ax, value, value1, value2, + aop_sub, aop_sub, 1, "subtraction"); + break; + case BINOP_MUL: + gen_binop (ax, value, value1, value2, + aop_mul, aop_mul, 1, "multiplication"); + break; + case BINOP_DIV: + gen_binop (ax, value, value1, value2, + aop_div_signed, aop_div_unsigned, 1, "division"); + break; + case BINOP_REM: + gen_binop (ax, value, value1, value2, + aop_rem_signed, aop_rem_unsigned, 1, "remainder"); + break; + case BINOP_SUBSCRIPT: + { + struct type *type; - old_chain = make_cleanup_free_agent_expr (ax); + if (binop_types_user_defined_p (op, value1->type, value2->type)) + { + error (_("\ +cannot subscript requested type: cannot call user defined functions")); + } + else + { + /* If the user attempts to subscript something that is not + an array or pointer type (like a plain int variable for + example), then report this as an error. */ + type = check_typedef (value1->type); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_PTR) + { + if (TYPE_NAME (type)) + error (_("cannot subscript something of type `%s'"), + TYPE_NAME (type)); + else + error (_("cannot subscript requested type")); + } + } + + gen_ptradd (ax, value, value1, value2); + gen_deref (ax, value); + break; + } + case BINOP_BITWISE_AND: + gen_binop (ax, value, value1, value2, + aop_bit_and, aop_bit_and, 0, "bitwise and"); + break; - pc = expr->elts; - trace_kludge = 0; - gen_expr (&pc, ax, value); + case BINOP_BITWISE_IOR: + gen_binop (ax, value, value1, value2, + aop_bit_or, aop_bit_or, 0, "bitwise or"); + break; + + case BINOP_BITWISE_XOR: + gen_binop (ax, value, value1, value2, + aop_bit_xor, aop_bit_xor, 0, "bitwise exclusive-or"); + break; - /* We have successfully built the agent expr, so cancel the cleanup - request. If we add more cleanups that we always want done, this - will have to get more complicated. */ - discard_cleanups (old_chain); - return ax; -} + case BINOP_EQUAL: + gen_binop (ax, value, value1, value2, + aop_equal, aop_equal, 0, "equal"); + break; + + case BINOP_NOTEQUAL: + gen_binop (ax, value, value1, value2, + aop_equal, aop_equal, 0, "equal"); + gen_logical_not (ax, value, + language_bool_type (exp->language_defn, + exp->gdbarch)); + break; + + case BINOP_LESS: + gen_binop (ax, value, value1, value2, + aop_less_signed, aop_less_unsigned, 0, "less than"); + break; + + case BINOP_GTR: + ax_simple (ax, aop_swap); + gen_binop (ax, value, value1, value2, + aop_less_signed, aop_less_unsigned, 0, "less than"); + break; + + case BINOP_LEQ: + ax_simple (ax, aop_swap); + gen_binop (ax, value, value1, value2, + aop_less_signed, aop_less_unsigned, 0, "less than"); + gen_logical_not (ax, value, + language_bool_type (exp->language_defn, + exp->gdbarch)); + break; + case BINOP_GEQ: + gen_binop (ax, value, value1, value2, + aop_less_signed, aop_less_unsigned, 0, "less than"); + gen_logical_not (ax, value, + language_bool_type (exp->language_defn, + exp->gdbarch)); + break; + + default: + /* We should only list operators in the outer case statement + that we actually handle in the inner case statement. */ + internal_error (__FILE__, __LINE__, + _("gen_expr: op case sets don't match")); + } +} + -#if 0 /* not used */ -/* Given a GDB expression EXPR denoting an lvalue in memory, produce a - string of agent bytecode which will leave its address and size on - the top of stack. Return the agent expression. +/* Given a single variable and a scope, generate bytecodes to trace + its value. This is for use in situations where we have only a + variable's name, and no parsed expression; for instance, when the + name comes from a list of local variables of a function. */ - Not sure this function is useful at all. */ struct agent_expr * -expr_to_address_and_size (struct expression *expr) +gen_trace_for_var (CORE_ADDR scope, struct symbol *var) { + struct cleanup *old_chain = 0; + struct agent_expr *ax = new_agent_expr (scope); struct axs_value value; - struct agent_expr *ax = expr_to_agent (expr, &value); - /* Complain if the result is not a memory lvalue. */ - if (value.kind != axs_lvalue_memory) - { - free_agent_expr (ax); - error (_("Expression does not denote an object in memory.")); - } + old_chain = make_cleanup_free_agent_expr (ax); + + trace_kludge = 1; + gen_var_ref (NULL, ax, &value, var); + + /* Make sure we record the final object, and get rid of it. */ + gen_traced_pop (ax, &value); - /* Push the object's size on the stack. */ - ax_const_l (ax, TYPE_LENGTH (value.type)); + /* Oh, and terminate. */ + ax_simple (ax, aop_end); + /* We have successfully built the agent expr, so cancel the cleanup + request. If we add more cleanups that we always want done, this + will have to get more complicated. */ + discard_cleanups (old_chain); return ax; } -#endif + +/* Generating bytecode from GDB expressions: driver */ /* Given a GDB expression EXPR, return bytecode to trace its value. The result will use the `trace' and `trace_quick' bytecodes to @@ -1804,7 +2028,7 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr) pc = expr->elts; trace_kludge = 1; - gen_expr (&pc, ax, &value); + gen_expr (expr, &pc, ax, &value); /* Make sure we record the final object, and get rid of it. */ gen_traced_pop (ax, &value); @@ -1819,6 +2043,37 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr) return ax; } +/* Given a GDB expression EXPR, return a bytecode sequence that will + evaluate and return a result. The bytecodes will do a direct + evaluation, using the current data on the target, rather than + recording blocks of memory and registers for later use, as + gen_trace_for_expr does. The generated bytecode sequence leaves + the result of expression evaluation on the top of the stack. */ + +struct agent_expr * +gen_eval_for_expr (CORE_ADDR scope, struct expression *expr) +{ + struct cleanup *old_chain = 0; + struct agent_expr *ax = new_agent_expr (scope); + union exp_element *pc; + struct axs_value value; + + old_chain = make_cleanup_free_agent_expr (ax); + + pc = expr->elts; + trace_kludge = 0; + gen_expr (expr, &pc, ax, &value); + + /* Oh, and terminate. */ + ax_simple (ax, aop_end); + + /* We have successfully built the agent expr, so cancel the cleanup + request. If we add more cleanups that we always want done, this + will have to get more complicated. */ + discard_cleanups (old_chain); + return ax; +} + static void agent_command (char *exp, int from_tty) { @@ -1849,6 +2104,41 @@ agent_command (char *exp, int from_tty) do_cleanups (old_chain); dont_repeat (); } + +/* Parse the given expression, compile it into an agent expression + that does direct evaluation, and display the resulting + expression. */ + +static void +agent_eval_command (char *exp, int from_tty) +{ + struct cleanup *old_chain = 0; + struct expression *expr; + struct agent_expr *agent; + struct frame_info *fi = get_current_frame (); /* need current scope */ + + /* We don't deal with overlay debugging at the moment. We need to + think more carefully about this. If you copy this code into + another command, change the error message; the user shouldn't + have to know anything about agent expressions. */ + if (overlay_debugging) + error (_("GDB can't do agent expression translation with overlays.")); + + if (exp == 0) + error_no_arg (_("expression to translate")); + + expr = parse_expression (exp); + old_chain = make_cleanup (free_current_contents, &expr); + agent = gen_eval_for_expr (get_frame_pc (fi), expr); + make_cleanup_free_agent_expr (agent); + ax_print (gdb_stdout, agent); + + /* It would be nice to call ax_reqs here to gather some general info + about the expression, and then print out the result. */ + + do_cleanups (old_chain); + dont_repeat (); +} /* Initialization code. */ @@ -1858,6 +2148,10 @@ void _initialize_ax_gdb (void) { add_cmd ("agent", class_maintenance, agent_command, - _("Translate an expression into remote agent bytecode."), + _("Translate an expression into remote agent bytecode for tracing."), + &maintenancelist); + + add_cmd ("agent-eval", class_maintenance, agent_eval_command, + _("Translate an expression into remote agent bytecode for evaluation."), &maintenancelist); }