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 Michael Snyder <msnyder@redhat.com>
+ 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 <jimb@redhat.com>
* s390-tdep.c (s390_pop_frame_regular): On the S/390, the frame
}
;
+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
{ $$ = 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
}
;
+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; }
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
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);
\f
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:
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:
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,
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, " ");
}
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;
}
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.
*/
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:
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))
template <class T1, class T2> 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++)
{
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
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);
}
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
/* 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 */
#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
{
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;
#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
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
/* 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)
{
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)
{
int done = 0;
int make_const = 0;
int make_volatile = 0;
+ int make_addr_space = 0;
int array_size;
struct type *range_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;
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)
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 ();
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
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);