* blockframe.c (block_innermost_frame): Uncomment.

Return NULL if passed NULL.
	* frame.h: Declare it.
	* expression.h (union exp_element): Add field block.
	* parse.c (write_exp_elt_block): New function.
	* expression.h (OP_VAR_VALUE): Now takes additional struct block *.
	* *-exp.y: Write block for OP_VAR_VALUE.
	* eval.c, expprint.c, parse.c: Deal with block for OP_VAR_VALUE.
	* valops.c, value.h (value_of_variable), callers:
	Add second argument, for block.
This commit is contained in:
Jim Kingdon 1993-08-18 19:33:39 +00:00
parent e56ac0ba86
commit 479fdd26ee
9 changed files with 153 additions and 57 deletions

View file

@ -1,5 +1,16 @@
Wed Aug 18 12:03:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com) Wed Aug 18 12:03:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
* blockframe.c (block_innermost_frame): Uncomment.
Return NULL if passed NULL.
* frame.h: Declare it.
* expression.h (union exp_element): Add field block.
* parse.c (write_exp_elt_block): New function.
* expression.h (OP_VAR_VALUE): Now takes additional struct block *.
* *-exp.y: Write block for OP_VAR_VALUE.
* eval.c, expprint.c, parse.c: Deal with block for OP_VAR_VALUE.
* valops.c, value.h (value_of_variable), callers:
Add second argument, for block.
* main.c (gdb_readline): If we read some characters followed by EOF, * main.c (gdb_readline): If we read some characters followed by EOF,
return them rather than returning NULL. return them rather than returning NULL.

View file

@ -724,10 +724,8 @@ find_pc_partial_function (pc, name, address, endaddr)
return 1; return 1;
} }
/* Return the innermost stack frame executing inside of the specified block, /* Return the innermost stack frame executing inside of BLOCK,
or zero if there is no such frame. */ or zero if there is no such frame. If BLOCK is NULL, just return NULL. */
#if 0 /* Currently unused */
FRAME FRAME
block_innermost_frame (block) block_innermost_frame (block)
@ -738,6 +736,9 @@ block_innermost_frame (block)
register CORE_ADDR start = BLOCK_START (block); register CORE_ADDR start = BLOCK_START (block);
register CORE_ADDR end = BLOCK_END (block); register CORE_ADDR end = BLOCK_END (block);
if (block == NULL)
return NULL;
frame = 0; frame = 0;
while (1) while (1)
{ {
@ -750,8 +751,6 @@ block_innermost_frame (block)
} }
} }
#endif /* 0 */
#ifdef SIGCONTEXT_PC_OFFSET #ifdef SIGCONTEXT_PC_OFFSET
/* Get saved user PC for sigtramp from sigcontext for BSD style sigtramp. */ /* Get saved user PC for sigtramp from sigcontext for BSD style sigtramp. */

View file

@ -564,6 +564,8 @@ variable: block COLONCOLON name
copy_name ($3)); copy_name ($3));
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
/* block_found is set by lookup_symbol. */
write_exp_elt_block (block_found);
write_exp_elt_sym (sym); write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE); } write_exp_elt_opcode (OP_VAR_VALUE); }
; ;
@ -620,6 +622,7 @@ variable: qualified_name
if (sym) if (sym)
{ {
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_block (NULL);
write_exp_elt_sym (sym); write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
break; break;
@ -689,6 +692,10 @@ variable: name_not_typename
break; break;
} }
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
/* We want to use the selected frame, not
another more inner frame which happens to
be in the same block. */
write_exp_elt_block (NULL);
write_exp_elt_sym (sym); write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
} }

View file

@ -346,6 +346,7 @@ location : access_name
access_name : LOCATION_NAME access_name : LOCATION_NAME
{ {
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_block (NULL);
write_exp_elt_sym ($1.sym); write_exp_elt_sym ($1.sym);
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
} }
@ -477,6 +478,7 @@ value_name : synonym_name
| GENERAL_PROCEDURE_NAME | GENERAL_PROCEDURE_NAME
{ {
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_block (NULL);
write_exp_elt_sym ($1.sym); write_exp_elt_sym ($1.sym);
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
} }

View file

@ -197,7 +197,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
exp->elts[pc + 2].doubleconst); exp->elts[pc + 2].doubleconst);
case OP_VAR_VALUE: case OP_VAR_VALUE:
(*pos) += 2; (*pos) += 3;
if (noside == EVAL_SKIP) if (noside == EVAL_SKIP)
goto nosideret; goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS) if (noside == EVAL_AVOID_SIDE_EFFECTS)
@ -226,7 +226,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
return value_zero (SYMBOL_TYPE (sym), lv); return value_zero (SYMBOL_TYPE (sym), lv);
} }
else else
return value_of_variable (exp->elts[pc + 1].symbol); return value_of_variable (exp->elts[pc + 2].symbol,
exp->elts[pc + 1].block);
case OP_LAST: case OP_LAST:
(*pos) += 2; (*pos) += 2;
@ -373,6 +374,20 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (op == STRUCTOP_STRUCT) if (op == STRUCTOP_STRUCT)
{ {
/* If v is a variable in a register, and the user types
v.method (), this will produce an error, because v has
no address.
A possible way around this would be to allocate a
copy of the variable on the stack, copy in the
contents, call the function, and copy out the
contents. I.e. convert this from call by reference
to call by copy-return (or whatever it's called).
However, this does not work because it is not the
same: the method being called could stash a copy of
the address, and then future uses through that address
(after the method returns) would be expected to
use the variable itself, not some copy of it. */
arg2 = evaluate_subexp_for_address (exp, pos, noside); arg2 = evaluate_subexp_for_address (exp, pos, noside);
} }
else else
@ -1041,14 +1056,14 @@ evaluate_subexp_for_address (exp, pos, noside)
evaluate_subexp (NULL_TYPE, exp, pos, noside)); evaluate_subexp (NULL_TYPE, exp, pos, noside));
case OP_VAR_VALUE: case OP_VAR_VALUE:
var = exp->elts[pc + 1].symbol; var = exp->elts[pc + 2].symbol;
/* C++: The "address" of a reference should yield the address /* C++: The "address" of a reference should yield the address
* of the object pointed to. Let value_addr() deal with it. */ * of the object pointed to. Let value_addr() deal with it. */
if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_REF) if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_REF)
goto default_case; goto default_case;
(*pos) += 3; (*pos) += 4;
if (noside == EVAL_AVOID_SIDE_EFFECTS) if (noside == EVAL_AVOID_SIDE_EFFECTS)
{ {
struct type *type = struct type *type =
@ -1065,7 +1080,10 @@ evaluate_subexp_for_address (exp, pos, noside)
value_zero (type, not_lval); value_zero (type, not_lval);
} }
else else
return locate_var_value (var, (FRAME) 0); return
locate_var_value
(var,
block_innermost_frame (exp->elts[pc + 1].block));
default: default:
default_case: default_case:
@ -1085,14 +1103,15 @@ evaluate_subexp_for_address (exp, pos, noside)
/* Evaluate like `evaluate_subexp' except coercing arrays to pointers. /* Evaluate like `evaluate_subexp' except coercing arrays to pointers.
When used in contexts where arrays will be coerced anyway, this is When used in contexts where arrays will be coerced anyway, this is
equivalent to `evaluate_subexp' but much faster because it avoids equivalent to `evaluate_subexp' but much faster because it avoids
actually fetching array contents. actually fetching array contents (perhaps obsolete now that we have
VALUE_LAZY).
Note that we currently only do the coercion for C expressions, where Note that we currently only do the coercion for C expressions, where
arrays are zero based and the coercion is correct. For other languages, arrays are zero based and the coercion is correct. For other languages,
with nonzero based arrays, coercion loses. Use CAST_IS_CONVERSION with nonzero based arrays, coercion loses. Use CAST_IS_CONVERSION
to decide if coercion is appropriate. to decide if coercion is appropriate.
*/ */
static value static value
evaluate_subexp_with_coercion (exp, pos, noside) evaluate_subexp_with_coercion (exp, pos, noside)
@ -1111,17 +1130,21 @@ evaluate_subexp_with_coercion (exp, pos, noside)
switch (op) switch (op)
{ {
case OP_VAR_VALUE: case OP_VAR_VALUE:
var = exp->elts[pc + 1].symbol; var = exp->elts[pc + 2].symbol;
if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_ARRAY if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_ARRAY
&& CAST_IS_CONVERSION) && CAST_IS_CONVERSION)
{ {
(*pos) += 3; (*pos) += 4;
val = locate_var_value (var, (FRAME) 0); val =
locate_var_value
(var, block_innermost_frame (exp->elts[pc + 1].block));
return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (var))), return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (var))),
val); val);
} }
default: /* FALLTHROUGH */
return evaluate_subexp (NULL_TYPE, exp, pos, noside);
default:
return evaluate_subexp (NULL_TYPE, exp, pos, noside);
} }
} }
@ -1159,9 +1182,11 @@ evaluate_subexp_for_sizeof (exp, pos)
(LONGEST) TYPE_LENGTH (exp->elts[pc + 1].type)); (LONGEST) TYPE_LENGTH (exp->elts[pc + 1].type));
case OP_VAR_VALUE: case OP_VAR_VALUE:
(*pos) += 3; (*pos) += 4;
return value_from_longest (builtin_type_int, return
(LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol))); value_from_longest
(builtin_type_int,
(LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 2].symbol)));
default: default:
val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);

View file

@ -223,34 +223,27 @@ get_frame_pc PARAMS ((FRAME));
extern CORE_ADDR extern CORE_ADDR
get_pc_function_start PARAMS ((CORE_ADDR)); get_pc_function_start PARAMS ((CORE_ADDR));
extern struct block * extern struct block * block_for_pc PARAMS ((CORE_ADDR));
block_for_pc PARAMS ((CORE_ADDR));
extern int extern int frameless_look_for_prologue PARAMS ((FRAME));
frameless_look_for_prologue PARAMS ((FRAME));
extern void extern void print_frame_args PARAMS ((struct symbol *, struct frame_info *,
print_frame_args PARAMS ((struct symbol *, struct frame_info *, int, FILE *)); int, FILE *));
extern FRAME extern FRAME find_relative_frame PARAMS ((FRAME, int*));
find_relative_frame PARAMS ((FRAME, int*));
extern void extern void print_stack_frame PARAMS ((FRAME, int, int));
print_stack_frame PARAMS ((FRAME, int, int));
extern void extern void select_frame PARAMS ((FRAME, int));
select_frame PARAMS ((FRAME, int));
extern void extern void record_selected_frame PARAMS ((FRAME_ADDR *, int *));
record_selected_frame PARAMS ((FRAME_ADDR *, int *));
extern void extern void print_frame_info PARAMS ((struct frame_info *, int, int, int));
print_frame_info PARAMS ((struct frame_info *, int, int, int));
extern CORE_ADDR extern CORE_ADDR find_saved_register PARAMS ((FRAME, int));
find_saved_register PARAMS ((FRAME, int));
extern CORE_ADDR extern FRAME block_innermost_frame PARAMS ((struct block *));
sigtramp_saved_pc PARAMS ((FRAME));
extern CORE_ADDR sigtramp_saved_pc PARAMS ((FRAME));
#endif /* !defined (FRAME_H) */ #endif /* !defined (FRAME_H) */

View file

@ -559,6 +559,7 @@ fblock : block COLONCOLON BLOCKNAME
/* Useful for assigning to PROCEDURE variables */ /* Useful for assigning to PROCEDURE variables */
variable: fblock variable: fblock
{ write_exp_elt_opcode(OP_VAR_VALUE); { write_exp_elt_opcode(OP_VAR_VALUE);
write_exp_elt_block (NULL);
write_exp_elt_sym ($1); write_exp_elt_sym ($1);
write_exp_elt_opcode (OP_VAR_VALUE); } write_exp_elt_opcode (OP_VAR_VALUE); }
; ;
@ -580,6 +581,8 @@ variable: block COLONCOLON NAME
copy_name ($3)); copy_name ($3));
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
/* block_found is set by lookup_symbol. */
write_exp_elt_block (block_found);
write_exp_elt_sym (sym); write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE); } write_exp_elt_opcode (OP_VAR_VALUE); }
; ;
@ -623,6 +626,10 @@ variable: NAME
break; break;
} }
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
/* We want to use the selected frame, not
another more inner frame which happens to
be in the same block. */
write_exp_elt_block (NULL);
write_exp_elt_sym (sym); write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE); write_exp_elt_opcode (OP_VAR_VALUE);
} }

View file

@ -178,6 +178,15 @@ write_exp_elt_sym (expelt)
write_exp_elt (tmp); write_exp_elt (tmp);
} }
void
write_exp_elt_block (b)
struct block *b;
{
union exp_element tmp;
tmp.block = b;
write_exp_elt (tmp);
}
void void
write_exp_elt_longcst (expelt) write_exp_elt_longcst (expelt)
LONGEST expelt; LONGEST expelt;
@ -389,12 +398,12 @@ length_of_subexp (expr, endpos)
case OP_LONG: case OP_LONG:
case OP_DOUBLE: case OP_DOUBLE:
case OP_VAR_VALUE:
oplen = 4; oplen = 4;
break; break;
case OP_TYPE: case OP_TYPE:
case OP_BOOL: case OP_BOOL:
case OP_VAR_VALUE:
case OP_LAST: case OP_LAST:
case OP_REGISTER: case OP_REGISTER:
case OP_INTERNALVAR: case OP_INTERNALVAR:
@ -518,12 +527,12 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
case OP_LONG: case OP_LONG:
case OP_DOUBLE: case OP_DOUBLE:
case OP_VAR_VALUE:
oplen = 4; oplen = 4;
break; break;
case OP_TYPE: case OP_TYPE:
case OP_BOOL: case OP_BOOL:
case OP_VAR_VALUE:
case OP_LAST: case OP_LAST:
case OP_REGISTER: case OP_REGISTER:
case OP_INTERNALVAR: case OP_INTERNALVAR:

View file

@ -81,7 +81,7 @@ allocate_space_in_inferior (len)
{ {
error ("\"malloc\" exists in this program but is not a function."); error ("\"malloc\" exists in this program but is not a function.");
} }
val = value_of_variable (sym); val = value_of_variable (sym, NULL);
} }
else else
{ {
@ -332,7 +332,7 @@ value_assign (toval, fromval)
int v; /* FIXME, this won't work for large bitfields */ int v; /* FIXME, this won't work for large bitfields */
read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
(char *) &v, sizeof v); (char *) &v, sizeof v);
modify_field ((char *) &v, (int) value_as_long (fromval), modify_field ((char *) &v, value_as_long (fromval),
VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
(char *)&v, sizeof v); (char *)&v, sizeof v);
@ -352,7 +352,7 @@ value_assign (toval, fromval)
read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
(char *) &v, sizeof v); (char *) &v, sizeof v);
modify_field ((char *) &v, (int) value_as_long (fromval), modify_field ((char *) &v, value_as_long (fromval),
VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
(char *) &v, sizeof v); (char *) &v, sizeof v);
@ -415,7 +415,7 @@ value_assign (toval, fromval)
/* Modify what needs to be modified. */ /* Modify what needs to be modified. */
if (VALUE_BITSIZE (toval)) if (VALUE_BITSIZE (toval))
modify_field (buffer + byte_offset, modify_field (buffer + byte_offset,
(int) value_as_long (fromval), value_as_long (fromval),
VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
else if (use_buffer) else if (use_buffer)
memcpy (buffer + byte_offset, raw_buffer, use_buffer); memcpy (buffer + byte_offset, raw_buffer, use_buffer);
@ -498,12 +498,30 @@ value_repeat (arg1, count)
} }
value value
value_of_variable (var) value_of_variable (var, b)
struct symbol *var; struct symbol *var;
struct block *b;
{ {
value val; value val;
FRAME fr;
val = read_var_value (var, (FRAME) 0); if (b == NULL)
/* Use selected frame. */
fr = NULL;
else
{
fr = block_innermost_frame (b);
if (fr == NULL)
{
if (BLOCK_FUNCTION (b) != NULL
&& SYMBOL_NAME (BLOCK_FUNCTION (b)) != NULL)
error ("No frame is currently executing in block %s.",
SYMBOL_NAME (BLOCK_FUNCTION (b)));
else
error ("No frame is currently executing in specified block");
}
}
val = read_var_value (var, fr);
if (val == 0) if (val == 0)
error ("Address of symbol \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var)); error ("Address of symbol \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var));
return val; return val;
@ -632,14 +650,14 @@ push_word (sp, word)
REGISTER_TYPE word; REGISTER_TYPE word;
{ {
register int len = sizeof (REGISTER_TYPE); register int len = sizeof (REGISTER_TYPE);
REGISTER_TYPE buffer; char buffer[MAX_REGISTER_RAW_SIZE];
store_unsigned_integer (&buffer, len, word); store_unsigned_integer (buffer, len, word);
#if 1 INNER_THAN 2 #if 1 INNER_THAN 2
sp -= len; sp -= len;
write_memory (sp, (char *)&buffer, len); write_memory (sp, buffer, len);
#else /* stack grows upward */ #else /* stack grows upward */
write_memory (sp, (char *)&buffer, len); write_memory (sp, buffer, len);
sp += len; sp += len;
#endif /* stack grows upward */ #endif /* stack grows upward */
@ -694,7 +712,15 @@ value_arg_coerce (arg)
{ {
register struct type *type; register struct type *type;
COERCE_ENUM (arg); /* FIXME: We should coerce this according to the prototype (if we have
one). Right now we do a little bit of this in typecmp(), but that
doesn't always get called. For example, if passing a ref to a function
without a prototype, we probably should de-reference it. Currently
we don't. */
if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM)
arg = value_cast (builtin_type_unsigned_int, arg);
#if 1 /* FIXME: This is only a temporary patch. -fnf */ #if 1 /* FIXME: This is only a temporary patch. -fnf */
if (VALUE_REPEATED (arg) if (VALUE_REPEATED (arg)
|| TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY) || TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY)
@ -1153,8 +1179,11 @@ value_string (ptr, len)
return (val); return (val);
} }
/* Compare two argument lists and return the position in which they differ, /* See if we can pass arguments in T2 to a function which takes arguments
or zero if equal. of types T1. Both t1 and t2 are NULL-terminated vectors. If some
arguments need coercion of some sort, then the coerced values are written
into T2. Return value is 0 if the arguments could be matched, or the
position at which they differ if not.
STATICP is nonzero if the T1 argument list came from a STATICP is nonzero if the T1 argument list came from a
static member function. static member function.
@ -1186,8 +1215,22 @@ typecmp (staticp, t1, t2)
if (! t2[i]) if (! t2[i])
return i+1; return i+1;
if (TYPE_CODE (t1[i]) == TYPE_CODE_REF if (TYPE_CODE (t1[i]) == TYPE_CODE_REF
&& TYPE_TARGET_TYPE (t1[i]) == VALUE_TYPE (t2[i])) /* We should be doing hairy argument matching, as below. */
&& (TYPE_CODE (TYPE_TARGET_TYPE (t1[i]))
== TYPE_CODE (VALUE_TYPE (t2[i]))))
{
t2[i] = value_addr (t2[i]);
continue;
}
if (TYPE_CODE (t1[i]) == TYPE_CODE_PTR
&& TYPE_CODE (VALUE_TYPE (t2[i])) == TYPE_CODE_ARRAY)
/* Array to pointer is a `trivial conversion' according to the ARM. */
continue; continue;
/* We should be doing much hairier argument matching (see section 13.2
of the ARM), but as a quick kludge, just check for the same type
code. */
if (TYPE_CODE (t1[i]) != TYPE_CODE (VALUE_TYPE (t2[i]))) if (TYPE_CODE (t1[i]) != TYPE_CODE (VALUE_TYPE (t2[i])))
return i+1; return i+1;
} }