diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
commit | 071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch) | |
tree | 5deda65b8d7b04d1f4cbc534c3206d328e1267ec /gdb/ax-gdb.c | |
parent | 1730ec6b1848f0f32154277f788fb29f88d8475b (diff) | |
download | gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2 |
Initial creation of sourceware repository
Diffstat (limited to 'gdb/ax-gdb.c')
-rw-r--r-- | gdb/ax-gdb.c | 1939 |
1 files changed, 0 insertions, 1939 deletions
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c deleted file mode 100644 index cf2d90e..0000000 --- a/gdb/ax-gdb.c +++ /dev/null @@ -1,1939 +0,0 @@ -/* 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 "frame.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. */ - - - -/* Prototypes for local functions. */ - -/* There's a standard order to the arguments of these functions: - union exp_element ** --- pointer into expression - struct agent_expr * --- agent expression buffer to generate code into - struct axs_value * --- describes value left on top of stack */ - -static struct value *const_var_ref 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)); - - -/* 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; -} - - -/* 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.) */ - - -/* 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); -} - - - -/* 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); - } -} - - - -/* 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; -{ - long frame_reg, frame_offset; - - TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset); - ax_reg (ax, frame_reg); - gen_offset (ax, frame_offset); -} - - -/* 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; -{ - long frame_reg, frame_offset; - - TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset); - ax_reg (ax, frame_reg); - gen_offset (ax, frame_offset); -} - - -/* 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; - } -} - - - -/* 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; -} - - - -/* 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 (0); - 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; -} - - - -/* 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); -} - - - -/* 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 = check_typedef (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; -} - - -/* 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."); - } -} - - - -#if 0 /* not used */ -/* 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 ((make_cleanup_func) 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; -} -#endif /* 0 */ - -/* Given a GDB expression EXPR, return bytecode to trace its value. - The result will use the `trace' and `trace_quick' bytecodes to - record the value of all memory touched by the expression. The - caller can then use the ax_reqs function to discover which - registers it relies upon. */ -struct agent_expr * -gen_trace_for_expr (scope, expr) - CORE_ADDR scope; - struct expression *expr; -{ - struct cleanup *old_chain = 0; - struct agent_expr *ax = new_agent_expr (scope); - union exp_element *pc; - struct axs_value value; - - old_chain = make_cleanup ((make_cleanup_func) 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; -} - - - -/* 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; - 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 ((make_cleanup_func) free_current_contents, &expr); - agent = gen_trace_for_expr (fi->pc, expr); - make_cleanup ((make_cleanup_func) free_agent_expr, agent); - ax_print (gdb_stdout, agent); - ax_reqs (agent, &reqs); - - do_cleanups (old_chain); - dont_repeat (); -} - - -/* 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); -} |