* debug.h (enum debug_type_kind): Add DEBUG_KIND_ILLEGAL.

(struct debug_write_fns): Add field ellipsis_type.  Add id
	parameter to start_struct_type, start_class_type, and tag_type.
	(debug_make_ellipsis_type): Declare.
	(debug_find_named_type): Declare.
	(debug_get_type_kind): Declare.
	(debug_get_return_type): Declare.
	(debug_get_parameter_types): Declare.
	(debug_get_fields): Declare.
	(debug_get_field_type): Declare.
	* debug.c (struct debug_handle): Add fields class_id and base_id.
	(struct debug_class_type): Add field id.
	(struct debug_method_variant): Rename argtypes to physname.
	Change all uses.
	(debug_ellipsis_type): New static variable.
	(ELLIPSIS_P): New macro.
	(debug_make_ellipsis_type): New function.
	(debug_make_method_variant): Rename argtypes to physname.
	(debug_make_static_method_variant): Likewise.
	(debug_name_type): Always put types in the global namespace.
	(debug_find_named_type): New function.
	(debug_find_tagged_type): Treat DEBUG_KIND_ILLEGAL specially,
	rather than DEBUG_KIND_VOID.
	(debug_get_real_type): New static function.
	(debug_get_type_kind): New function.
	(debug_get_return_type): New function.
	(debug_get_parameter_types): New function.
	(debug_get_fields): New function.
	(debug_get_field_type): New function.
	(debug_write): Initialize base_id.
	(debug_write_type): Pass new id argument to tag_type.  Handle
	DEBUG_KIND_ILLEGAL.  Use id for	DEBUG_KIND_STRUCT and
	DEBUG_KIND_UNION.  Handle ellipsis for method arguments.
	(debug_write_class_type): Don't dereference kclass if it is NULL.
	Use id.
	* prdbg.c (pr_fns): Add pr_ellipsis_type.
	(pr_ellipsis_type): New static function.
	(pr_pointer_type): If this is a pointer to an array, parenthesize
	it correctly.
	(pr_start_struct_type): Add id parameter.
	(pr_start_class_type): Likewise.
	(pr_tag_type): Likewise.
	(pr_fix_visibility): Add the visibility to the top of the stack,
	not the second element on the stack.
	(pr_struct_field): Pop the stack before calling pr_fix_visibility.
	(pr_class_static_member): Likewise.
	(pr_class_start_method): Don't push a type, just set the method
	name in the type on the top of the stack.
	(pr_class_end_method): Don't pop the stack.
	(pr_class_method_variant): Rename argtypes parameter to physname.
	Append const and volatile rather than prepending them.  Add a
	space after the physname.
	(pr_class_static_method_variant): Likewise.
	* ieee.c (ieee_fns): Add ieee_ellipsis_type.
	(ieee_define_named_type): Use DEBUG_KIND_ILLEGAL rather than
	DEBUG_KIND_VOID.
	(write_ieee_debugging_info): Likewise.
	(ieee_typdef): Likewise.
	(ieee_ellipsis_type): New static function.
	(ieee_start_struct_type): Add id parameter.
	(ieee_start_class_type): Likewise.
	(ieee_tag_type): Likewise.
	(ieee_class_method_variant): Rename name to physname.
	(ieee_class_static_method_variant): Likewise.
This commit is contained in:
Ian Lance Taylor 1996-01-19 18:03:04 +00:00
parent 8c038399b5
commit 07aa1e1b7a
4 changed files with 502 additions and 145 deletions

View file

@ -54,6 +54,10 @@ struct debug_handle
unsigned int mark;
/* Another mark used by debug_write. */
unsigned int class_mark;
/* A struct/class ID used by debug_write. */
unsigned int class_id;
/* The base for class_id for this call to debug_write. */
unsigned int base_id;
};
/* Information we keep for a single compilation unit. */
@ -150,6 +154,8 @@ struct debug_class_type
debug_field *fields;
/* A mark field used to avoid recursively printing out structs. */
unsigned int mark;
/* This is used to uniquely identify unnamed structs when printing. */
unsigned int id;
/* The remaining fields are only used for DEBUG_KIND_CLASS and
DEBUG_KIND_UNION_CLASS. */
/* NULL terminated array of base classes. */
@ -309,8 +315,8 @@ struct debug_method
struct debug_method_variant
{
/* The argument types of the function. */
const char *argtypes;
/* The physical name of the function. */
const char *physname;
/* The type of the function. */
struct debug_type *type;
/* The visibility of the function. */
@ -497,6 +503,17 @@ struct debug_name
} u;
};
/* This variable is an ellipsis type. The contents are not used; its
address is returned by debug_make_ellipsis_type, and anything which
needs to know whether it is dealing with an ellipsis compares
addresses. */
static const struct debug_type debug_ellipsis_type;
#define ELLIPSIS_P(t) ((t) == &debug_ellipsis_type)
/* Local functions. */
static void debug_error PARAMS ((const char *));
static struct debug_name *debug_add_to_namespace
PARAMS ((struct debug_handle *, struct debug_namespace **, const char *,
@ -506,6 +523,7 @@ static struct debug_name *debug_add_to_current_namespace
enum debug_object_linkage));
static struct debug_type *debug_make_type
PARAMS ((struct debug_handle *, enum debug_type_kind, unsigned int));
static struct debug_type *debug_get_real_type PARAMS ((PTR, debug_type));
static boolean debug_write_name
PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
struct debug_name *));
@ -1223,6 +1241,18 @@ debug_make_indirect_type (handle, slot, tag)
return t;
}
/* Make an ellipsis type. This is not a type at all, but is a marker
suitable for appearing in the list of argument types passed to
debug_make_method_type. It should be used to indicate a method
which takes a variable number of arguments. */
debug_type
debug_make_ellipsis_type (handle)
PTR handle;
{
return (debug_type) &debug_ellipsis_type;
}
/* Make a void type. There is only one of these. */
debug_type
@ -1847,10 +1877,10 @@ debug_make_method (handle, name, variants)
/*ARGSUSED*/
debug_method_variant
debug_make_method_variant (handle, argtypes, type, visibility, constp,
debug_make_method_variant (handle, physname, type, visibility, constp,
volatilep, voffset, context)
PTR handle;
const char *argtypes;
const char *physname;
debug_type type;
enum debug_visibility visibility;
boolean constp;
@ -1863,7 +1893,7 @@ debug_make_method_variant (handle, argtypes, type, visibility, constp,
m = (struct debug_method_variant *) xmalloc (sizeof *m);
memset (m, 0, sizeof *m);
m->argtypes = argtypes;
m->physname = physname;
m->type = type;
m->visibility = visibility;
m->constp = constp;
@ -1879,10 +1909,10 @@ debug_make_method_variant (handle, argtypes, type, visibility, constp,
since a static method can not also be virtual. */
debug_method_variant
debug_make_static_method_variant (handle, argtypes, type, visibility,
debug_make_static_method_variant (handle, physname, type, visibility,
constp, volatilep)
PTR handle;
const char *argtypes;
const char *physname;
debug_type type;
enum debug_visibility visibility;
boolean constp;
@ -1893,7 +1923,7 @@ debug_make_static_method_variant (handle, argtypes, type, visibility,
m = (struct debug_method_variant *) xmalloc (sizeof *m);
memset (m, 0, sizeof *m);
m->argtypes = argtypes;
m->physname = physname;
m->type = type;
m->visibility = visibility;
m->constp = constp;
@ -1919,6 +1949,13 @@ debug_name_type (handle, name, type)
if (name == NULL || type == NULL)
return DEBUG_TYPE_NULL;
if (info->current_unit == NULL
|| info->current_file == NULL)
{
debug_error ("debug_record_variable: no current file");
return false;
}
t = debug_make_type (info, DEBUG_KIND_NAMED, 0);
if (t == NULL)
return DEBUG_TYPE_NULL;
@ -1930,10 +1967,11 @@ debug_name_type (handle, name, type)
t->u.knamed = n;
/* We also need to add the name to the current namespace. */
/* We always add the name to the global namespace. This is probably
wrong in some cases, but it seems to be right for stabs. FIXME. */
nm = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_TYPE,
DEBUG_LINKAGE_NONE);
nm = debug_add_to_namespace (info, &info->current_file->globals, name,
DEBUG_OBJECT_TYPE, DEBUG_LINKAGE_NONE);
if (nm == NULL)
return false;
@ -2018,6 +2056,61 @@ debug_record_type_size (handle, type, size)
return true;
}
/* Find a named type. */
debug_type
debug_find_named_type (handle, name)
PTR handle;
const char *name;
{
struct debug_handle *info = (struct debug_handle *) handle;
struct debug_block *b;
struct debug_file *f;
/* We only search the current compilation unit. I don't know if
this is right or not. */
if (info->current_unit == NULL)
{
debug_error ("debug_find_named_type: no current compilation unit");
return DEBUG_TYPE_NULL;
}
for (b = info->current_block; b != NULL; b = b->parent)
{
if (b->locals != NULL)
{
struct debug_name *n;
for (n = b->locals->list; n != NULL; n = n->next)
{
if (n->kind == DEBUG_OBJECT_TYPE
&& n->name[0] == name[0]
&& strcmp (n->name, name) == 0)
return n->u.type;
}
}
}
for (f = info->current_unit->files; f != NULL; f = f->next)
{
if (f->globals != NULL)
{
struct debug_name *n;
for (n = f->globals->list; n != NULL; n = n->next)
{
if (n->kind == DEBUG_OBJECT_TYPE
&& n->name[0] == name[0]
&& strcmp (n->name, name) == 0)
return n->u.type;
}
}
}
return DEBUG_TYPE_NULL;
}
/* Find a tagged type. */
debug_type
@ -2045,7 +2138,7 @@ debug_find_tagged_type (handle, name, kind)
for (n = f->globals->list; n != NULL; n = n->next)
{
if (n->kind == DEBUG_OBJECT_TAG
&& (kind == DEBUG_KIND_VOID
&& (kind == DEBUG_KIND_ILLEGAL
|| n->u.tag->kind == kind)
&& n->name[0] == name[0]
&& strcmp (n->name, name) == 0)
@ -2058,9 +2151,42 @@ debug_find_tagged_type (handle, name, kind)
return DEBUG_TYPE_NULL;
}
/* Get a base type. */
static struct debug_type *
debug_get_real_type (handle, type)
PTR handle;
debug_type type;
{
switch (type->kind)
{
default:
return type;
case DEBUG_KIND_INDIRECT:
if (*type->u.kindirect->slot != NULL)
return debug_get_real_type (handle, *type->u.kindirect->slot);
return type;
case DEBUG_KIND_NAMED:
return debug_get_real_type (handle, type->u.knamed->type);
}
/*NOTREACHED*/
}
/* Get the kind of a type. */
enum debug_type_kind
debug_get_type_kind (handle, type)
PTR handle;
debug_type type;
{
if (type == NULL)
return DEBUG_KIND_ILLEGAL;
type = debug_get_real_type (handle, type);
return type->kind;
}
/* Get the name of a type. */
/*ARGSUSED*/
const char *
debug_get_type_name (handle, type)
PTR handle;
@ -2077,6 +2203,86 @@ debug_get_type_name (handle, type)
return type->u.knamed->name->name;
return NULL;
}
/* Get the return type of a function or method type. */
debug_type
debug_get_return_type (handle, type)
PTR handle;
debug_type type;
{
if (type == NULL)
return DEBUG_TYPE_NULL;
type = debug_get_real_type (handle, type);
switch (type->kind)
{
default:
return DEBUG_TYPE_NULL;
case DEBUG_KIND_FUNCTION:
return type->u.kfunction->return_type;
case DEBUG_KIND_METHOD:
return type->u.kmethod->return_type;
}
/*NOTREACHED*/
}
/* Get the parameter types of a function or method type (except that
we don't currently store the parameter types of a function). */
const debug_type *
debug_get_parameter_types (handle, type)
PTR handle;
debug_type type;
{
if (type == NULL)
return NULL;
type = debug_get_real_type (handle, type);
switch (type->kind)
{
default:
return NULL;
case DEBUG_KIND_METHOD:
return type->u.kmethod->arg_types;
}
/*NOTREACHED*/
}
/* Get the NULL terminated array of fields for a struct, union, or
class. */
const debug_field *
debug_get_fields (handle, type)
PTR handle;
debug_type type;
{
if (type == NULL)
return NULL;
type = debug_get_real_type (handle, type);
switch (type->kind)
{
default:
return NULL;
case DEBUG_KIND_STRUCT:
case DEBUG_KIND_UNION:
case DEBUG_KIND_CLASS:
case DEBUG_KIND_UNION_CLASS:
return type->u.kclass->fields;
}
/*NOTREACHED*/
}
/* Get the type of a field. */
/*ARGSUSED*/
debug_type
debug_get_field_type (handle, field)
PTR handle;
debug_field field;
{
if (field == NULL)
return NULL;
return field->type;
}
/* Write out the debugging information. This is given a handle to
debugging information, and a set of function pointers to call. */
@ -2096,6 +2302,11 @@ debug_write (handle, fns, fhandle)
information more than once. */
++info->mark;
/* The base_id field holds an ID value which will never be used, so
that we can tell whether we have assigned an ID during this call
to debug_write. */
info->base_id = info->class_id;
for (u = info->units; u != NULL; u = u->next)
{
struct debug_file *f;
@ -2225,7 +2436,7 @@ debug_write_type (info, fns, fhandle, type, name)
if (type->kind == DEBUG_KIND_NAMED)
return (*fns->typedef_type) (fhandle, type->u.knamed->name->name);
else
return (*fns->tag_type) (fhandle, type->u.knamed->name->name,
return (*fns->tag_type) (fhandle, type->u.knamed->name->name, 0,
type->u.knamed->type->kind);
}
@ -2247,6 +2458,9 @@ debug_write_type (info, fns, fhandle, type, name)
switch (type->kind)
{
case DEBUG_KIND_ILLEGAL:
debug_error ("debug_write_type: illegal type encountered");
return false;
case DEBUG_KIND_INDIRECT:
if (*type->u.kindirect->slot == DEBUG_TYPE_NULL)
return (*fns->empty_type) (fhandle);
@ -2266,17 +2480,25 @@ debug_write_type (info, fns, fhandle, type, name)
case DEBUG_KIND_UNION:
if (type->u.kclass != NULL)
{
if (info->class_mark == type->u.kclass->mark)
if (info->class_mark == type->u.kclass->mark
|| type->u.kclass->id > info->base_id)
{
/* We are currently outputting this struct. I don't
know if this can happen, but it can happen for a
class. */
return (*fns->tag_type) (fhandle, "?defining?", type->kind);
/* We are currently outputting this struct, or we have
already output it. I don't know if this can happen,
but it can happen for a class. */
assert (type->u.kclass->id > info->base_id);
return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
type->kind);
}
type->u.kclass->mark = info->class_mark;
++info->class_id;
type->u.kclass->id = info->class_id;
}
if (! (*fns->start_struct_type) (fhandle, tag,
(type->u.kclass != NULL
? type->u.kclass->id
: 0),
type->kind == DEBUG_KIND_STRUCT,
type->size))
return false;
@ -2361,10 +2583,18 @@ debug_write_type (info, fns, fhandle, type, name)
{
for (i = 0; type->u.kmethod->arg_types[i] != NULL; i++)
{
if (! debug_write_type (info, fns, fhandle,
type->u.kmethod->arg_types[i],
(struct debug_name *) NULL))
return false;
if (ELLIPSIS_P (type->u.kmethod->arg_types[i]))
{
if (! (*fns->ellipsis_type) (fhandle))
return false;
}
else
{
if (! debug_write_type (info, fns, fhandle,
type->u.kmethod->arg_types[i],
(struct debug_name *) NULL))
return false;
}
}
}
if (type->u.kmethod->domain_type != NULL)
@ -2410,32 +2640,45 @@ debug_write_class_type (info, fns, fhandle, type, tag)
const char *tag;
{
unsigned int i;
unsigned int id;
struct debug_type *vptrbase;
if (type->u.kclass != NULL)
if (type->u.kclass == NULL)
{
if (info->class_mark == type->u.kclass->mark)
id = 0;
vptrbase = NULL;
}
else
{
if (info->class_mark == type->u.kclass->mark
|| type->u.kclass->id > info->base_id)
{
/* We are currently outputting this class. This can happen
when there are methods for an anonymous class. */
return (*fns->tag_type) (fhandle, "?defining?", type->kind);
/* We are currently outputting this class, or we have
already output it. This can happen when there are
methods for an anonymous class. */
assert (type->u.kclass->id > info->base_id);
return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
type->kind);
}
type->u.kclass->mark = info->class_mark;
++info->class_id;
id = info->class_id;
type->u.kclass->id = id;
if (type->u.kclass->vptrbase != NULL
&& type->u.kclass->vptrbase != type)
vptrbase = type->u.kclass->vptrbase;
if (vptrbase != NULL && vptrbase != type)
{
if (! debug_write_type (info, fns, fhandle,
type->u.kclass->vptrbase,
if (! debug_write_type (info, fns, fhandle, vptrbase,
(struct debug_name *) NULL))
return false;
}
}
if (! (*fns->start_class_type) (fhandle, tag,
if (! (*fns->start_class_type) (fhandle, tag, id,
type->kind == DEBUG_KIND_CLASS,
type->size,
type->u.kclass->vptrbase != NULL,
type->u.kclass->vptrbase == type))
vptrbase != NULL,
vptrbase == type))
return false;
if (type->u.kclass != NULL)
@ -2508,7 +2751,7 @@ debug_write_class_type (info, fns, fhandle, type, tag)
return false;
if (v->voffset != VOFFSET_STATIC_METHOD)
{
if (! (*fns->class_method_variant) (fhandle, v->argtypes,
if (! (*fns->class_method_variant) (fhandle, v->physname,
v->visibility,
v->constp,
v->volatilep,
@ -2519,7 +2762,7 @@ debug_write_class_type (info, fns, fhandle, type, tag)
else
{
if (! (*fns->class_static_method_variant) (fhandle,
v->argtypes,
v->physname,
v->visibility,
v->constp,
v->volatilep))