From 47663de5984a7cf5eff8c8780cdf093aa9629a64 Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Thu, 15 Nov 2001 01:55:59 +0000 Subject: [PATCH] 2001-11-14 Michael Snyder Add address space identifiers to expression language for types. * c-exp.y (space_identifier, cv_with_space_id, const_or_volatile_or_space_identifier_noopt, const_or_volatile_or_space_identifier): New terminals. (ptype): Accept const_or_volatile_or_space_identifier. (typebase): Accept const_or_volatile_or_space_identifier. * c-typeprint.c (c_type_print_cv_qualifier): Rename to c_type_print_modifier. Handle address space modified types. * gdbtypes.h (TYPE_FLAG_CODE_SPACE, TYPE_FLAG_DATA_SPACE): New type flags. (struct type): Add new field as_type for addr-space qualified types. (TYPE_AS_TYPE): New macro, retrieves the chain of types that are identical to this one except for address-space qualification. * gdbtypes.c (alloc_type): Initialize new field 'as_type'. (address_space_name_to_int): New function. (address_space_int_to_name): New function. (make_type_with_address_space): New function. (make_cv_type): Handle as_type field of new struct type object. * parse.c (check_type_stack_depth): New function. (push_type_address_space): New function. (follow_types): Handle types with address-space qualifier. * parser-defs.h (enum type_pieces): Add enum tp_space_identifier. --- gdb/ChangeLog | 24 +++++++++++++++++++ gdb/c-exp.y | 57 ++++++++++++++++++++++++++++++++------------- gdb/c-typeprint.c | 45 ++++++++++++++++++++++-------------- gdb/gdbtypes.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/gdbtypes.h | 36 +++++++++++++++++++++++++++++ gdb/parse.c | 48 ++++++++++++++++++++++++++++++-------- gdb/parser-defs.h | 5 +++- 7 files changed, 240 insertions(+), 44 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f13b54a..9a60f6a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2001-11-14 Michael Snyder + Add address space identifiers to expression language for types. + * c-exp.y (space_identifier, cv_with_space_id, + const_or_volatile_or_space_identifier_noopt, + const_or_volatile_or_space_identifier): New terminals. + (ptype): Accept const_or_volatile_or_space_identifier. + (typebase): Accept const_or_volatile_or_space_identifier. + * c-typeprint.c (c_type_print_cv_qualifier): Rename to + c_type_print_modifier. Handle address space modified types. + * gdbtypes.h (TYPE_FLAG_CODE_SPACE, TYPE_FLAG_DATA_SPACE): + New type flags. + (struct type): Add new field as_type for addr-space qualified types. + (TYPE_AS_TYPE): New macro, retrieves the chain of types that are + identical to this one except for address-space qualification. + * gdbtypes.c (alloc_type): Initialize new field 'as_type'. + (address_space_name_to_int): New function. + (address_space_int_to_name): New function. + (make_type_with_address_space): New function. + (make_cv_type): Handle as_type field of new struct type object. + * parse.c (check_type_stack_depth): New function. + (push_type_address_space): New function. + (follow_types): Handle types with address-space qualifier. + * parser-defs.h (enum type_pieces): Add enum tp_space_identifier. + 2001-11-14 Jim Blandy * s390-tdep.c (s390_pop_frame_regular): On the S/390, the frame diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 6605751..3d2d1aa 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -718,24 +718,28 @@ variable: name_not_typename } ; +space_identifier : '@' NAME + { push_type_address_space (copy_name ($2.stoken)); + push_type (tp_space_identifier); + } + ; -ptype : typebase - | ptype const_or_volatile abs_decl const_or_volatile - { $$ = follow_types ($1); } +const_or_volatile: const_or_volatile_noopt + | ; -const_and_volatile: CONST_KEYWORD VOLATILE_KEYWORD - | VOLATILE_KEYWORD CONST_KEYWORD + +cv_with_space_id : const_or_volatile space_identifier const_or_volatile ; -const_or_volatile_noopt: const_and_volatile - { push_type (tp_const); push_type (tp_volatile);} - | CONST_KEYWORD - { push_type (tp_const);} - | VOLATILE_KEYWORD - { push_type (tp_volatile); } + +const_or_volatile_or_space_identifier_noopt: cv_with_space_id + | const_or_volatile_noopt ; -const_or_volatile: const_or_volatile_noopt - | + +const_or_volatile_or_space_identifier: + const_or_volatile_or_space_identifier_noopt + | ; + abs_decl: '*' { push_type (tp_pointer); $$ = 0; } | '*' abs_decl @@ -852,8 +856,10 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */ { $$ = lookup_template_type(copy_name($2), $4, expression_context_block); } - | const_or_volatile_noopt typebase { $$ = follow_types ($2); } - | typebase const_or_volatile_noopt { $$ = follow_types ($1); } + | const_or_volatile_or_space_identifier_noopt typebase + { $$ = follow_types ($2); } + | typebase const_or_volatile_or_space_identifier_noopt + { $$ = follow_types ($1); } ; typename: TYPENAME @@ -890,6 +896,25 @@ nonempty_typelist } ; +ptype : typebase + | ptype const_or_volatile_or_space_identifier abs_decl const_or_volatile_or_space_identifier + { $$ = follow_types ($1); } + ; + +const_and_volatile: CONST_KEYWORD VOLATILE_KEYWORD + | VOLATILE_KEYWORD CONST_KEYWORD + ; + +const_or_volatile_noopt: const_and_volatile + { push_type (tp_const); + push_type (tp_volatile); + } + | CONST_KEYWORD + { push_type (tp_const); } + | VOLATILE_KEYWORD + { push_type (tp_volatile); } + ; + name : NAME { $$ = $1.stoken; } | BLOCKNAME { $$ = $1.stoken; } | TYPENAME { $$ = $1.stoken; } @@ -1683,7 +1708,7 @@ yylex () return TYPENAME; } if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0) - return TYPENAME; + return TYPENAME; /* Input names that aren't symbols but ARE valid hex numbers, when the input radix permits them, can be names or numbers diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 789d5f0..c830029 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -52,8 +52,9 @@ static void cp_type_print_derivation_info (struct ui_file *, struct type *); void c_type_print_varspec_prefix (struct type *, struct ui_file *, int, int); -static void c_type_print_cv_qualifier (struct type *, struct ui_file *, - int, int); +/* Print "const", "volatile", or address space modifiers. */ +static void c_type_print_modifier (struct type *, struct ui_file *, + int, int); @@ -211,7 +212,7 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, case TYPE_CODE_PTR: c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); fprintf_filtered (stream, "*"); - c_type_print_cv_qualifier (type, stream, 1, 0); + c_type_print_modifier (type, stream, 1, 0); break; case TYPE_CODE_MEMBER: @@ -242,7 +243,7 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, case TYPE_CODE_REF: c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); fprintf_filtered (stream, "&"); - c_type_print_cv_qualifier (type, stream, 1, 0); + c_type_print_modifier (type, stream, 1, 0); break; case TYPE_CODE_FUNC: @@ -289,10 +290,11 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, NEED_SPACE = 1 indicates an initial white space is needed */ static void -c_type_print_cv_qualifier (struct type *type, struct ui_file *stream, - int need_pre_space, int need_post_space) +c_type_print_modifier (struct type *type, struct ui_file *stream, + int need_pre_space, int need_post_space) { - int flag = 0; + int did_print_modifier = 0; + char *address_space_id; /* We don't print `const' qualifiers for references --- since all operators affect the thing referenced, not the reference itself, @@ -303,18 +305,27 @@ c_type_print_cv_qualifier (struct type *type, struct ui_file *stream, if (need_pre_space) fprintf_filtered (stream, " "); fprintf_filtered (stream, "const"); - flag = 1; + did_print_modifier = 1; } if (TYPE_VOLATILE (type)) { - if (flag || need_pre_space) + if (did_print_modifier || need_pre_space) fprintf_filtered (stream, " "); fprintf_filtered (stream, "volatile"); - flag = 1; + did_print_modifier = 1; } - if (flag && need_post_space) + address_space_id = address_space_int_to_name (TYPE_FLAGS (type)); + if (address_space_id) + { + if (did_print_modifier || need_pre_space) + fprintf_filtered (stream, " "); + fprintf_filtered (stream, "@%s", address_space_id); + did_print_modifier = 1; + } + + if (did_print_modifier && need_post_space) fprintf_filtered (stream, " "); } @@ -655,7 +666,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, if (show <= 0 && TYPE_NAME (type) != NULL) { - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); fputs_filtered (TYPE_NAME (type), stream); return; } @@ -675,7 +686,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_STRUCT: - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); /* Note TYPE_CODE_STRUCT and TYPE_CODE_CLASS have the same value, * so we use another means for distinguishing them. */ @@ -708,7 +719,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, goto struct_union; case TYPE_CODE_UNION: - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); fprintf_filtered (stream, "union "); struct_union: @@ -1023,7 +1034,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_ENUM: - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); /* HP C supports sized enums */ if (hp_som_som_object_present) switch (TYPE_LENGTH (type)) @@ -1104,7 +1115,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, template class " and then merges with the struct/union/class code to print the rest of the definition. */ - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); fprintf_filtered (stream, "template <"); for (i = 0; i < TYPE_NTEMPLATE_ARGS (type); i++) { @@ -1139,7 +1150,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, is no type name, then complain. */ if (TYPE_NAME (type) != NULL) { - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); fputs_filtered (TYPE_NAME (type), stream); } else diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index bf05cf0..8a941de 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -146,6 +146,7 @@ alloc_type (struct objfile *objfile) TYPE_OBJFILE (type) = objfile; TYPE_VPTR_FIELDNO (type) = -1; TYPE_CV_TYPE (type) = type; /* chain back to itself */ + TYPE_AS_TYPE (type) = type; /* ditto */ return (type); } @@ -323,6 +324,73 @@ lookup_function_type (struct type *type) return make_function_type (type, (struct type **) 0); } +/* Identify address space identifier by name -- + return the integer flag defined in gdbtypes.h. */ +extern int +address_space_name_to_int (char *space_identifier) +{ + /* Check for known address space delimiters. */ + if (!strcmp (space_identifier, "code")) + return TYPE_FLAG_CODE_SPACE; + else if (!strcmp (space_identifier, "data")) + return TYPE_FLAG_DATA_SPACE; + else + error ("Unknown address space specifier: \"%s\"", space_identifier); +} + +/* Identify address space identifier by integer flag as defined in + gdbtypes.h -- return the string version of the adress space name. */ + +extern char * +address_space_int_to_name (int space_flag) +{ + if (space_flag & TYPE_FLAG_CODE_SPACE) + return "code"; + else if (space_flag & TYPE_FLAG_DATA_SPACE) + return "data"; + else + return NULL; +} + +/* Make an address-space-delimited variant of a type -- a type that + is identical to the one supplied except that it has an address + space attribute attached to it (such as "code" or "data"). + + This is for Harvard architectures. */ + +struct type * +make_type_with_address_space (struct type *type, int space_flag) +{ + struct type *ntype; + + ntype = type; + do { + if ((ntype->flags & space_flag) != 0) + return ntype; + ntype = TYPE_AS_TYPE (ntype); + } while (ntype != type); + + /* Create a new, duplicate type. */ + ntype = alloc_type (TYPE_OBJFILE (type)); + /* Copy original type. */ + memcpy ((char *) ntype, (char *) type, sizeof (struct type)); + + /* Pointers or references to the original type are not relevant to + the new type; but if the original type is a pointer, the new type + points to the same thing (so TYPE_TARGET_TYPE remains unchanged). */ + TYPE_POINTER_TYPE (ntype) = (struct type *) 0; + TYPE_REFERENCE_TYPE (ntype) = (struct type *) 0; + TYPE_CV_TYPE (ntype) = ntype; + + /* Chain the new address-space-specific type to the old type. */ + ntype->as_type = type->as_type; + type->as_type = ntype; + + /* Now set the address-space flag, and return the new type. */ + ntype->flags |= space_flag; + return ntype; +} + /* Make a "c-v" variant of a type -- a type that is identical to the one supplied except that it may have const or volatile attributes @@ -380,6 +448,7 @@ make_cv_type (int cnst, int voltl, struct type *type, struct type **typeptr) /* But zero out fields that shouldn't be copied */ TYPE_POINTER_TYPE (ntype) = (struct type *) 0; /* Need new pointer kind */ TYPE_REFERENCE_TYPE (ntype) = (struct type *) 0; /* Need new referene kind */ + TYPE_AS_TYPE (ntype) = ntype; /* Need new address-space kind. */ /* Note: TYPE_TARGET_TYPE can be left as is */ /* Set flags appropriately */ diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 686983c..3bc8131 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -206,6 +206,28 @@ enum type_code #define TYPE_FLAG_INCOMPLETE (1 << 8) +/* Instruction-space delimited type. This is for Harvard architectures + which have separate instruction and data address spaces (and perhaps + others). + + GDB usually defines a flat address space that is a superset of the + architecture's two (or more) address spaces, but this is an extension + of the architecture's model. + + If TYPE_FLAG_INST is set, an object of the corresponding type + resides in instruction memory, even if its address (in the extended + flat address space) does not reflect this. + + Similarly, if TYPE_FLAG_DATA is set, then an object of the + corresponding type resides in the data memory space, even if + this is not indicated by its (flat address space) address. + + If neither flag is set, the default space for functions / methods + is instruction space, and for data objects is data memory. */ + +#define TYPE_FLAG_CODE_SPACE (1 << 9) +#define TYPE_FLAG_DATA_SPACE (1 << 10) + struct type { @@ -310,6 +332,12 @@ struct type are chained together in a ring. */ struct type *cv_type; + /* Address-space delimited variant chain. This points to a type + that differs from this one only in an address-space qualifier + attribute. The otherwise-identical address-space delimited + types are chained together in a ring. */ + struct type *as_type; + /* Flags about this type. */ int flags; @@ -689,6 +717,7 @@ extern void allocate_cplus_struct_type (struct type *); #define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type #define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type #define TYPE_CV_TYPE(thistype) (thistype)->cv_type +#define TYPE_AS_TYPE(thistype) (thistype)->as_type /* Note that if thistype is a TYPEDEF type, you have to call check_typedef. But check_typedef does set the TYPE_LENGTH of the TYPEDEF type, so you only have to call check_typedef once. Since allocate_value @@ -1008,6 +1037,13 @@ extern struct type *make_reference_type (struct type *, struct type **); extern struct type *make_cv_type (int, int, struct type *, struct type **); +extern int address_space_name_to_int (char *); + +extern char *address_space_int_to_name (int); + +extern struct type *make_type_with_address_space (struct type *type, + int space_identifier); + extern struct type *lookup_member_type (struct type *, struct type *); extern void diff --git a/gdb/parse.c b/gdb/parse.c index 64966ed..42fccc6 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -1208,8 +1208,8 @@ parse_expression (char *string) /* Stuff for maintaining a stack of types. Currently just used by C, but probably useful for any language which declares its types "backwards". */ -void -push_type (enum type_pieces tp) +static void +check_type_stack_depth (void) { if (type_stack_depth == type_stack_size) { @@ -1217,21 +1217,28 @@ push_type (enum type_pieces tp) type_stack = (union type_stack_elt *) xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack)); } +} + +void +push_type (enum type_pieces tp) +{ + check_type_stack_depth (); type_stack[type_stack_depth++].piece = tp; } void push_type_int (int n) { - if (type_stack_depth == type_stack_size) - { - type_stack_size *= 2; - type_stack = (union type_stack_elt *) - xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack)); - } + check_type_stack_depth (); type_stack[type_stack_depth++].int_val = n; } +void +push_type_address_space (char *string) +{ + push_type_int (address_space_name_to_int (string)); +} + enum type_pieces pop_type (void) { @@ -1257,6 +1264,7 @@ follow_types (struct type *follow_type) int done = 0; int make_const = 0; int make_volatile = 0; + int make_addr_space = 0; int array_size; struct type *range_type; @@ -1273,6 +1281,11 @@ follow_types (struct type *follow_type) follow_type = make_cv_type (TYPE_CONST (follow_type), make_volatile, follow_type, 0); + if (make_addr_space) + follow_type = make_type_with_address_space (follow_type, + make_addr_space); + make_const = make_volatile = 0; + make_addr_space = 0; break; case tp_const: make_const = 1; @@ -1280,6 +1293,9 @@ follow_types (struct type *follow_type) case tp_volatile: make_volatile = 1; break; + case tp_space_identifier: + make_addr_space = pop_type_int (); + break; case tp_pointer: follow_type = lookup_pointer_type (follow_type); if (make_const) @@ -1290,15 +1306,27 @@ follow_types (struct type *follow_type) follow_type = make_cv_type (TYPE_CONST (follow_type), make_volatile, follow_type, 0); + if (make_addr_space) + follow_type = make_type_with_address_space (follow_type, + make_addr_space); make_const = make_volatile = 0; + make_addr_space = 0; break; case tp_reference: follow_type = lookup_reference_type (follow_type); if (make_const) - follow_type = make_cv_type (make_const, TYPE_VOLATILE (follow_type), follow_type, 0); + follow_type = make_cv_type (make_const, + TYPE_VOLATILE (follow_type), + follow_type, 0); if (make_volatile) - follow_type = make_cv_type (TYPE_CONST (follow_type), make_volatile, follow_type, 0); + follow_type = make_cv_type (TYPE_CONST (follow_type), + make_volatile, + follow_type, 0); + if (make_addr_space) + follow_type = make_type_with_address_space (follow_type, + make_addr_space); make_const = make_volatile = 0; + make_addr_space = 0; break; case tp_array: array_size = pop_type_int (); diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h index bd7fb39..66e929f 100644 --- a/gdb/parser-defs.h +++ b/gdb/parser-defs.h @@ -90,7 +90,8 @@ enum type_pieces tp_array, tp_function, tp_const, - tp_volatile + tp_volatile, + tp_space_identifier }; /* The stack can contain either an enum type_pieces or an int. */ union type_stack_elt @@ -141,6 +142,8 @@ extern void push_type (enum type_pieces); extern void push_type_int (int); +extern void push_type_address_space (char *); + extern enum type_pieces pop_type (void); extern int pop_type_int (void); -- 2.7.4