Tue Aug 25 13:21:58 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
authorMichael Snyder <msnyder@vmware.com>
Tue, 25 Aug 1998 20:24:03 +0000 (20:24 +0000)
committerMichael Snyder <msnyder@vmware.com>
Tue, 25 Aug 1998 20:24:03 +0000 (20:24 +0000)
        * ax-gdb.c (gen_var_ref): Allow for typedef types.
        (gen_cast, gen_bitfield_ref, gen_expr): ditto.

gdb/ChangeLog
gdb/ax-gdb.c [new file with mode: 0644]

index d7f31a1d8739e319f64e76f280363d9ab6d7f8b1..49150fdc6a5c0b25a71e9a1c3125a99fc8b0442a 100644 (file)
@@ -1,3 +1,8 @@
+Tue Aug 25 13:21:58 1998  Michael Snyder  <msnyder@cleaver.cygnus.com>
+
+       * ax-gdb.c (gen_var_ref): Allow for typedef types.
+       (gen_cast, gen_bitfield_ref, gen_expr): ditto.
+
 Mon Aug 24 18:29:03 1998  Michael Snyder  <msnyder@cleaver.cygnus.com>
 
        * tracepoint.c (collect_symbol): Handle register doubles that
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
new file mode 100644 (file)
index 0000000..a55df32
--- /dev/null
@@ -0,0 +1,1928 @@
+/* GDB-specific functions for operating on agent expressions
+   Copyright 1998 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
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+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.  */
+
+/* $Id$ */
+
+#include "defs.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "expression.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "ax.h"
+#include "ax-gdb.h"
+
+/* Probably the best way to read this file is to start with the types
+   and enums in ax-gdb.h, and then look at gen_expr, towards the
+   bottom; that's the main function that looks at the GDB expressions
+   and calls everything else to generate code.
+
+   I'm beginning to wonder whether it wouldn't be nicer to internally
+   generate trees, with types, and then spit out the bytecode in
+   linear form afterwards; we could generate fewer `swap', `ext', and
+   `zero_ext' bytecodes that way; it would make good constant folding
+   easier, too.  But at the moment, I think we should be willing to
+   pay for the simplicity of this code with less-than-optimal bytecode
+   strings.
+
+   Remember, "GBD" stands for "Great Britain, Dammit!"  So be careful.  */ 
+
+
+\f
+/* Static forward declarations */
+
+/* There's a standard order to the arguments of these functions:
+   union exp_element ** --- pointer into expression
+   struct agent_expr * --- agent expression buffer to generate code into
+   struct axs_value * --- describes value left on top of stack  */
+   
+static struct value *const_var_ref PARAMS ((struct symbol *var));
+static struct value *const_expr PARAMS ((union exp_element **pc));
+static struct value *maybe_const_expr PARAMS ((union exp_element **pc));
+
+static void gen_traced_pop PARAMS ((struct agent_expr *, struct axs_value *));
+
+static void gen_sign_extend PARAMS ((struct agent_expr *, struct type *));
+static void gen_extend PARAMS ((struct agent_expr *, struct type *));
+static void gen_fetch PARAMS ((struct agent_expr *, struct type *));
+static void gen_left_shift PARAMS ((struct agent_expr *, int));
+
+
+static void gen_frame_args_address PARAMS ((struct agent_expr *));
+static void gen_frame_locals_address PARAMS ((struct agent_expr *));
+static void gen_offset PARAMS ((struct agent_expr *ax, int offset));
+static void gen_sym_offset PARAMS ((struct agent_expr *, struct symbol *));
+static void gen_var_ref PARAMS ((struct agent_expr *ax,
+                                struct axs_value *value,
+                                struct symbol *var));
+
+
+static void gen_int_literal PARAMS ((struct agent_expr *ax,
+                                    struct axs_value *value,
+                                    LONGEST k, struct type *type));
+
+
+static void require_rvalue PARAMS ((struct agent_expr *ax,
+                                   struct axs_value *value));
+static void gen_usual_unary PARAMS ((struct agent_expr *ax,
+                                    struct axs_value *value));
+static int type_wider_than PARAMS ((struct type *type1,
+                                   struct type *type2));
+static struct type *max_type PARAMS ((struct type *type1, 
+                                     struct type *type2));
+static void gen_conversion PARAMS ((struct agent_expr *ax,
+                                   struct type *from,
+                                   struct type *to));
+static int is_nontrivial_conversion PARAMS ((struct type *from,
+                                            struct type *to));
+static void gen_usual_arithmetic PARAMS ((struct agent_expr *ax,
+                                         struct axs_value *value1,
+                                         struct axs_value *value2));
+static void gen_integral_promotions PARAMS ((struct agent_expr *ax,
+                                            struct axs_value *value));
+static void gen_cast PARAMS ((struct agent_expr *ax,
+                             struct axs_value *value,
+                             struct type *type));
+static void gen_scale PARAMS ((struct agent_expr *ax,
+                              enum agent_op op,
+                              struct type *type));
+static void gen_add PARAMS ((struct agent_expr *ax,
+                            struct axs_value *value, 
+                            struct axs_value *value1,
+                            struct axs_value *value2,
+                            char *name));
+static void gen_sub PARAMS ((struct agent_expr *ax,
+                            struct axs_value *value, 
+                            struct axs_value *value1,
+                            struct axs_value *value2));
+static void gen_binop PARAMS ((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 PARAMS ((struct agent_expr *ax,
+                                    struct axs_value *value));
+static void gen_complement PARAMS ((struct agent_expr *ax,
+                                   struct axs_value *value));
+static void gen_deref PARAMS ((struct agent_expr *, struct axs_value *));
+static void gen_address_of PARAMS ((struct agent_expr *, struct axs_value *));
+static int find_field PARAMS ((struct type *type, char *name));
+static void gen_bitfield_ref PARAMS ((struct agent_expr *ax,
+                                     struct axs_value *value,
+                                     struct type *type,
+                                     int start, int end));
+static void gen_struct_ref PARAMS ((struct agent_expr *ax,
+                                   struct axs_value *value,
+                                   char *field,
+                                   char *operator_name,
+                                   char *operand_name));
+static void gen_repeat PARAMS ((union exp_element **pc,
+                               struct agent_expr *ax,
+                               struct axs_value *value));
+static void gen_sizeof PARAMS ((union exp_element **pc,
+                               struct agent_expr *ax,
+                               struct axs_value *value));
+static void gen_expr PARAMS ((union exp_element **pc,
+                             struct agent_expr *ax,
+                             struct axs_value *value));
+static void print_axs_value PARAMS ((GDB_FILE *f, struct axs_value *value));
+static void agent_command PARAMS ((char *exp, int from_tty));
+
+\f
+/* Detecting constant expressions.  */
+
+/* If the variable reference at *PC is a constant, return its value.
+   Otherwise, return zero.
+
+   Hey, Wally!  How can a variable reference be a constant?
+
+   Well, Beav, this function really handles the OP_VAR_VALUE operator,
+   not specifically variable references.  GDB uses OP_VAR_VALUE to
+   refer to any kind of symbolic reference: function names, enum
+   elements, and goto labels are all handled through the OP_VAR_VALUE
+   operator, even though they're constants.  It makes sense given the
+   situation.
+
+   Gee, Wally, don'cha wonder sometimes if data representations that
+   subvert commonly accepted definitions of terms in favor of heavily
+   context-specific interpretations are really just a tool of the
+   programming hegemony to preserve their power and exclude the
+   proletariat?  */
+
+static struct value *
+const_var_ref (var)
+     struct symbol *var;
+{
+  struct type *type = SYMBOL_TYPE (var);
+
+  switch (SYMBOL_CLASS (var))
+    {
+    case LOC_CONST:
+      return value_from_longest (type, (LONGEST) SYMBOL_VALUE (var));
+
+    case LOC_LABEL:
+      return value_from_longest (type, (LONGEST) SYMBOL_VALUE_ADDRESS (var));
+
+    default:
+      return 0;
+    }
+}
+
+
+/* If the expression starting at *PC has a constant value, return it.
+   Otherwise, return zero.  If we return a value, then *PC will be
+   advanced to the end of it.  If we return zero, *PC could be
+   anywhere.  */
+static struct value *
+const_expr (pc)
+     union exp_element **pc;
+{
+  enum exp_opcode op = (*pc)->opcode;
+  struct value *v1;
+
+  switch (op)
+    {
+    case OP_LONG:
+      {
+       struct type *type = (*pc)[1].type;
+       LONGEST k = (*pc)[2].longconst;
+       (*pc) += 4;
+       return value_from_longest (type, k);
+      }
+
+    case OP_VAR_VALUE:
+      {
+       struct value *v = const_var_ref ((*pc)[2].symbol);
+       (*pc) += 4;
+       return v;
+      }
+
+    /* We could add more operators in here.  */
+
+    case UNOP_NEG:
+      (*pc)++;
+      v1 = const_expr (pc);
+      if (v1)
+       return value_neg (v1);
+      else
+       return 0;
+
+    default:
+      return 0;
+    }
+}
+
+
+/* Like const_expr, but guarantee also that *PC is undisturbed if the
+   expression is not constant.  */
+static struct value *
+maybe_const_expr (pc)
+     union exp_element **pc;
+{
+  union exp_element *tentative_pc = *pc;
+  struct value *v = const_expr (&tentative_pc);
+
+  /* If we got a value, then update the real PC.  */
+  if (v)
+    *pc = tentative_pc;
+  return v;
+}
+
+\f
+/* Generating bytecode from GDB expressions: general assumptions */
+
+/* Here are a few general assumptions made throughout the code; if you
+   want to make a change that contradicts one of these, then you'd
+   better scan things pretty thoroughly.
+
+   - We assume that all values occupy one stack element.  For example,
+     sometimes we'll swap to get at the left argument to a binary
+     operator.  If we decide that void values should occupy no stack
+     elements, or that synthetic arrays (whose size is determined at
+     run time, created by the `@' operator) should occupy two stack
+     elements (address and length), then this will cause trouble.
+
+   - We assume the stack elements are infinitely wide, and that we
+     don't have to worry what happens if the user requests an
+     operation that is wider than the actual interpreter's stack.
+     That is, it's up to the interpreter to handle directly all the
+     integer widths the user has access to.  (Woe betide the language
+     with bignums!)
+
+   - We don't support side effects.  Thus, we don't have to worry about
+     GCC's generalized lvalues, function calls, etc.
+
+   - We don't support floating point.  Many places where we switch on
+     some type don't bother to include cases for floating point; there
+     may be even more subtle ways this assumption exists.  For
+     example, the arguments to % must be integers.
+
+   - We assume all subexpressions have a static, unchanging type.  If
+     we tried to support convenience variables, this would be a
+     problem.
+
+   - All values on the stack should always be fully zero- or
+     sign-extended.
+
+     (I wasn't sure whether to choose this or its opposite --- that
+     only addresses are assumed extended --- but it turns out that
+     neither convention completely eliminates spurious extend
+     operations (if everything is always extended, then you have to
+     extend after add, because it could overflow; if nothing is
+     extended, then you end up producing extends whenever you change
+     sizes), and this is simpler.)  */
+
+\f
+/* Generating bytecode from GDB expressions: the `trace' kludge  */
+
+/* The compiler in this file is a general-purpose mechanism for
+   translating GDB expressions into bytecode.  One ought to be able to
+   find a million and one uses for it.
+
+   However, at the moment it is HOPELESSLY BRAIN-DAMAGED for the sake
+   of expediency.  Let he who is without sin cast the first stone.
+
+   For the data tracing facility, we need to insert `trace' bytecodes
+   before each data fetch; this records all the memory that the
+   expression touches in the course of evaluation, so that memory will
+   be available when the user later tries to evaluate the expression
+   in GDB.
+
+   This should be done (I think) in a post-processing pass, that walks
+   an arbitrary agent expression and inserts `trace' operations at the
+   appropriate points.  But it's much faster to just hack them
+   directly into the code.  And since we're in a crunch, that's what
+   I've done.
+
+   Setting the flag trace_kludge to non-zero enables the code that
+   emits the trace bytecodes at the appropriate points.  */
+static int trace_kludge;
+
+/* 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;
+{
+  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);
+       break;
+
+      case axs_lvalue_memory:
+       {
+         int length = TYPE_LENGTH (value->type);
+
+         /* There's no point in trying to use a trace_quick bytecode
+            here, since "trace_quick SIZE pop" is three bytes, whereas
+            "const8 SIZE trace" is also three bytes, does the same
+            thing, and the simplest code which generates that will also
+            work correctly for objects with large sizes.  */
+         ax_const_l (ax, length);
+         ax_simple (ax, aop_trace);
+       }
+      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);
+       break;
+      }
+  else
+    /* If we're not tracing, just pop the value.  */
+    ax_simple (ax, aop_pop);
+}
+
+
+\f
+/* Generating bytecode from GDB expressions: helper functions */
+
+/* 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;
+{
+  /* Do we need to sign-extend this?  */
+  if (! TYPE_UNSIGNED (type))
+    ax_ext (ax, type->length * TARGET_CHAR_BIT);
+}
+
+
+/* Assume the lower bits of the top of the stack hold a value of 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;
+{
+  int bits = type->length * TARGET_CHAR_BIT;
+  /* I just had to.  */
+  ((TYPE_UNSIGNED (type) ? ax_zero_ext : ax_ext) (ax, bits));
+}
+
+
+/* Assume that the top of the stack contains a value of type "pointer
+   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;
+{
+  if (trace_kludge)
+    {
+      /* Record the area of memory we're about to fetch.  */
+      ax_trace_quick (ax, TYPE_LENGTH (type));
+    }
+
+  switch (type->code)
+    {
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_CHAR:
+      /* It's a scalar value, so we know how to dereference it.  How
+         many bytes long is it?  */
+      switch (type->length)
+       {
+       case 8  / TARGET_CHAR_BIT: ax_simple (ax, aop_ref8 ); break;
+       case 16 / TARGET_CHAR_BIT: ax_simple (ax, aop_ref16); break;
+       case 32 / TARGET_CHAR_BIT: ax_simple (ax, aop_ref32); break;
+       case 64 / TARGET_CHAR_BIT: ax_simple (ax, aop_ref64); break;
+
+         /* Either our caller shouldn't have asked us to dereference
+            that 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.  */
+       default:
+         error ("GDB bug: ax-gdb.c (gen_fetch): strange size");
+       }
+
+      gen_sign_extend (ax, type);
+      break;
+
+    default:
+      /* Either our caller shouldn't have asked us to dereference that
+        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.  */
+      error ("GDB bug: ax-gdb.c (gen_fetch): bad type code");
+    }
+}
+
+
+/* Generate code to left shift the top of the stack by DISTANCE bits, or
+   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;
+{
+  if (distance > 0)
+    {
+      ax_const_l (ax, distance);
+      ax_simple (ax, aop_lsh);
+    }
+  else if (distance < 0)
+    {
+      ax_const_l (ax, -distance);
+      ax_simple (ax, aop_rsh_unsigned);
+    }
+}
+
+
+\f
+/* Generating bytecode from GDB expressions: symbol references */
+
+/* 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;
+{
+  /* FIXME: I'm sure this is wrong for processors other than the 68k.  */
+  ax_reg (ax, FP_REGNUM);
+}
+
+
+/* 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;
+{
+  /* FIXME: I'm sure this is wrong for processors other than the 68k.  */
+  ax_reg (ax, FP_REGNUM);
+}
+
+
+/* Generate code to add OFFSET to the top of the stack.  Try to
+   generate short and readable code.  We use this for getting to
+   variables on the stack, and structure members.  If we were
+   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;
+{
+  /* It would suffice to simply push the offset and add it, but this
+     makes it easier to read positive and negative offsets in the
+     bytecode.  */
+  if (offset > 0)
+    {
+      ax_const_l (ax, offset);
+      ax_simple (ax, aop_add);
+    }
+  else if (offset < 0)
+    {
+      ax_const_l (ax, -offset);
+      ax_simple (ax, aop_sub);
+    }
+}
+
+
+/* In many cases, a symbol's value is the offset from some other
+   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_offset (ax, SYMBOL_VALUE (var));
+}
+
+
+/* Generate code for a variable reference to AX.  The variable is the
+   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;
+{
+  /* Dereference any typedefs. */
+  value->type = check_typedef (SYMBOL_TYPE (var));
+
+  /* I'm imitating the code in read_var_value.  */
+  switch (SYMBOL_CLASS (var))
+    {
+    case LOC_CONST:            /* A constant, like an enum value.  */
+      ax_const_l (ax, (LONGEST) SYMBOL_VALUE (var));
+      value->kind = axs_rvalue;
+      break;
+
+    case LOC_LABEL:            /* A goto label, being used as a value.  */
+      ax_const_l (ax, (LONGEST) SYMBOL_VALUE_ADDRESS (var));
+      value->kind = axs_rvalue;
+      break;
+
+    case LOC_CONST_BYTES:
+      error ("GDB bug: ax-gdb.c (gen_var_ref): LOC_CONST_BYTES symbols are not supported");
+
+      /* Variable at a fixed location in memory.  Easy.  */
+    case LOC_STATIC:
+      /* Push the address of the variable.  */
+      ax_const_l (ax, SYMBOL_VALUE_ADDRESS (var));
+      value->kind = axs_lvalue_memory;
+      break;
+
+    case LOC_ARG:              /* var lives in argument area of frame */
+      gen_frame_args_address (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_sym_offset (ax, var);
+      /* Don't assume any particular pointer size.  */
+      gen_fetch (ax, lookup_pointer_type (builtin_type_void));
+      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_sym_offset (ax, var);
+      value->kind = axs_lvalue_memory;
+      break;
+
+    case LOC_TYPEDEF:
+      error ("Cannot compute value of typedef `%s'.",
+            SYMBOL_SOURCE_NAME (var));
+      break;
+
+    case LOC_BLOCK:
+      ax_const_l (ax, BLOCK_START (SYMBOL_BLOCK_VALUE (var)));
+      value->kind = axs_rvalue;
+      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);
+      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.  */
+    case LOC_REGPARM_ADDR:
+      ax_reg (ax, SYMBOL_VALUE (var));
+      value->kind = axs_lvalue_memory;
+      break;
+
+    case LOC_UNRESOLVED:
+      {
+       struct minimal_symbol *msym 
+         = lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL);
+       if (! msym)
+         error ("Couldn't resolve symbol `%s'.", SYMBOL_SOURCE_NAME (var));
+       
+       /* Push the address of the variable.  */
+       ax_const_l (ax, SYMBOL_VALUE_ADDRESS (msym));
+       value->kind = axs_lvalue_memory;
+      }
+    break;
+
+    case LOC_OPTIMIZED_OUT:
+      error ("The variable `%s' has been optimized out.",
+            SYMBOL_SOURCE_NAME (var));
+      break;
+
+    default:
+      error ("Cannot find value of botched symbol `%s'.",
+            SYMBOL_SOURCE_NAME (var));
+      break;
+    }
+}
+
+
+\f
+/* 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;
+{
+  ax_const_l (ax, k);
+  value->kind = axs_rvalue;
+  value->type = type;
+}
+
+
+\f
+/* Generating bytecode from GDB expressions: unary conversions, casts */
+
+/* Take what's on the top of the stack (as described by VALUE), and
+   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;
+{
+  switch (value->kind)
+    {
+    case axs_rvalue:
+      /* It's already an rvalue.  */
+      break;
+
+    case axs_lvalue_memory:
+      /* The top of stack is the address of the object.  Dereference.  */
+      gen_fetch (ax, value->type);
+      break;
+
+    case axs_lvalue_register:
+      /* There's nothing on the stack, but value->u.reg is the
+         register number containing the value.
+
+        When we add floating-point support, this is going to have to
+        change.  What about SPARC register pairs, for example?  */
+      ax_reg (ax, value->u.reg);
+      gen_extend (ax, value->type);
+      break;
+    }
+
+  value->kind = axs_rvalue;
+}
+
+
+/* Assume the top of the stack is described by VALUE, and perform the
+   usual unary conversions.  This is motivated by ANSI 6.2.2, but of
+   course GDB expressions are not ANSI; they're the mishmash union of
+   a bunch of languages.  Rah.
+
+   NOTE!  This function promises to produce an rvalue only when the
+   incoming value is of an appropriate type.  In other words, the
+   consumer of the value this function produces may assume the value
+   is an rvalue only after checking its type.
+
+   The immediate issue is that if the user tries to use a structure or
+   union as an operand of, say, the `+' operator, we don't want to try
+   to convert that structure to an rvalue; require_rvalue will bomb on
+   structs and unions.  Rather, we want to simply pass the struct
+   lvalue through unchanged, and let `+' raise an error.  */
+
+static void
+gen_usual_unary (ax, value)
+     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)
+    {
+      /* Functions get converted to a pointer to the function.  */
+    case TYPE_CODE_FUNC:
+      value->type = lookup_pointer_type (value->type);
+      value->kind = axs_rvalue;        /* Should always be true, but just in case.  */
+      break;
+
+      /* Arrays get converted to a pointer to their first element, and
+        are no longer an lvalue.  */
+    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
+          is also the address of its first element.  */
+      }
+    break;
+
+    /* Don't try to convert structures and unions to rvalues.  Let the
+       consumer signal an error.  */
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      return;
+
+      /* If the value is an enum, call it an integer.  */
+    case TYPE_CODE_ENUM:
+      value->type = builtin_type_int;
+      break;
+    }
+
+  /* If the value is an lvalue, dereference it.  */
+  require_rvalue (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;
+{
+  return (TYPE_LENGTH (type1) > TYPE_LENGTH (type2)
+         || (TYPE_LENGTH (type1) == TYPE_LENGTH (type2)
+             && TYPE_UNSIGNED (type1)
+             && ! TYPE_UNSIGNED (type2)));
+}
+
+
+/* Return the "wider" of the two types TYPE1 and TYPE2.  */
+static struct type *
+max_type (type1, type2)
+     struct type *type1, *type2;
+{
+  return type_wider_than (type1, type2) ? 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;
+{
+  /* Perhaps there is a more graceful way to state these rules.  */
+
+  /* If we're converting to a narrower type, then we need to clear out
+     the upper bits.  */
+  if (TYPE_LENGTH (to) < TYPE_LENGTH (from))
+    gen_extend (ax, from);
+
+  /* If the two values have equal width, but different signednesses,
+     then we need to extend.  */
+  else if (TYPE_LENGTH (to) == TYPE_LENGTH (from))
+    {
+      if (TYPE_UNSIGNED (from) != TYPE_UNSIGNED (to))
+       gen_extend (ax, to);
+    }
+
+  /* If we're converting to a wider type, and becoming unsigned, then
+     we need to zero out any possible sign bits.  */
+  else if (TYPE_LENGTH (to) > TYPE_LENGTH (from))
+    {
+      if (TYPE_UNSIGNED (to))
+       gen_extend (ax, 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;
+{
+  struct agent_expr *ax = new_agent_expr ();
+  int nontrivial;
+
+  /* Actually generate the code, and see if anything came out.  At the
+     moment, it would be trivial to replicate the code in
+     gen_conversion here, but in the future, when we're supporting
+     floating point and the like, it may not be.  Doing things this
+     way allows this function to be independent of the logic in
+     gen_conversion.  */
+  gen_conversion (ax, from, to);
+  nontrivial = ax->len > 0;
+  free_agent_expr (ax);
+  return nontrivial;
+}
+
+
+/* Generate code to perform the "usual arithmetic conversions" (ANSI C
+   6.2.1.5) for the two operands of an arithmetic operator.  This
+   effectively finds a "least upper bound" type for the two arguments,
+   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;
+{
+  /* Do the usual binary conversions.  */
+  if (TYPE_CODE (value1->type) == TYPE_CODE_INT
+      && TYPE_CODE (value2->type) == TYPE_CODE_INT)
+    {
+      /* The ANSI integral promotions seem to work this way: Order the
+        integer types by size, and then by signedness: an n-bit
+        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,
+                                     max_type (value1->type, value2->type));
+
+      /* Deal with value2, on the top of the stack.  */
+      gen_conversion (ax, value2->type, target);
+
+      /* Deal with value1, not on the top of the stack.  Don't
+         generate the `swap' instructions if we're not actually going
+         to do anything.  */
+      if (is_nontrivial_conversion (value1->type, target))
+       {
+         ax_simple (ax, aop_swap);
+         gen_conversion (ax, value1->type, target);
+         ax_simple (ax, aop_swap);
+       }
+
+      value1->type = value2->type = target;
+    }
+}
+
+
+/* Generate code to perform the integral promotions (ANSI 6.2.1.1) on
+   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;
+{
+  if (! type_wider_than (value->type, builtin_type_int))
+    {
+      gen_conversion (ax, value->type, builtin_type_int);
+      value->type = builtin_type_int;
+    }
+  else if (! type_wider_than (value->type, builtin_type_unsigned_int))
+    {
+      gen_conversion (ax, value->type, builtin_type_unsigned_int);
+      value->type = builtin_type_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;
+{
+  /* 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. */
+  type = check_typedef (type);
+
+  switch (type->code)
+    {
+    case TYPE_CODE_PTR:
+      /* It's implementation-defined, and I'll bet this is what GCC
+         does.  */
+      break;
+
+    case TYPE_CODE_ARRAY:
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+    case TYPE_CODE_FUNC:
+      error ("Illegal type cast: intended type must be scalar.");
+
+    case TYPE_CODE_ENUM:
+      /* 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;
+      break;
+      
+    case TYPE_CODE_INT:
+      gen_conversion (ax, value->type, type);
+      break;
+
+    case TYPE_CODE_VOID:
+      /* We could pop the value, and rely on everyone else to check
+        the type and notice that this value doesn't occupy a stack
+        slot.  But for now, leave the value on the stack, and
+        preserve the "value == stack element" assumption.  */
+      break;
+
+    default:
+      error ("Casts to requested type are not yet implemented.");
+    }
+
+  value->type = type;
+}
+
+
+\f
+/* Generating bytecode from GDB expressions: arithmetic */
+
+/* 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;
+{
+  struct type *element = TYPE_TARGET_TYPE (type);
+
+  if (element->length != 1)
+    {
+      ax_const_l (ax, element->length);
+      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.  */
+static void
+gen_add (ax, value, value1, value2, name)
+     struct agent_expr *ax;
+     struct axs_value *value, *value1, *value2;
+     char *name;
+{
+  /* 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;
+    }
+
+  /* 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;
+    }
+
+  /* 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);
+
+  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.  */
+static void
+gen_sub (ax, value, value1, value2)
+     struct agent_expr *ax;
+     struct axs_value *value, *value1, *value2;
+{
+  struct type *element;
+
+  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;
+       }
+
+      /* 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 ("\
+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 (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;
+    }
+  
+  else
+    error ("Illegal combination of types in subtraction.");
+
+  value->kind = axs_rvalue;
+}
+
+/* Generate code for a binary operator that doesn't do pointer magic.
+   We set VALUE to describe the result value; we assume VALUE1 and
+   VALUE2 describe the two operands, and that they've undergone the
+   usual binary conversions.  MAY_CARRY should be non-zero iff the
+   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;
+{
+  /* 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);
+  
+  ax_simple (ax,
+            TYPE_UNSIGNED (value1->type) ? op_unsigned : op);
+  if (may_carry)
+    gen_extend (ax, value1->type); /* catch overflow */
+  value->type = value1->type;
+  value->kind = axs_rvalue;
+}
+
+
+static void
+gen_logical_not (ax, value)
+     struct agent_expr *ax;
+     struct axs_value *value;
+{
+  if (TYPE_CODE (value->type) != TYPE_CODE_INT
+      && TYPE_CODE (value->type) != TYPE_CODE_PTR)
+    error ("Illegal type of operand to `!'.");
+
+  gen_usual_unary (ax, value);
+  ax_simple (ax, aop_log_not);
+  value->type = builtin_type_int;
+}
+
+
+static void
+gen_complement (ax, value)
+     struct agent_expr *ax;
+     struct axs_value *value;
+{
+  if (TYPE_CODE (value->type) != TYPE_CODE_INT)
+    error ("Illegal 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);
+}
+
+
+\f
+/* Generating bytecode from GDB expressions: * & . -> @ sizeof */
+
+/* Dereference the value on the top of the stack.  */
+static void
+gen_deref (ax, value)
+     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)
+    error ("GDB bug: ax-gdb.c (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
+     actually emit any code; we just change the type from "Pointer to
+     T" to "T", and mark the value as an lvalue in memory.  Leave it
+     to the consumer to actually dereference it.  */
+  value->type = TYPE_TARGET_TYPE (value->type);
+  value->kind = ((value->type->code == 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;
+{
+  /* 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)
+    /* The value's already an rvalue on the stack, so we just need to
+       change the type.  */
+    value->type = lookup_pointer_type (value->type);
+  else
+    switch (value->kind)
+      {
+      case axs_rvalue:
+       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.");
+
+      case axs_lvalue_memory:
+       value->kind = axs_rvalue;
+       value->type = lookup_pointer_type (value->type);
+       break;
+      }
+}
+
+
+/* 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)
+    error ("GDB bug: 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')
+       error ("GDB bug: 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;
+{
+  /* Note that ops[i] fetches 8 << i bits.  */
+  static enum agent_op ops[]
+    = { 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
+     actually occupy; we shouldn't make any accesses we're not
+     explicitly permitted to.  We rely here on the fact that the
+     bytecode `ref' operators work on unaligned addresses.
+
+     It takes some fancy footwork to get the stack to work the way
+     we'd like.  Say we're retrieving a bitfield that requires three
+     fetches.  Initially, the stack just contains the address:
+               addr
+     For the first fetch, we duplicate the address
+               addr addr
+     then add the byte offset, do the fetch, and shift and mask as
+     needed, yielding a fragment of the value, properly aligned for
+     the final bitwise or:
+                addr frag1
+     then we swap, and repeat the process:
+                frag1 addr                    --- address on top
+               frag1 addr addr               --- duplicate it
+                frag1 addr frag2              --- get second fragment
+                frag1 frag2 addr              --- swap again
+                frag1 frag2 frag3             --- get third fragment
+     Notice that, since the third fragment is the last one, we don't
+     bother duplicating the address this time.  Now we have all the
+     fragments on the stack, and we can simply `or' them together,
+     yielding the final value of the bitfield.  */
+
+  /* The first and one-after-last bits in the field, but rounded down
+     and up to byte boundaries.  */
+  int bound_start = (start / TARGET_CHAR_BIT) * TARGET_CHAR_BIT;
+  int bound_end   = (((end + TARGET_CHAR_BIT - 1)
+                     / TARGET_CHAR_BIT)
+                    * TARGET_CHAR_BIT);
+
+  /* current bit offset within the structure */
+  int offset;
+
+  /* The index in ops of the opcode we're considering.  */
+  int op;
+
+  /* The number of fragments we generated in the process.  Probably
+     equal to the number of `one' bits in bytesize, but who cares?  */
+  int fragment_count;
+
+  /* Dereference any typedefs. */
+  type = check_typedef (type);
+
+  /* Can we fetch the number of bits requested at all?  */
+  if ((end - start) > ((1 << num_ops) * 8))
+    error ("GDB bug: ax-gdb.c (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.  */
+  offset = bound_start;
+  fragment_count = 0;
+  for (op = num_ops - 1; op >= 0; op--)
+    {
+      /* number of bits that ops[op] would fetch */
+      int op_size = 8 << op;
+
+      /* The stack at this point, from bottom to top, contains zero or
+        more fragments, then the address.  */
+      
+      /* Does this fetch fit within the bitfield?  */
+      if (offset + op_size <= bound_end)
+       {
+         /* Is this the last fragment?  */
+         int last_frag = (offset + op_size == bound_end);
+
+         if (! last_frag)
+           ax_simple (ax, aop_dup); /* keep a copy of the address */
+         
+         /* Add the offset.  */
+         gen_offset (ax, offset / TARGET_CHAR_BIT);
+
+         if (trace_kludge)
+           {
+             /* Record the area of memory we're about to fetch.  */
+             ax_trace_quick (ax, op_size / TARGET_CHAR_BIT);
+           }
+
+         /* Perform the fetch.  */
+         ax_simple (ax, ops[op]);
+       
+          /* Shift the bits we have to their proper position.
+            gen_left_shift will generate right shifts when the operand
+            is negative.
+
+             A big-endian field diagram to ponder:
+              byte 0  byte 1  byte 2  byte 3  byte 4  byte 5  byte 6  byte 7
+             +------++------++------++------++------++------++------++------+
+             xxxxAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCxxxxxxxxxxx
+                             ^               ^               ^    ^
+             bit number      16              32              48   53
+            These are bit numbers as supplied by GDB.  Note that the
+            bit numbers run from right to left once you've fetched the
+            value!
+
+             A little-endian field diagram to ponder:
+              byte 7  byte 6  byte 5  byte 4  byte 3  byte 2  byte 1  byte 0
+             +------++------++------++------++------++------++------++------+
+             xxxxxxxxxxxAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCxxxx
+                            ^               ^               ^           ^   ^
+             bit number     48              32              16          4   0
+
+             In both cases, the most significant end is on the left
+             (i.e. normal numeric writing order), which means that you
+             don't go crazy thinking about `left' and `right' shifts.
+
+             We don't have to worry about masking yet:
+             - If they contain garbage off the least significant end, then we
+               must be looking at the low end of the field, and the right
+               shift will wipe them out.
+             - If they contain garbage off the most significant end, then we
+               must be looking at the most significant end of the word, and
+               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)
+           gen_left_shift (ax, end - (offset + op_size));
+         else 
+           gen_left_shift (ax, offset - start);
+
+         if (! last_frag)
+           /* Bring the copy of the address up to the top.  */
+           ax_simple (ax, aop_swap);
+
+         offset += op_size;
+         fragment_count++;
+       }
+    }
+
+  /* Generate enough bitwise `or' operations to combine all the
+     fragments we left on the stack.  */
+  while (fragment_count-- > 1)
+    ax_simple (ax, aop_bit_or);
+
+  /* Sign- or zero-extend the value as appropriate.  */
+  ((TYPE_UNSIGNED (type) ? ax_zero_ext : ax_ext) (ax, end - start));
+
+  /* This is *not* an lvalue.  Ugh.  */
+  value->kind = axs_rvalue;
+  value->type = type;
+}
+
+
+/* Generate code to reference the member named FIELD of a structure or
+   union.  The top of the stack, as described by VALUE, should have
+   type (pointer to a)* struct/union.  OPERATOR_NAME is the name of
+   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;
+{
+  struct type *type;
+  int i;
+
+  /* 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)
+    {
+      gen_usual_unary (ax, value);
+      gen_deref (ax, value);
+    }
+  type = 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.",
+          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.");
+
+  i = find_field (type, field);
+  
+  /* 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
+    {
+      gen_offset (ax, TYPE_FIELD_BITPOS (type, i) / TARGET_CHAR_BIT);
+      value->kind = axs_lvalue_memory;
+      value->type = TYPE_FIELD_TYPE (type, i);
+    }
+}
+
+
+/* Generate code for GDB's magical `repeat' operator.  
+   LVALUE @ INT creates an array INT elements long, and whose elements
+   have the same type as LVALUE, located in memory so that LVALUE is
+   its first element.  For example, argv[0]@argc gives you the array
+   of command-line arguments.
+
+   Unfortunately, because we have to know the types before we actually
+   have a value for the expression, we can't implement this perfectly
+   without changing the type system, having values that occupy two
+   stack slots, doing weird things with sizeof, etc.  So we require
+   the right operand to be a constant expression.  */
+static void
+gen_repeat (pc, ax, value)
+     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);
+  if (value1.kind != axs_lvalue_memory)
+    error ("Left operand of `@' must be an object in memory.");
+
+  /* Evaluate the length; it had better be a constant.  */
+  {
+    struct value *v = const_expr (pc);
+    int length;
+
+    if (! v)
+      error ("Right operand of `@' must be a constant, in agent expressions.");
+    if (v->type->code != TYPE_CODE_INT)
+      error ("Right operand of `@' must be an integer.");
+    length = value_as_long (v);
+    if (length <= 0)
+      error ("Right operand of `@' must be positive.");
+
+    /* The top of the stack is already the address of the object, so
+       all we need to do is frob the type of the lvalue.  */
+    {
+      /* FIXME-type-allocation: need a way to free this type when we are
+        done with it.  */
+      struct type *range
+       = create_range_type (0, builtin_type_int, 0, length - 1);
+      struct type *array = create_array_type (0, value1.type, range);
+
+      value->kind = axs_lvalue_memory;
+      value->type = array;
+    }
+  }
+}
+
+
+/* Emit code for the `sizeof' operator.
+   *PC should point at the start of the operand expression; we advance it
+   to the first instruction after the operand.  */
+static void
+gen_sizeof (pc, ax, value)
+     union exp_element **pc;
+     struct agent_expr *ax;
+     struct axs_value *value;
+{
+  /* We don't care about the value of the operand expression; we only
+     care about its type.  However, in the current arrangement, the
+     only way to find an expression's type is to generate code for it.
+     So we generate code for the operand, and then throw it away,
+     replacing it with code that simply pushes its size.  */
+  int start = ax->len;
+  gen_expr (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;
+}
+
+\f
+/* Generating bytecode from GDB expressions: general recursive thingy  */
+
+/* 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;
+{
+  /* Used to hold the descriptions of operand expressions.  */
+  struct axs_value value1, value2;
+  enum exp_opcode op = (*pc)[0].opcode;
+
+  /* If we're looking at a constant expression, just push its value.  */
+  {
+    struct value *v = maybe_const_expr (pc);
+    
+    if (v)
+      {
+       ax_const_l (ax, value_as_long (v));
+       value->kind = axs_rvalue;
+       value->type = check_typedef (VALUE_TYPE (v));
+       return;
+      }
+  }
+
+  /* Otherwise, go ahead and generate code for it.  */
+  switch (op)
+    {
+      /* Binary arithmetic operators.  */
+    case BINOP_ADD:
+    case BINOP_SUB:
+    case BINOP_MUL:
+    case BINOP_DIV:
+    case BINOP_REM:
+    case BINOP_SUBSCRIPT:
+    case BINOP_BITWISE_AND:
+    case BINOP_BITWISE_IOR:
+    case BINOP_BITWISE_XOR:
+      (*pc)++;
+      gen_expr (pc, ax, &value1);
+      gen_usual_unary (ax, &value1);
+      gen_expr (pc, ax, &value2);
+      gen_usual_unary (ax, &value2);
+      gen_usual_arithmetic (ax, &value1, &value2);
+      switch (op)
+       {
+       case BINOP_ADD:
+         gen_add (ax, value, &value1, &value2, "addition");
+         break;
+       case BINOP_SUB:
+         gen_sub (ax, value, &value1, &value2);
+         break;
+       case BINOP_MUL:
+         gen_binop (ax, value, &value1, &value2,
+                    aop_mul, aop_mul, 1, "multiplication");
+         break;
+       case BINOP_DIV:
+         gen_binop (ax, value, &value1, &value2,
+                    aop_div_signed, aop_div_unsigned, 1, "division");
+         break;
+       case BINOP_REM:
+         gen_binop (ax, value, &value1, &value2,
+                    aop_rem_signed, aop_rem_unsigned, 1, "remainder");
+         break;
+       case BINOP_SUBSCRIPT:
+         gen_add (ax, value, &value1, &value2, "array subscripting");
+         if (TYPE_CODE (value->type) != TYPE_CODE_PTR)
+           error ("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;
+
+       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;
+
+       default:
+         /* We should only list operators in the outer case statement
+             that we actually handle in the inner case statement.  */
+         error ("GDB bug: ax-gdb.c (gen_expr): op case sets don't match");
+       }
+      break;
+
+      /* Note that we need to be a little subtle about generating code
+        for comma.  In C, we can do some optimizations here because
+        we know the left operand is only being evaluated for effect.
+        However, if the tracing kludge is in effect, then we always
+        need to evaluate the left hand side fully, so that all the
+        variables it mentions get traced.  */
+    case BINOP_COMMA:
+      (*pc)++;
+      gen_expr (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);
+      /* It's the consumer's responsibility to trace the right operand.  */
+      break;
+      
+    case OP_LONG:              /* some integer constant */
+      {
+       struct type *type = (*pc)[1].type;
+       LONGEST k = (*pc)[2].longconst;
+       (*pc) += 4;
+       gen_int_literal (ax, value, k, type);
+      }
+    break;
+
+    case OP_VAR_VALUE:
+      gen_var_ref (ax, value, (*pc)[2].symbol);
+      (*pc) += 4;
+      break;
+
+    case OP_REGISTER:
+      {
+       int reg = (int) (*pc)[1].longconst;
+       (*pc) += 3;
+       value->kind = axs_lvalue_register;
+       value->u.reg = reg;
+       value->type = REGISTER_VIRTUAL_TYPE (reg);
+      }
+    break;
+
+    case OP_INTERNALVAR:
+      error ("GDB agent expressions cannot use convenience variables.");
+
+    /* 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);
+      break;
+
+    case UNOP_CAST:
+      {
+       struct type *type = (*pc)[1].type;
+       (*pc) += 3;
+       gen_expr (pc, ax, value);
+       gen_cast (ax, value, type);
+      }
+    break;
+
+    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.  */
+         error ("GDB bug: ax-gdb.c (gen_expr): OP_MEMVAL operand isn't an rvalue???");
+       value->type = type;
+       value->kind = axs_lvalue_memory;
+      }
+    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);
+      break;
+
+    case UNOP_LOGICAL_NOT:
+      (*pc)++;
+      gen_expr (pc, ax, value);
+      gen_logical_not (ax, value);
+      break;
+
+    case UNOP_COMPLEMENT:
+      (*pc)++;
+      gen_expr (pc, 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_deref (ax, value);
+      break;
+
+    case UNOP_ADDR:
+      (*pc)++;
+      gen_expr (pc, ax, value);
+      gen_address_of (ax, value);
+      break;
+
+    case UNOP_SIZEOF:
+      (*pc)++;
+      /* Notice that gen_sizeof handles its own operand, unlike most
+        of the other unary operator functions.  This is because we
+        have to throw away the code we generate.  */
+      gen_sizeof (pc, ax, value);
+      break;
+
+    case STRUCTOP_STRUCT:
+    case STRUCTOP_PTR:
+      {
+       int length = (*pc)[1].longconst;
+       char *name = &(*pc)[2].string;
+
+       (*pc) += 4 + BYTES_TO_EXP_ELEM (length + 1);
+       gen_expr (pc, ax, value);
+       if (op == STRUCTOP_STRUCT)
+         gen_struct_ref (ax, value, name, ".", "structure or union");
+       else if (op == STRUCTOP_PTR)
+         gen_struct_ref (ax, value, name, "->",
+                         "pointer to a structure or union");
+       else
+         /* If this `if' chain doesn't handle it, then the case list
+             shouldn't mention it, and we shouldn't be here.  */
+         error ("GDB bug: ax-gdb.c (gen_expr): unhandled struct case");
+      }
+    break;
+
+    case OP_TYPE:
+      error ("Attempt to use a type name as an expression.");
+
+    default:
+      error ("Unsupported operator in expression.");
+    }
+}
+     
+
+\f
+/* 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 (expr, value)
+     struct expression *expr;
+     struct axs_value *value;
+{
+  struct cleanup *old_chain = 0;
+  struct agent_expr *ax = new_agent_expr ();
+  union exp_element *pc;
+
+  old_chain = make_cleanup (free_agent_expr, ax);
+
+  pc = expr->elts;
+  trace_kludge = 0;
+  gen_expr (&pc, ax, value);
+
+  /* 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 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;
+{
+  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.");
+    }
+
+  /* Push the object's size on the stack.  */
+  ax_const_l (ax, TYPE_LENGTH (value.type));
+
+  return ax;
+}
+
+
+/* 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 (expr)
+     struct expression *expr;
+{
+  struct cleanup *old_chain = 0;
+  struct agent_expr *ax = new_agent_expr ();
+  union exp_element *pc;
+  struct axs_value value;
+
+  old_chain = make_cleanup (free_agent_expr, ax);
+
+  pc = expr->elts;
+  trace_kludge = 1;
+  gen_expr (&pc, ax, &value);
+
+  /* Make sure we record the final object, and get rid of it.  */
+  gen_traced_pop (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;
+}
+
+
+\f
+/* The "agent" command, for testing: compile and disassemble an expression.  */
+
+static void
+print_axs_value (f, value)
+     GDB_FILE *f;
+     struct axs_value *value;
+{
+  switch (value->kind)
+    {
+    case axs_rvalue:
+      fputs_filtered ("rvalue", f);
+      break;
+
+    case axs_lvalue_memory:
+      fputs_filtered ("memory lvalue", f);
+      break;
+
+    case axs_lvalue_register:
+      fprintf_filtered (f, "register %d lvalue", value->u.reg);
+      break;
+    }
+
+  fputs_filtered (" : ", f);
+  type_print (value->type, "", f, -1);
+}
+
+
+static void
+agent_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  struct cleanup *old_chain = 0;
+  struct expression *expr;
+  struct agent_expr *agent;
+  struct agent_reqs reqs;
+
+  /* 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_trace_for_expr (expr);
+  make_cleanup (free_agent_expr, agent);
+  ax_print (gdb_stdout, agent);
+  ax_reqs (agent, &reqs);
+
+  do_cleanups (old_chain);
+  dont_repeat ();
+}
+
+\f
+/* Initialization code.  */
+
+_initialize_ax_gdb ()
+{
+  struct cmd_list_element *c;
+
+  add_cmd ("agent", class_maintenance, agent_command,
+          "Translate an expression into remote agent bytecode.",
+          &maintenancelist);
+}