X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fax-gdb.c;h=739677f0f3e00874fe566c2d50e5cf591f0105fb;hb=0d5cff5020224cfd67bc3d6e30b158105d03a324;hp=e0d6ce581c637dd791ed1c4c5fb3b781a04ff4d2;hpb=d0352a18a504a4e7b761f6b3264cf11347d8d056;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index e0d6ce581c..739677f0f3 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -1,11 +1,13 @@ -/* GDB-specific functions for operating on agent expressions - Copyright 1998, 2000 Free Software Foundation, Inc. +/* GDB-specific functions for operating on agent expressions. + + Copyright (C) 1998-2001, 2003, 2007-2012 Free Software Foundation, + Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,14 +16,13 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "symtab.h" #include "symfile.h" #include "gdbtypes.h" +#include "language.h" #include "value.h" #include "expression.h" #include "command.h" @@ -30,6 +31,19 @@ #include "target.h" #include "ax.h" #include "ax-gdb.h" +#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" +#include "cp-support.h" +#include "arch-utils.h" + +#include "valprint.h" +#include "c-lang.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, @@ -49,7 +63,7 @@ -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ /* There's a standard order to the arguments of these functions: union exp_element ** --- pointer into expression @@ -60,7 +74,8 @@ 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_traced_pop (struct gdbarch *, struct agent_expr *, + struct axs_value *); static void gen_sign_extend (struct agent_expr *, struct type *); static void gen_extend (struct agent_expr *, struct type *); @@ -68,11 +83,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); @@ -82,54 +97,75 @@ 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_primitive_field (struct expression *exp, + struct agent_expr *ax, + struct axs_value *value, + int offset, int fieldno, struct type *type); +static int gen_struct_ref_recursive (struct expression *exp, + struct agent_expr *ax, + struct axs_value *value, + char *field, int offset, + struct type *type); +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, - struct agent_expr *ax, struct axs_value *value); -static void gen_sizeof (union exp_element **pc, +static void gen_static_field (struct gdbarch *gdbarch, + 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_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 print_axs_value (struct ui_file *f, struct axs_value * value); static void agent_command (char *exp, int from_tty); @@ -154,8 +190,7 @@ static void agent_command (char *exp, int from_tty); proletariat? */ static struct value * -const_var_ref (var) - struct symbol *var; +const_var_ref (struct symbol *var) { struct type *type = SYMBOL_TYPE (var); @@ -178,8 +213,7 @@ const_var_ref (var) advanced to the end of it. If we return zero, *PC could be anywhere. */ static struct value * -const_expr (pc) - union exp_element **pc; +const_expr (union exp_element **pc) { enum exp_opcode op = (*pc)->opcode; struct value *v1; @@ -190,6 +224,7 @@ const_expr (pc) { struct type *type = (*pc)[1].type; LONGEST k = (*pc)[2].longconst; + (*pc) += 4; return value_from_longest (type, k); } @@ -197,6 +232,7 @@ const_expr (pc) case OP_VAR_VALUE: { struct value *v = const_var_ref ((*pc)[2].symbol); + (*pc) += 4; return v; } @@ -220,8 +256,7 @@ const_expr (pc) /* Like const_expr, but guarantee also that *PC is undisturbed if the expression is not constant. */ static struct value * -maybe_const_expr (pc) - union exp_element **pc; +maybe_const_expr (union exp_element **pc) { union exp_element *tentative_pc = *pc; struct value *v = const_expr (&tentative_pc); @@ -301,28 +336,99 @@ maybe_const_expr (pc) Setting the flag trace_kludge to non-zero enables the code that emits the trace bytecodes at the appropriate points. */ -static int trace_kludge; +int trace_kludge; + +/* Inspired by trace_kludge, this indicates that pointers to chars + should get an added tracenz bytecode to record nonzero bytes, up to + a length that is the value of trace_string_kludge. */ +int trace_string_kludge; + +/* Scan for all static fields in the given class, including any base + classes, and generate tracing bytecodes for each. */ + +static void +gen_trace_static_fields (struct gdbarch *gdbarch, + struct agent_expr *ax, + struct type *type) +{ + int i, nbases = TYPE_N_BASECLASSES (type); + struct axs_value value; + + CHECK_TYPEDEF (type); + + for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--) + { + if (field_is_static (&TYPE_FIELD (type, i))) + { + gen_static_field (gdbarch, ax, &value, type, i); + if (value.optimized_out) + continue; + switch (value.kind) + { + case axs_lvalue_memory: + { + int length = TYPE_LENGTH (check_typedef (value.type)); + + ax_const_l (ax, length); + ax_simple (ax, aop_trace); + } + break; + + case axs_lvalue_register: + /* We don't actually need the register's value to be pushed, + just note that we need it to be collected. */ + ax_reg_mask (ax, value.u.reg); + + default: + break; + } + } + } + + /* Now scan through base classes recursively. */ + for (i = 0; i < nbases; i++) + { + struct type *basetype = check_typedef (TYPE_BASECLASS (type, i)); + + gen_trace_static_fields (gdbarch, ax, basetype); + } +} /* Trace the lvalue on the stack, if it needs it. In either case, pop the value. Useful on the left side of a comma, and at the end of an expression being used for tracing. */ static void -gen_traced_pop (ax, value) - struct agent_expr *ax; - struct axs_value *value; +gen_traced_pop (struct gdbarch *gdbarch, + struct agent_expr *ax, struct axs_value *value) { + int string_trace = 0; + if (trace_string_kludge + && TYPE_CODE (value->type) == TYPE_CODE_PTR + && c_textual_element_type (check_typedef (TYPE_TARGET_TYPE (value->type)), + 's')) + string_trace = 1; + if (trace_kludge) switch (value->kind) { case axs_rvalue: - /* We don't trace rvalues, just the lvalues necessary to - produce them. So just dispose of this value. */ - ax_simple (ax, aop_pop); + if (string_trace) + { + ax_const_l (ax, trace_string_kludge); + ax_simple (ax, aop_tracenz); + } + else + /* We don't trace rvalues, just the lvalues necessary to + produce them. So just dispose of this value. */ + ax_simple (ax, aop_pop); break; case axs_lvalue_memory: { - int length = TYPE_LENGTH (value->type); + int length = TYPE_LENGTH (check_typedef (value->type)); + + if (string_trace) + ax_simple (ax, aop_dup); /* There's no point in trying to use a trace_quick bytecode here, since "trace_quick SIZE pop" is three bytes, whereas @@ -331,20 +437,42 @@ gen_traced_pop (ax, value) work correctly for objects with large sizes. */ ax_const_l (ax, length); ax_simple (ax, aop_trace); + + if (string_trace) + { + ax_simple (ax, aop_ref32); + ax_const_l (ax, trace_string_kludge); + ax_simple (ax, aop_tracenz); + } } break; case axs_lvalue_register: - /* We need to mention the register somewhere in the bytecode, - so ax_reqs will pick it up and add it to the mask of - registers used. */ - ax_reg (ax, value->u.reg); - ax_simple (ax, aop_pop); + /* We don't actually need the register's value to be on the + stack, and the target will get heartburn if the register is + larger than will fit in a stack, so just mark it for + collection and be done with it. */ + ax_reg_mask (ax, value->u.reg); + + /* But if the register points to a string, assume the value + will fit on the stack and push it anyway. */ + if (string_trace) + { + ax_reg (ax, value->u.reg); + ax_const_l (ax, trace_string_kludge); + ax_simple (ax, aop_tracenz); + } break; } else /* If we're not tracing, just pop the value. */ ax_simple (ax, aop_pop); + + /* To trace C++ classes with static fields stored elsewhere. */ + if (trace_kludge + && (TYPE_CODE (value->type) == TYPE_CODE_STRUCT + || TYPE_CODE (value->type) == TYPE_CODE_UNION)) + gen_trace_static_fields (gdbarch, ax, value->type); } @@ -354,13 +482,11 @@ gen_traced_pop (ax, value) /* Assume that the lower bits of the top of the stack is a value of type TYPE, and the upper bits are zero. Sign-extend if necessary. */ static void -gen_sign_extend (ax, type) - struct agent_expr *ax; - struct type *type; +gen_sign_extend (struct agent_expr *ax, struct type *type) { /* Do we need to sign-extend this? */ if (!TYPE_UNSIGNED (type)) - ax_ext (ax, type->length * TARGET_CHAR_BIT); + ax_ext (ax, TYPE_LENGTH (type) * TARGET_CHAR_BIT); } @@ -368,11 +494,10 @@ gen_sign_extend (ax, type) TYPE, and the upper bits are garbage. Sign-extend or truncate as needed. */ static void -gen_extend (ax, type) - struct agent_expr *ax; - struct type *type; +gen_extend (struct agent_expr *ax, struct type *type) { - int bits = type->length * TARGET_CHAR_BIT; + int bits = TYPE_LENGTH (type) * TARGET_CHAR_BIT; + /* I just had to. */ ((TYPE_UNSIGNED (type) ? ax_zero_ext : ax_ext) (ax, bits)); } @@ -382,9 +507,7 @@ gen_extend (ax, type) to TYPE"; generate code to fetch its value. Note that TYPE is the target type, not the pointer type. */ static void -gen_fetch (ax, type) - struct agent_expr *ax; - struct type *type; +gen_fetch (struct agent_expr *ax, struct type *type) { if (trace_kludge) { @@ -392,15 +515,17 @@ gen_fetch (ax, type) ax_trace_quick (ax, TYPE_LENGTH (type)); } - switch (type->code) + switch (TYPE_CODE (type)) { case TYPE_CODE_PTR: + case TYPE_CODE_REF: case TYPE_CODE_ENUM: case TYPE_CODE_INT: case TYPE_CODE_CHAR: + case TYPE_CODE_BOOL: /* It's a scalar value, so we know how to dereference it. How many bytes long is it? */ - switch (type->length) + switch (TYPE_LENGTH (type)) { case 8 / TARGET_CHAR_BIT: ax_simple (ax, aop_ref8); @@ -420,7 +545,8 @@ gen_fetch (ax, type) implementing something we should be (this code's fault). In any case, it's a bug the user shouldn't see. */ default: - internal_error ("ax-gdb.c (gen_fetch): strange size"); + internal_error (__FILE__, __LINE__, + _("gen_fetch: strange size")); } gen_sign_extend (ax, type); @@ -431,7 +557,8 @@ gen_fetch (ax, type) pointer (other code's fault), or we're not implementing something we should be (this code's fault). In any case, it's a bug the user shouldn't see. */ - internal_error ("ax-gdb.c (gen_fetch): bad type code"); + internal_error (__FILE__, __LINE__, + _("gen_fetch: bad type code")); } } @@ -440,9 +567,7 @@ gen_fetch (ax, type) right shift it by -DISTANCE bits if DISTANCE < 0. This generates unsigned (logical) right shifts. */ static void -gen_left_shift (ax, distance) - struct agent_expr *ax; - int distance; +gen_left_shift (struct agent_expr *ax, int distance) { if (distance > 0) { @@ -463,12 +588,13 @@ gen_left_shift (ax, distance) /* Generate code to push the base address of the argument portion of the top stack frame. */ static void -gen_frame_args_address (ax) - struct agent_expr *ax; +gen_frame_args_address (struct gdbarch *gdbarch, struct agent_expr *ax) { - long frame_reg, frame_offset; + int frame_reg; + LONGEST frame_offset; - TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset); + gdbarch_virtual_frame_pointer (gdbarch, + ax->scope, &frame_reg, &frame_offset); ax_reg (ax, frame_reg); gen_offset (ax, frame_offset); } @@ -477,12 +603,13 @@ gen_frame_args_address (ax) /* Generate code to push the base address of the locals portion of the top stack frame. */ static void -gen_frame_locals_address (ax) - struct agent_expr *ax; +gen_frame_locals_address (struct gdbarch *gdbarch, struct agent_expr *ax) { - long frame_reg, frame_offset; + int frame_reg; + LONGEST frame_offset; - TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset); + gdbarch_virtual_frame_pointer (gdbarch, + ax->scope, &frame_reg, &frame_offset); ax_reg (ax, frame_reg); gen_offset (ax, frame_offset); } @@ -494,9 +621,7 @@ gen_frame_locals_address (ax) programming in ML, it would be clearer why these are the same thing. */ static void -gen_offset (ax, offset) - struct agent_expr *ax; - int offset; +gen_offset (struct agent_expr *ax, int offset) { /* It would suffice to simply push the offset and add it, but this makes it easier to read positive and negative offsets in the @@ -518,9 +643,7 @@ gen_offset (ax, offset) address (stack frame, base register, etc.) Generate code to add VAR's value to the top of the stack. */ static void -gen_sym_offset (ax, var) - struct agent_expr *ax; - struct symbol *var; +gen_sym_offset (struct agent_expr *ax, struct symbol *var) { gen_offset (ax, SYMBOL_VALUE (var)); } @@ -530,13 +653,12 @@ gen_sym_offset (ax, var) symbol VAR. Set VALUE to describe the result. */ static void -gen_var_ref (ax, value, var) - 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. */ + /* Dereference any typedefs. */ value->type = check_typedef (SYMBOL_TYPE (var)); + value->optimized_out = 0; /* I'm imitating the code in read_var_value. */ switch (SYMBOL_CLASS (var)) @@ -552,7 +674,9 @@ gen_var_ref (ax, value, var) break; case LOC_CONST_BYTES: - internal_error ("ax-gdb.c (gen_var_ref): LOC_CONST_BYTES symbols are not supported"); + internal_error (__FILE__, __LINE__, + _("gen_var_ref: LOC_CONST_BYTES " + "symbols are not supported")); /* Variable at a fixed location in memory. Easy. */ case LOC_STATIC: @@ -562,37 +686,29 @@ gen_var_ref (ax, value, 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; case LOC_TYPEDEF: - error ("Cannot compute value of typedef `%s'.", - SYMBOL_SOURCE_NAME (var)); + error (_("Cannot compute value of typedef `%s'."), + SYMBOL_PRINT_NAME (var)); break; case LOC_BLOCK: @@ -601,29 +717,29 @@ gen_var_ref (ax, value, 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 (SYMBOL_NAME (var), NULL, NULL); + = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (var), NULL, NULL); + if (!msym) - error ("Couldn't resolve symbol `%s'.", SYMBOL_SOURCE_NAME (var)); + error (_("Couldn't resolve symbol `%s'."), SYMBOL_PRINT_NAME (var)); /* Push the address of the variable. */ ax_const_l (ax, SYMBOL_VALUE_ADDRESS (msym)); @@ -631,14 +747,24 @@ gen_var_ref (ax, value, var) } break; + case LOC_COMPUTED: + /* FIXME: cagney/2004-01-26: It should be possible to + 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_COMPUTED_OPS (var)->tracepoint_var_ref (var, gdbarch, ax, value); + break; + case LOC_OPTIMIZED_OUT: - error ("The variable `%s' has been optimized out.", - SYMBOL_SOURCE_NAME (var)); + /* Flag this, but don't say anything; leave it up to callers to + warn the user. */ + value->optimized_out = 1; break; default: - error ("Cannot find value of botched symbol `%s'.", - SYMBOL_SOURCE_NAME (var)); + error (_("Cannot find value of botched symbol `%s'."), + SYMBOL_PRINT_NAME (var)); break; } } @@ -648,15 +774,12 @@ gen_var_ref (ax, value, var) /* Generating bytecode from GDB expressions: literals */ static void -gen_int_literal (ax, value, k, type) - struct agent_expr *ax; - struct axs_value *value; - LONGEST k; - struct type *type; +gen_int_literal (struct agent_expr *ax, struct axs_value *value, LONGEST k, + struct type *type) { ax_const_l (ax, k); value->kind = axs_rvalue; - value->type = type; + value->type = check_typedef (type); } @@ -667,10 +790,17 @@ gen_int_literal (ax, value, k, type) try to make an rvalue out of it. Signal an error if we can't do that. */ static void -require_rvalue (ax, value) - struct agent_expr *ax; - struct axs_value *value; +require_rvalue (struct agent_expr *ax, struct axs_value *value) { + /* Only deal with scalars, structs and such may be too large + to fit in a stack entry. */ + value->type = check_typedef (value->type); + if (TYPE_CODE (value->type) == TYPE_CODE_ARRAY + || TYPE_CODE (value->type) == TYPE_CODE_STRUCT + || TYPE_CODE (value->type) == TYPE_CODE_UNION + || TYPE_CODE (value->type) == TYPE_CODE_FUNC) + error (_("Value not scalar: cannot be an rvalue.")); + switch (value->kind) { case axs_rvalue: @@ -714,16 +844,15 @@ require_rvalue (ax, value) lvalue through unchanged, and let `+' raise an error. */ static void -gen_usual_unary (ax, value) - 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 the stack. Should we tweak the type? */ /* Some types require special handling. */ - switch (value->type->code) + switch (TYPE_CODE (value->type)) { /* Functions get converted to a pointer to the function. */ case TYPE_CODE_FUNC: @@ -736,6 +865,7 @@ gen_usual_unary (ax, value) case TYPE_CODE_ARRAY: { struct type *elements = TYPE_TARGET_TYPE (value->type); + value->type = lookup_pointer_type (elements); value->kind = axs_rvalue; /* We don't need to generate any code; the address of the array @@ -749,9 +879,10 @@ gen_usual_unary (ax, value) case TYPE_CODE_UNION: return; - /* If the value is an enum, call it an integer. */ + /* If the value is an enum or a bool, call it an integer. */ case TYPE_CODE_ENUM: - value->type = builtin_type_int; + case TYPE_CODE_BOOL: + value->type = builtin_type (exp->gdbarch)->builtin_int; break; } @@ -763,8 +894,7 @@ gen_usual_unary (ax, value) /* Return non-zero iff the type TYPE1 is considered "wider" than the type TYPE2, according to the rules described in gen_usual_arithmetic. */ static int -type_wider_than (type1, type2) - struct type *type1, *type2; +type_wider_than (struct type *type1, struct type *type2) { return (TYPE_LENGTH (type1) > TYPE_LENGTH (type2) || (TYPE_LENGTH (type1) == TYPE_LENGTH (type2) @@ -775,8 +905,7 @@ type_wider_than (type1, type2) /* Return the "wider" of the two types TYPE1 and TYPE2. */ static struct type * -max_type (type1, type2) - struct type *type1, *type2; +max_type (struct type *type1, struct type *type2) { return type_wider_than (type1, type2) ? type1 : type2; } @@ -784,9 +913,7 @@ max_type (type1, type2) /* Generate code to convert a scalar value of type FROM to type TO. */ static void -gen_conversion (ax, from, to) - struct agent_expr *ax; - struct type *from, *to; +gen_conversion (struct agent_expr *ax, struct type *from, struct type *to) { /* Perhaps there is a more graceful way to state these rules. */ @@ -816,10 +943,9 @@ gen_conversion (ax, from, to) /* Return non-zero iff the type FROM will require any bytecodes to be emitted to be converted to the type TO. */ static int -is_nontrivial_conversion (from, to) - struct type *from, *to; +is_nontrivial_conversion (struct type *from, struct type *to) { - struct agent_expr *ax = new_agent_expr (0); + struct agent_expr *ax = new_agent_expr (NULL, 0); int nontrivial; /* Actually generate the code, and see if anything came out. At the @@ -841,9 +967,8 @@ is_nontrivial_conversion (from, 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 (ax, value1, value2) - struct agent_expr *ax; - struct axs_value *value1, *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 @@ -854,7 +979,7 @@ gen_usual_arithmetic (ax, value1, value2) 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. */ @@ -870,7 +995,7 @@ gen_usual_arithmetic (ax, value1, value2) ax_simple (ax, aop_swap); } - value1->type = value2->type = target; + value1->type = value2->type = check_typedef (target); } } @@ -879,39 +1004,38 @@ gen_usual_arithmetic (ax, value1, value2) the value on the top of the stack, as described by VALUE. Assume the value has integral type. */ static void -gen_integral_promotions (ax, value) - 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; } } /* Generate code for a cast to TYPE. */ static void -gen_cast (ax, value, type) - struct agent_expr *ax; - struct axs_value *value; - struct type *type; +gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type) { /* GCC does allow casts to yield lvalues, so this should be fixed before merging these changes into the trunk. */ require_rvalue (ax, value); - /* Dereference typedefs. */ + /* Dereference typedefs. */ type = check_typedef (type); - switch (type->code) + 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; @@ -920,15 +1044,15 @@ gen_cast (ax, value, type) case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: case TYPE_CODE_FUNC: - error ("Illegal type cast: intended type must be scalar."); + error (_("Invalid type cast: intended type must be scalar.")); case TYPE_CODE_ENUM: + case TYPE_CODE_BOOL: /* 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: @@ -943,7 +1067,7 @@ gen_cast (ax, value, type) break; default: - error ("Casts to requested type are not yet implemented."); + error (_("Casts to requested type are not yet implemented.")); } value->type = type; @@ -956,120 +1080,96 @@ gen_cast (ax, value, type) /* Scale the integer on the top of the stack by the size of the target of the pointer type TYPE. */ static void -gen_scale (ax, op, type) - struct agent_expr *ax; - enum agent_op op; - struct type *type; +gen_scale (struct agent_expr *ax, enum agent_op op, struct type *type) { struct type *element = TYPE_TARGET_TYPE (type); - if (element->length != 1) + if (TYPE_LENGTH (element) != 1) { - ax_const_l (ax, element->length); + ax_const_l (ax, TYPE_LENGTH (element)); ax_simple (ax, op); } } -/* 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 (ax, value, value1, value2, name) - struct agent_expr *ax; - struct axs_value *value, *value1, *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 (value1->type->code == TYPE_CODE_INT - && value2->type->code == 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 (value1->type->code == TYPE_CODE_PTR - && value2->type->code == 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 (value1->type->code == TYPE_CODE_INT - && value2->type->code == TYPE_CODE_INT) - { - ax_simple (ax, aop_add); - gen_extend (ax, value1->type); /* Catch overflow. */ - value->type = value1->type; - } - else - error ("Illegal 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 (ax, value, value1, value2) - struct agent_expr *ax; - struct axs_value *value, *value1, *value2; +gen_ptrdiff (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2, + struct type *result_type) { - if (value1->type->code == TYPE_CODE_PTR) - { - /* Is it PTR - INT? */ - if (value2->type->code == 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 (value2->type->code == 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."); - } +an integer nor a pointer of the same type.")); - /* Must be number + number. */ - else if (value1->type->code == TYPE_CODE_INT - && value2->type->code == TYPE_CODE_INT) - { - ax_simple (ax, aop_sub); - gen_extend (ax, value1->type); /* Catch overflow. */ - value->type = value1->type; - } + ax_simple (ax, aop_sub); + gen_scale (ax, aop_div_unsigned, value1->type); + value->type = result_type; + value->kind = axs_rvalue; +} +static void +gen_equal (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2, + struct type *result_type) +{ + if (pointer_type (value1->type) || pointer_type (value2->type)) + ax_simple (ax, aop_equal); else - error ("Illegal combination of types in subtraction."); + gen_binop (ax, value, value1, value2, + aop_equal, aop_equal, 0, "equal"); + value->type = result_type; + value->kind = axs_rvalue; +} +static void +gen_less (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2, + struct type *result_type) +{ + if (pointer_type (value1->type) || pointer_type (value2->type)) + ax_simple (ax, aop_less_unsigned); + else + gen_binop (ax, value, value1, value2, + aop_less_signed, aop_less_unsigned, 0, "less than"); + value->type = result_type; value->kind = axs_rvalue; } @@ -1080,17 +1180,15 @@ an integer nor a pointer of the same type."); result needs to be extended. NAME is the English name of the operator, used in error messages */ static void -gen_binop (ax, value, value1, value2, op, op_unsigned, may_carry, name) - struct agent_expr *ax; - struct axs_value *value, *value1, *value2; - enum agent_op op, op_unsigned; - int may_carry; - char *name; +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) { /* We only handle INT op INT. */ - if ((value1->type->code != TYPE_CODE_INT) - || (value2->type->code != TYPE_CODE_INT)) - error ("Illegal combination of types in %s.", name); + if ((TYPE_CODE (value1->type) != TYPE_CODE_INT) + || (TYPE_CODE (value2->type) != TYPE_CODE_INT)) + error (_("Invalid combination of types in %s."), name); ax_simple (ax, TYPE_UNSIGNED (value1->type) ? op_unsigned : op); @@ -1102,30 +1200,24 @@ gen_binop (ax, value, value1, value2, op, op_unsigned, may_carry, name) static void -gen_logical_not (ax, value) - 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 ("Illegal type of operand to `!'."); + 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; } static void -gen_complement (ax, value) - struct agent_expr *ax; - struct axs_value *value; +gen_complement (struct agent_expr *ax, struct axs_value *value) { if (TYPE_CODE (value->type) != TYPE_CODE_INT) - error ("Illegal type of operand to `~'."); + 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); } @@ -1136,14 +1228,13 @@ gen_complement (ax, value) /* Dereference the value on the top of the stack. */ static void -gen_deref (ax, value) - struct agent_expr *ax; - struct axs_value *value; +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 (value->type->code != TYPE_CODE_PTR) - internal_error ("ax-gdb.c (gen_deref): expected a pointer"); + if (!pointer_type (value->type)) + internal_error (__FILE__, __LINE__, + _("gen_deref: expected a pointer")); /* We've got an rvalue now, which is a pointer. We want to yield an lvalue, whose address is exactly that pointer. So we don't @@ -1151,21 +1242,21 @@ gen_deref (ax, 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)); - value->kind = ((value->type->code == TYPE_CODE_FUNC) + 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); } /* Produce the address of the lvalue on the top of the stack. */ static void -gen_address_of (ax, value) - struct agent_expr *ax; - struct axs_value *value; +gen_address_of (struct agent_expr *ax, struct axs_value *value) { /* Special case for taking the address of a function. The ANSI standard describes this as a special case, too, so this arrangement is not without motivation. */ - if (value->type->code == TYPE_CODE_FUNC) + if (TYPE_CODE (value->type) == TYPE_CODE_FUNC) /* The value's already an rvalue on the stack, so we just need to change the type. */ value->type = lookup_pointer_type (value->type); @@ -1173,10 +1264,10 @@ gen_address_of (ax, value) switch (value->kind) { case axs_rvalue: - error ("Operand of `&' is an rvalue, which has no address."); + error (_("Operand of `&' is an rvalue, which has no address.")); case axs_lvalue_register: - error ("Operand of `&' is in a register, and has no address."); + error (_("Operand of `&' is in a register, and has no address.")); case axs_lvalue_memory: value->kind = axs_rvalue; @@ -1185,58 +1276,18 @@ gen_address_of (ax, value) } } - -/* A lot of this stuff will have to change to support C++. But we're - not going to deal with that at the moment. */ - -/* Find the field in the structure type TYPE named NAME, and return - its index in TYPE's field array. */ -static int -find_field (type, name) - struct type *type; - char *name; -{ - int i; - - CHECK_TYPEDEF (type); - - /* Make sure this isn't C++. */ - if (TYPE_N_BASECLASSES (type) != 0) - internal_error ("ax-gdb.c (find_field): derived classes supported"); - - for (i = 0; i < TYPE_NFIELDS (type); i++) - { - char *this_name = TYPE_FIELD_NAME (type, i); - - if (this_name && STREQ (name, this_name)) - return i; - - if (this_name[0] == '\0') - internal_error ("ax-gdb.c (find_field): anonymous unions not supported"); - } - - error ("Couldn't find member named `%s' in struct/union `%s'", - name, type->tag_name); - - return 0; -} - - /* Generate code to push the value of a bitfield of a structure whose address is on the top of the stack. START and END give the starting and one-past-ending *bit* numbers of the field within the structure. */ static void -gen_bitfield_ref (ax, value, type, start, end) - struct agent_expr *ax; - struct axs_value *value; - struct type *type; - int start, 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[] - = - {aop_ref8, aop_ref16, aop_ref32, aop_ref64}; + = {aop_ref8, aop_ref16, aop_ref32, aop_ref64}; static int num_ops = (sizeof (ops) / sizeof (ops[0])); /* We don't want to touch any byte that the bitfield doesn't @@ -1282,12 +1333,13 @@ gen_bitfield_ref (ax, value, type, start, end) equal to the number of `one' bits in bytesize, but who cares? */ int fragment_count; - /* Dereference any typedefs. */ + /* Dereference any typedefs. */ type = check_typedef (type); /* Can we fetch the number of bits requested at all? */ if ((end - start) > ((1 << num_ops) * 8)) - internal_error ("ax-gdb.c (gen_bitfield_ref): bitfield too wide"); + internal_error (__FILE__, __LINE__, + _("gen_bitfield_ref: bitfield too wide")); /* Note that we know here that we only need to try each opcode once. That may not be true on machines with weird byte sizes. */ @@ -1356,7 +1408,7 @@ gen_bitfield_ref (ax, value, type, start, end) 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 (TARGET_BYTE_ORDER == BIG_ENDIAN) + if (gdbarch_byte_order (exp->gdbarch) == BFD_ENDIAN_BIG) gen_left_shift (ax, end - (offset + op_size)); else gen_left_shift (ax, offset - start); @@ -1383,6 +1435,95 @@ gen_bitfield_ref (ax, value, type, start, end) value->type = type; } +/* Generate bytecodes for field number FIELDNO of type TYPE. OFFSET + is an accumulated offset (in bytes), will be nonzero for objects + embedded in other objects, like C++ base classes. Behavior should + generally follow value_primitive_field. */ + +static void +gen_primitive_field (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + int offset, int fieldno, struct type *type) +{ + /* Is this a bitfield? */ + if (TYPE_FIELD_PACKED (type, fieldno)) + gen_bitfield_ref (exp, ax, value, TYPE_FIELD_TYPE (type, fieldno), + (offset * TARGET_CHAR_BIT + + TYPE_FIELD_BITPOS (type, fieldno)), + (offset * TARGET_CHAR_BIT + + TYPE_FIELD_BITPOS (type, fieldno) + + TYPE_FIELD_BITSIZE (type, fieldno))); + else + { + gen_offset (ax, offset + + TYPE_FIELD_BITPOS (type, fieldno) / TARGET_CHAR_BIT); + value->kind = axs_lvalue_memory; + value->type = TYPE_FIELD_TYPE (type, fieldno); + } +} + +/* Search for the given field in either the given type or one of its + base classes. Return 1 if found, 0 if not. */ + +static int +gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax, + struct axs_value *value, + char *field, int offset, struct type *type) +{ + int i, rslt; + int nbases = TYPE_N_BASECLASSES (type); + + CHECK_TYPEDEF (type); + + for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--) + { + const char *this_name = TYPE_FIELD_NAME (type, i); + + if (this_name) + { + if (strcmp (field, this_name) == 0) + { + /* Note that bytecodes for the struct's base (aka + "this") will have been generated already, which will + be unnecessary but not harmful if the static field is + being handled as a global. */ + if (field_is_static (&TYPE_FIELD (type, i))) + { + gen_static_field (exp->gdbarch, ax, value, type, i); + if (value->optimized_out) + error (_("static field `%s' has been " + "optimized out, cannot use"), + field); + return 1; + } + + gen_primitive_field (exp, ax, value, offset, i, type); + return 1; + } +#if 0 /* is this right? */ + if (this_name[0] == '\0') + internal_error (__FILE__, __LINE__, + _("find_field: anonymous unions not supported")); +#endif + } + } + + /* Now scan through base classes recursively. */ + for (i = 0; i < nbases; i++) + { + struct type *basetype = check_typedef (TYPE_BASECLASS (type, i)); + + rslt = gen_struct_ref_recursive (exp, ax, value, field, + offset + TYPE_BASECLASS_BITPOS (type, i) + / TARGET_CHAR_BIT, + basetype); + if (rslt) + return 1; + } + + /* Not found anywhere, flag so caller can complain. */ + return 0; +} /* Generate code to reference the member named FIELD of a structure or union. The top of the stack, as described by VALUE, should have @@ -1390,55 +1531,200 @@ gen_bitfield_ref (ax, value, type, start, end) 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 (ax, value, field, operator_name, operand_name) - struct agent_expr *ax; - struct axs_value *value; - char *field; - char *operator_name; - char *operand_name; +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; - int i; + int found; /* 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 (value->type->code == TYPE_CODE_PTR) + while (pointer_type (value->type)) { - gen_usual_unary (ax, value); + require_rvalue (ax, value); gen_deref (ax, value); } - type = value->type; + type = check_typedef (value->type); /* This must yield a structure or a union. */ if (TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION) - error ("The left operand of `%s' is not a %s.", + error (_("The left operand of `%s' is not a %s."), operator_name, operand_name); /* And it must be in memory; we don't deal with structure rvalues, or structures living in registers. */ if (value->kind != axs_lvalue_memory) - error ("Structure does not live in memory."); + error (_("Structure does not live in memory.")); + + /* Search through fields and base classes recursively. */ + found = gen_struct_ref_recursive (exp, ax, value, field, 0, type); + + if (!found) + error (_("Couldn't find member named `%s' in struct/union/class `%s'"), + field, TYPE_TAG_NAME (type)); +} - i = find_field (type, field); +static int +gen_namespace_elt (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + const struct type *curtype, char *name); +static int +gen_maybe_namespace_elt (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + const struct type *curtype, char *name); - /* Is this a bitfield? */ - if (TYPE_FIELD_PACKED (type, i)) - gen_bitfield_ref (ax, value, TYPE_FIELD_TYPE (type, i), - TYPE_FIELD_BITPOS (type, i), - (TYPE_FIELD_BITPOS (type, i) - + TYPE_FIELD_BITSIZE (type, i))); - else +static void +gen_static_field (struct gdbarch *gdbarch, + struct agent_expr *ax, struct axs_value *value, + struct type *type, int fieldno) +{ + if (TYPE_FIELD_LOC_KIND (type, fieldno) == FIELD_LOC_KIND_PHYSADDR) { - gen_offset (ax, TYPE_FIELD_BITPOS (type, i) / TARGET_CHAR_BIT); + ax_const_l (ax, TYPE_FIELD_STATIC_PHYSADDR (type, fieldno)); value->kind = axs_lvalue_memory; - value->type = TYPE_FIELD_TYPE (type, i); + value->type = TYPE_FIELD_TYPE (type, fieldno); + value->optimized_out = 0; + } + else + { + const char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); + struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0); + + if (sym) + { + gen_var_ref (gdbarch, ax, value, sym); + + /* Don't error if the value was optimized out, we may be + scanning all static fields and just want to pass over this + and continue with the rest. */ + } + else + { + /* Silently assume this was optimized out; class printing + will let the user know why the data is missing. */ + value->optimized_out = 1; + } + } +} + +static int +gen_struct_elt_for_reference (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + struct type *type, char *fieldname) +{ + struct type *t = type; + int i; + + if (TYPE_CODE (t) != TYPE_CODE_STRUCT + && TYPE_CODE (t) != TYPE_CODE_UNION) + internal_error (__FILE__, __LINE__, + _("non-aggregate type to gen_struct_elt_for_reference")); + + for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--) + { + const char *t_field_name = TYPE_FIELD_NAME (t, i); + + if (t_field_name && strcmp (t_field_name, fieldname) == 0) + { + if (field_is_static (&TYPE_FIELD (t, i))) + { + gen_static_field (exp->gdbarch, ax, value, t, i); + if (value->optimized_out) + error (_("static field `%s' has been " + "optimized out, cannot use"), + fieldname); + return 1; + } + if (TYPE_FIELD_PACKED (t, i)) + error (_("pointers to bitfield members not allowed")); + + /* FIXME we need a way to do "want_address" equivalent */ + + error (_("Cannot reference non-static field \"%s\""), fieldname); + } } + + /* FIXME add other scoped-reference cases here */ + + /* Do a last-ditch lookup. */ + return gen_maybe_namespace_elt (exp, ax, value, type, fieldname); +} + +/* C++: Return the member NAME of the namespace given by the type + CURTYPE. */ + +static int +gen_namespace_elt (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + const struct type *curtype, char *name) +{ + int found = gen_maybe_namespace_elt (exp, ax, value, curtype, name); + + if (!found) + error (_("No symbol \"%s\" in namespace \"%s\"."), + name, TYPE_TAG_NAME (curtype)); + + return found; } +/* A helper function used by value_namespace_elt and + value_struct_elt_for_reference. It looks up NAME inside the + context CURTYPE; this works if CURTYPE is a namespace or if CURTYPE + is a class and NAME refers to a type in CURTYPE itself (as opposed + to, say, some base class of CURTYPE). */ + +static int +gen_maybe_namespace_elt (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + const struct type *curtype, char *name) +{ + const char *namespace_name = TYPE_TAG_NAME (curtype); + struct symbol *sym; + + sym = cp_lookup_symbol_namespace (namespace_name, name, + block_for_pc (ax->scope), + VAR_DOMAIN); + + if (sym == NULL) + return 0; + + gen_var_ref (exp->gdbarch, ax, value, sym); + + if (value->optimized_out) + error (_("`%s' has been optimized out, cannot use"), + SYMBOL_PRINT_NAME (sym)); + + return 1; +} + + +static int +gen_aggregate_elt_ref (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + struct type *type, char *field, + char *operator_name, char *operand_name) +{ + switch (TYPE_CODE (type)) + { + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + return gen_struct_elt_for_reference (exp, ax, value, type, field); + break; + case TYPE_CODE_NAMESPACE: + return gen_namespace_elt (exp, ax, value, type, field); + break; + default: + internal_error (__FILE__, __LINE__, + _("non-aggregate type in gen_aggregate_elt_ref")); + } + + return 0; +} -/* Generate code for GDB's magical `repeat' operator. +/* 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 @@ -1450,17 +1736,16 @@ gen_struct_ref (ax, value, field, operator_name, operand_name) stack slots, doing weird things with sizeof, etc. So we require the right operand to be a constant expression. */ static void -gen_repeat (pc, ax, value) - 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."); + error (_("Left operand of `@' must be an object in memory.")); /* Evaluate the length; it had better be a constant. */ { @@ -1468,21 +1753,21 @@ gen_repeat (pc, ax, value) int length; if (!v) - error ("Right operand of `@' must be a constant, in agent expressions."); - if (v->type->code != TYPE_CODE_INT) - error ("Right operand of `@' must be an integer."); + error (_("Right operand of `@' must be a " + "constant, in agent expressions.")); + if (TYPE_CODE (value_type (v)) != 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."); + 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 *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; @@ -1495,10 +1780,9 @@ gen_repeat (pc, ax, value) *PC should point at the start of the operand expression; we advance it to the first instruction after the operand. */ static void -gen_sizeof (pc, ax, value) - 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 @@ -1506,30 +1790,32 @@ gen_sizeof (pc, ax, value) 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; } /* 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. */ static void -gen_expr (pc, ax, value) - 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; + struct type *int_type = builtin_type (exp->gdbarch)->builtin_int; /* If we're looking at a constant expression, just push its value. */ { @@ -1539,7 +1825,7 @@ gen_expr (pc, ax, value) { ax_const_l (ax, value_as_long (v)); value->kind = axs_rvalue; - value->type = check_typedef (VALUE_TYPE (v)); + value->type = check_typedef (value_type (v)); return; } } @@ -1553,62 +1839,146 @@ gen_expr (pc, ax, value) 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 (exp, 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 (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 = 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 (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 = int_type; + break; + + 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, int_type); + 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)++; - 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) + if ((*pc)[0].opcode == OP_INTERNALVAR) { - 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 ("Illegal 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; + char *name = internalvar_name ((*pc)[1].internalvar); + struct trace_state_variable *tsv; - case BINOP_BITWISE_IOR: - gen_binop (ax, value, &value1, &value2, - aop_bit_or, aop_bit_or, 0, "bitwise or"); - break; + (*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_BITWISE_XOR: - gen_binop (ax, value, &value1, &value2, - aop_bit_xor, aop_bit_xor, 0, "bitwise exclusive-or"); - 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; - default: - /* We should only list operators in the outer case statement - that we actually handle in the inner case statement. */ - internal_error ("ax-gdb.c (gen_expr): op case sets don't match"); + (*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 @@ -1619,12 +1989,12 @@ gen_expr (pc, ax, value) 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_traced_pop (exp->gdbarch, ax, &value1); + gen_expr (exp, pc, ax, value); /* It's the consumer's responsibility to trace the right operand. */ break; @@ -1632,41 +2002,79 @@ gen_expr (pc, ax, value) { 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); + gen_var_ref (exp->gdbarch, ax, value, (*pc)[2].symbol); + + if (value->optimized_out) + error (_("`%s' has been optimized out, cannot use"), + SYMBOL_PRINT_NAME ((*pc)[2].symbol)); + (*pc) += 4; break; case OP_REGISTER: { - int reg = (int) (*pc)[1].longconst; - (*pc) += 3; + 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 (exp->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_regs (exp->gdbarch) + + gdbarch_num_pseudo_regs (exp->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_VIRTUAL_TYPE (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; @@ -1674,55 +2082,67 @@ gen_expr (pc, ax, value) case UNOP_MEMVAL: { struct type *type = check_typedef ((*pc)[1].type); + (*pc) += 3; - gen_expr (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 - the given type, and dereference it. */ - if (value->kind != axs_rvalue) - /* This would be weird. */ - internal_error ("ax-gdb.c (gen_expr): OP_MEMVAL operand isn't an rvalue???"); + 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 (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, int_type); 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) - error ("Argument of unary `*' is not a pointer."); + 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; @@ -1731,7 +2151,8 @@ gen_expr (pc, ax, value) /* 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: @@ -1741,48 +2162,287 @@ gen_expr (pc, ax, value) 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 shouldn't mention it, and we shouldn't be here. */ - internal_error ("ax-gdb.c (gen_expr): unhandled struct case"); + internal_error (__FILE__, __LINE__, + _("gen_expr: unhandled struct case")); + } + break; + + case OP_THIS: + { + char *this_name; + struct symbol *sym, *func; + struct block *b; + const struct language_defn *lang; + + b = block_for_pc (ax->scope); + func = block_linkage_function (b); + lang = language_def (SYMBOL_LANGUAGE (func)); + + sym = lookup_language_this (lang, b); + if (!sym) + error (_("no `%s' found"), lang->la_name_of_this); + + gen_var_ref (exp->gdbarch, ax, value, sym); + + if (value->optimized_out) + error (_("`%s' has been optimized out, cannot use"), + SYMBOL_PRINT_NAME (sym)); + + (*pc) += 2; + } + break; + + case OP_SCOPE: + { + struct type *type = (*pc)[1].type; + int length = longest_to_int ((*pc)[2].longconst); + char *name = &(*pc)[3].string; + int found; + + found = gen_aggregate_elt_ref (exp, 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: - error ("Attempt to use a type name as an expression."); + error (_("Attempt to use a type name as an expression.")); + + default: + error (_("Unsupported operator %s (%d) in expression."), + op_string (op), op); + } +} + +/* 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. */ + +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 type *int_type = builtin_type (exp->gdbarch)->builtin_int; + + 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_LSH: + gen_binop (ax, value, value1, value2, + aop_lsh, aop_lsh, 1, "left shift"); + break; + case BINOP_RSH: + gen_binop (ax, value, value1, value2, + aop_rsh_signed, aop_rsh_unsigned, 1, "right shift"); + break; + case BINOP_SUBSCRIPT: + { + struct type *type; + + 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")); + } + } + + if (!is_integral_type (value2->type)) + error (_("Argument to arithmetic operation " + "not a number or boolean.")); + + 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; + + 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; + + case BINOP_EQUAL: + gen_equal (ax, value, value1, value2, int_type); + break; + + case BINOP_NOTEQUAL: + gen_equal (ax, value, value1, value2, int_type); + gen_logical_not (ax, value, int_type); + break; + + case BINOP_LESS: + gen_less (ax, value, value1, value2, int_type); + break; + + case BINOP_GTR: + ax_simple (ax, aop_swap); + gen_less (ax, value, value1, value2, int_type); + break; + + case BINOP_LEQ: + ax_simple (ax, aop_swap); + gen_less (ax, value, value1, value2, int_type); + gen_logical_not (ax, value, int_type); + break; + + case BINOP_GEQ: + gen_less (ax, value, value1, value2, int_type); + gen_logical_not (ax, value, int_type); + break; default: - error ("Unsupported operator in expression."); + /* 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")); } } +/* 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. */ + +struct agent_expr * +gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch, + struct symbol *var) +{ + struct cleanup *old_chain = 0; + struct agent_expr *ax = new_agent_expr (gdbarch, scope); + struct axs_value value; + + old_chain = make_cleanup_free_agent_expr (ax); + + trace_kludge = 1; + gen_var_ref (gdbarch, ax, &value, var); + + /* If there is no actual variable to trace, flag it by returning + an empty agent expression. */ + if (value.optimized_out) + { + do_cleanups (old_chain); + return NULL; + } + + /* Make sure we record the final object, and get rid of it. */ + gen_traced_pop (gdbarch, 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; +} /* 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. */ +/* Given a GDB expression EXPR, return bytecode to trace its value. + The result will use the `trace' and `trace_quick' bytecodes to + record the value of all memory touched by the expression. The + caller can then use the ax_reqs function to discover which + registers it relies upon. */ struct agent_expr * -expr_to_agent (expr, value) - struct expression *expr; - struct axs_value *value; +gen_trace_for_expr (CORE_ADDR scope, struct expression *expr) { struct cleanup *old_chain = 0; - struct agent_expr *ax = new_agent_expr (0); + struct agent_expr *ax = new_agent_expr (expr->gdbarch, 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 (&pc, ax, value); + trace_kludge = 1; + value.optimized_out = 0; + gen_expr (expr, &pc, ax, &value); + + /* Make sure we record the final object, and get rid of it. */ + gen_traced_pop (expr->gdbarch, 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 @@ -1791,57 +2451,55 @@ expr_to_agent (expr, value) 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. */ -#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. - - Not sure this function is useful at all. */ struct agent_expr * -expr_to_address_and_size (expr) - struct expression *expr; +gen_eval_for_expr (CORE_ADDR scope, struct expression *expr) { + struct cleanup *old_chain = 0; + struct agent_expr *ax = new_agent_expr (expr->gdbarch, scope); + union exp_element *pc; 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); + + pc = expr->elts; + trace_kludge = 0; + value.optimized_out = 0; + gen_expr (expr, &pc, ax, &value); - /* Push the object's size on the stack. */ - ax_const_l (ax, TYPE_LENGTH (value.type)); + require_rvalue (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; } -#endif -/* Given a GDB expression EXPR, return bytecode to trace its value. - The result will use the `trace' and `trace_quick' bytecodes to - record the value of all memory touched by the expression. The - caller can then use the ax_reqs function to discover which - registers it relies upon. */ struct agent_expr * -gen_trace_for_expr (scope, expr) - CORE_ADDR scope; - struct expression *expr; +gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch) { struct cleanup *old_chain = 0; - struct agent_expr *ax = new_agent_expr (scope); - union exp_element *pc; + struct agent_expr *ax = new_agent_expr (gdbarch, scope); struct axs_value value; old_chain = make_cleanup_free_agent_expr (ax); - pc = expr->elts; trace_kludge = 1; - gen_expr (&pc, ax, &value); + + gdbarch_gen_return_address (gdbarch, ax, &value, scope); /* Make sure we record the final object, and get rid of it. */ - gen_traced_pop (ax, &value); + gen_traced_pop (gdbarch, ax, &value); /* Oh, and terminate. */ ax_simple (ax, aop_end); @@ -1852,40 +2510,61 @@ gen_trace_for_expr (scope, expr) discard_cleanups (old_chain); return ax; } - - - -/* The "agent" command, for testing: compile and disassemble an expression. */ static void -print_axs_value (f, value) - struct ui_file *f; - struct axs_value *value; +agent_command (char *exp, int from_tty) { - switch (value->kind) - { - case axs_rvalue: - fputs_filtered ("rvalue", f); - break; + struct cleanup *old_chain = 0; + struct expression *expr; + struct agent_expr *agent; + struct frame_info *fi = get_current_frame (); /* need current scope */ - case axs_lvalue_memory: - fputs_filtered ("memory lvalue", f); - break; + /* 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.")); - case axs_lvalue_register: - fprintf_filtered (f, "register %d lvalue", value->u.reg); - break; + if (exp == 0) + error_no_arg (_("expression to translate")); + + trace_string_kludge = 0; + if (*exp == '/') + exp = decode_agent_options (exp); + + /* Recognize the return address collection directive specially. Note + that it is not really an expression of any sort. */ + if (strcmp (exp, "$_ret") == 0) + { + agent = gen_trace_for_return_address (get_frame_pc (fi), + get_current_arch ()); + old_chain = make_cleanup_free_agent_expr (agent); + } + else + { + expr = parse_expression (exp); + old_chain = make_cleanup (free_current_contents, &expr); + agent = gen_trace_for_expr (get_frame_pc (fi), expr); + make_cleanup_free_agent_expr (agent); } - fputs_filtered (" : ", f); - type_print (value->type, "", f, -1); + ax_reqs (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 (); } +/* Parse the given expression, compile it into an agent expression + that does direct evaluation, and display the resulting + expression. */ static void -agent_command (exp, from_tty) - char *exp; - int from_tty; +agent_eval_command (char *exp, int from_tty) { struct cleanup *old_chain = 0; struct expression *expr; @@ -1897,15 +2576,16 @@ agent_command (exp, from_tty) 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."); + error (_("GDB can't do agent expression translation with overlays.")); if (exp == 0) - error_no_arg ("expression to translate"); + error_no_arg (_("expression to translate")); expr = parse_expression (exp); old_chain = make_cleanup (free_current_contents, &expr); - agent = gen_trace_for_expr (fi->pc, expr); + agent = gen_eval_for_expr (get_frame_pc (fi), expr); make_cleanup_free_agent_expr (agent); + ax_reqs (agent); ax_print (gdb_stdout, agent); /* It would be nice to call ax_reqs here to gather some general info @@ -1920,9 +2600,15 @@ agent_command (exp, from_tty) void _initialize_ax_gdb (void); void -_initialize_ax_gdb () +_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); }