Rephrase error message in infcall.c:call_function_by_hand
[deliverable/binutils-gdb.git] / gdb / ax-gdb.c
index 27cc5b1ea356497e573850337aaa0de76698f796..19c00ade5a36d0a171ca1f354993d549801a55e0 100644 (file)
@@ -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, 2011
    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"
 #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"
 
 /* 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,
@@ -52,7 +59,7 @@
 \f
 
 
-/* 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
@@ -63,7 +70,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 *);
@@ -71,11 +79,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 +93,74 @@ 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,
+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_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);
 \f
@@ -190,6 +220,7 @@ const_expr (union exp_element **pc)
       {
        struct type *type = (*pc)[1].type;
        LONGEST k = (*pc)[2].longconst;
+
        (*pc) += 4;
        return value_from_longest (type, k);
       }
@@ -197,6 +228,7 @@ const_expr (union exp_element **pc)
     case OP_VAR_VALUE:
       {
        struct value *v = const_var_ref ((*pc)[2].symbol);
+
        (*pc) += 4;
        return v;
       }
@@ -300,13 +332,65 @@ maybe_const_expr (union exp_element **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;
+
+/* 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 (struct agent_expr *ax, struct axs_value *value)
+gen_traced_pop (struct gdbarch *gdbarch,
+               struct agent_expr *ax, struct axs_value *value)
 {
   if (trace_kludge)
     switch (value->kind)
@@ -332,16 +416,22 @@ gen_traced_pop (struct agent_expr *ax, struct axs_value *value)
        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);
        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);
 }
 \f
 
@@ -366,6 +456,7 @@ static void
 gen_extend (struct agent_expr *ax, struct type *type)
 {
   int bits = TYPE_LENGTH (type) * TARGET_CHAR_BIT;
+
   /* I just had to.  */
   ((TYPE_UNSIGNED (type) ? ax_zero_ext : ax_ext) (ax, bits));
 }
@@ -386,9 +477,11 @@ 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:
+    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 (type))
@@ -454,12 +547,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 +562,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,10 +612,12 @@ 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. */
+  /* 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))
@@ -539,7 +634,8 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var)
 
     case LOC_CONST_BYTES:
       internal_error (__FILE__, __LINE__,
-                     _("gen_var_ref: LOC_CONST_BYTES symbols are not supported"));
+                     _("gen_var_ref: LOC_CONST_BYTES "
+                       "symbols are not supported"));
 
       /* Variable at a fixed location in memory.  Easy.  */
     case LOC_STATIC:
@@ -549,30 +645,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 +676,27 @@ 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,18 +707,18 @@ 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:
-      error (_("The variable `%s' has been optimized out."),
-            SYMBOL_PRINT_NAME (var));
+      /* Flag this, but don't say anything; leave it up to callers to
+        warn the user.  */
+      value->optimized_out = 1;
       break;
 
     default:
@@ -663,6 +751,15 @@ gen_int_literal (struct agent_expr *ax, struct axs_value *value, LONGEST k,
 static void
 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:
@@ -706,7 +803,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
@@ -726,6 +824,7 @@ gen_usual_unary (struct agent_expr *ax, struct axs_value *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
@@ -739,9 +838,10 @@ gen_usual_unary (struct agent_expr *ax, struct axs_value *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;
     }
 
@@ -804,7 +904,7 @@ gen_conversion (struct agent_expr *ax, struct type *from, struct type *to)
 static int
 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
@@ -826,8 +926,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 +938,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.  */
@@ -863,17 +963,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;
     }
 }
 
@@ -885,12 +988,13 @@ 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 (type))
     {
     case TYPE_CODE_PTR:
+    case TYPE_CODE_REF:
       /* It's implementation-defined, and I'll bet this is what GCC
          does.  */
       break;
@@ -902,12 +1006,12 @@ gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type)
       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:
@@ -947,102 +1051,84 @@ 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;
-    }
+  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 (_("Invalid 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;
 }
 
@@ -1054,8 +1140,9 @@ an integer nor a pointer of the same type."));
    operator, used in error messages */
 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)
+          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 ((TYPE_CODE (value1->type) != TYPE_CODE_INT)
@@ -1072,15 +1159,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 +1177,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 +1191,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 +1201,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);
 }
@@ -1148,58 +1235,18 @@ gen_address_of (struct agent_expr *ax, struct axs_value *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 (struct type *type, char *name)
-{
-  int i;
-
-  CHECK_TYPEDEF (type);
-
-  /* Make sure this isn't C++.  */
-  if (TYPE_N_BASECLASSES (type) != 0)
-    internal_error (__FILE__, __LINE__,
-                   _("find_field: derived classes supported"));
-
-  for (i = 0; i < TYPE_NFIELDS (type); i++)
-    {
-      char *this_name = TYPE_FIELD_NAME (type, i);
-
-      if (this_name)
-       {
-         if (strcmp (name, this_name) == 0)
-           return i;
-
-         if (this_name[0] == '\0')
-           internal_error (__FILE__, __LINE__,
-                           _("find_field: anonymous unions not supported"));
-       }
-    }
-
-  error (_("Couldn't find member named `%s' in struct/union `%s'"),
-        name, TYPE_TAG_NAME (type));
-
-  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 (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[]
-  =
-  {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
@@ -1245,7 +1292,7 @@ gen_bitfield_ref (struct agent_expr *ax, struct axs_value *value,
      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?  */
@@ -1320,7 +1367,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);
@@ -1347,6 +1394,95 @@ gen_bitfield_ref (struct agent_expr *ax, struct axs_value *value,
   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--)
+    {
+      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
@@ -1354,18 +1490,19 @@ 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;
-  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 (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);
@@ -1381,24 +1518,172 @@ gen_struct_ref (struct agent_expr *ax, struct axs_value *value, char *field,
   if (value->kind != axs_lvalue_memory)
     error (_("Structure does not live in memory."));
 
-  i = find_field (type, field);
+  /* 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));
+}
 
-  /* 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 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);
+
+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--)
+    {
+      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);
 
-/* Generate code for GDB's magical `repeat' operator.  
+  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.
    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
@@ -1410,13 +1695,14 @@ 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."));
 
@@ -1426,7 +1712,8 @@ gen_repeat (union exp_element **pc, struct agent_expr *ax,
     int length;
 
     if (!v)
-      error (_("Right operand of `@' must be a constant, in agent expressions."));
+      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);
@@ -1438,9 +1725,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 +1739,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 +1749,15 @@ 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;
 }
 \f
 
@@ -1479,12 +1767,14 @@ 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;
+  struct type *int_type = builtin_type (exp->gdbarch)->builtin_int;
 
   /* If we're looking at a constant expression, just push its value.  */
   {
@@ -1508,63 +1798,146 @@ gen_expr (union exp_element **pc, struct agent_expr *ax,
     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 (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)
+      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)++;
+      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 (_("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;
+         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 (__FILE__, __LINE__,
-                         _("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
@@ -1575,12 +1948,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_traced_pop (exp->gdbarch, ax, &value1);
+      gen_expr (exp, pc, ax, value);
       /* It's the consumer's responsibility to trace the right operand.  */
       break;
 
@@ -1588,13 +1961,19 @@ gen_expr (union exp_element **pc, struct agent_expr *ax,
       {
        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;
 
@@ -1602,33 +1981,59 @@ 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);
+       /* 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_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;
@@ -1636,16 +2041,16 @@ gen_expr (union exp_element **pc, struct agent_expr *ax,
     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 (__FILE__, __LINE__,
-                         _("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;
       }
@@ -1653,46 +2058,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);
+      /* + 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)
+      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 +2110,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 +2121,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,67 +2135,248 @@ 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, VAR_DOMAIN);
+       if (!sym)
+         error (_("no `%s' found"), this_name);
+
+       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."));
 
     default:
-      error (_("Unsupported operator in expression."));
+      error (_("Unsupported operator %s (%d) in expression."),
+            op_string (op), op);
     }
 }
-\f
 
+/* 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;
+  struct type *int_type = builtin_type (exp->gdbarch)->builtin_int;
 
-  old_chain = make_cleanup_free_agent_expr (ax);
+  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;
 
-  pc = expr->elts;
-  trace_kludge = 0;
-  gen_expr (&pc, ax, value);
+       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;
 
-  /* 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_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;
 
-#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.
+    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:
+      /* 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"));
+    }
+}
+\f
+
+/* 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 gdbarch *gdbarch,
+                  struct symbol *var)
 {
+  struct cleanup *old_chain = 0;
+  struct agent_expr *ax = new_agent_expr (gdbarch, 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)
+  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)
     {
-      free_agent_expr (ax);
-      error (_("Expression does not denote an object in memory."));
+      do_cleanups (old_chain);
+      return NULL;
     }
 
-  /* Push the object's size on the stack.  */
-  ax_const_l (ax, TYPE_LENGTH (value.type));
+  /* 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;
 }
-#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
@@ -1796,7 +2387,7 @@ struct agent_expr *
 gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
 {
   struct cleanup *old_chain = 0;
-  struct agent_expr *ax = new_agent_expr (scope);
+  struct agent_expr *ax = new_agent_expr (expr->gdbarch, scope);
   union exp_element *pc;
   struct axs_value value;
 
@@ -1804,10 +2395,45 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
 
   pc = expr->elts;
   trace_kludge = 1;
-  gen_expr (&pc, ax, &value);
+  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 (ax, &value);
+  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
+     will have to get more complicated.  */
+  discard_cleanups (old_chain);
+  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 (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;
+  value.optimized_out = 0;
+  gen_expr (expr, &pc, ax, &value);
+
+  require_rvalue (ax, &value);
 
   /* Oh, and terminate.  */
   ax_simple (ax, aop_end);
@@ -1841,6 +2467,43 @@ agent_command (char *exp, int from_tty)
   old_chain = make_cleanup (free_current_contents, &expr);
   agent = gen_trace_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
+     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_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_reqs (agent);
   ax_print (gdb_stdout, agent);
 
   /* It would be nice to call ax_reqs here to gather some general info
@@ -1858,6 +2521,12 @@ 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);
 }
This page took 0.121758 seconds and 4 git commands to generate.