Commit 36a5eadd by Geoffrey Keating Committed by Geoffrey Keating

Index: gcc/ChangeLog

2002-09-12  Geoffrey Keating  <geoffk@apple.com>

	* ggc-common.c (ggc_mark_rtx_children_1): Update for changed name
	mangling.

	The following changes are merged from pch-branch:

	* doc/gty.texi (GTY Options): Document %a.
	* gengtype.c (do_scalar_typedef): New function.
	(process_gc_options): Handle `length' option.
	(set_gc_used_type): A pointer to an array of structures doesn't
	qualify as a pointer to a structure.
	(output_escaped_param): Add `%a' escape.
	(write_gc_structure_fields): Allow 'desc' on array of unions.
	(main): Define `uint8', `jword' and `JCF_u2' as scalars; use
	do_scalar_typedef.

	* gengtype.c (enum rtx_code): Make global.
	(rtx_format): Make global.
	(rtx_next): New.
	(gen_rtx_next): New.
	(write_rtx_next): New.
	(adjust_field_rtx_def): Skip fields marked by chain_next.
	(open_base_files): Delete redundant prototype.
	(write_enum_defn): New.
	(output_mangled_typename): Correct abort call.
	(write_gc_marker_routine_for_structure): Handle chain_next and
	chain_prev options.
	(finish_root_table): Don't output redundant \n.
	(main): Call gen_rtx_next, write_rtx_next, write_enum_defn.
	* c-tree.h (union lang_tree_node): Add chain_next option.

	* gengtype.h (NUM_PARAM): New definition.
	(struct type): For TYPE_PARAM_STRUCT, allow multiple parameters.
	* gengtype.c (find_param_structure): New.
	(adjust_field_type): Handle param<n>_is option.
	(process_gc_options): Detect use_params option.  Update callers.
	(set_gc_used_type): Add 'param' parameter, update callers.  Handle
	'use_params' option.
	(open_base_files): Add splay-tree.h to list of files included.
	(output_mangled_typename): New.
	(write_gc_structure_fields): Update 'param' parameter to support
	multiple parameters.  Change name mangling.  Allow parameterized
	fields to have an apparent scalar type.  Handle param<n>_is options,
	use_param option.
	(write_gc_marker_routine_for_structure): Update for change to name
	mangling.  Better guess the output file for parameterized types.
	(write_gc_types): Update for change to name mangling.
	(write_gc_root): Update for change to name mangling.  Handle (ignore)
	param<n>_is options.
	* doc/gty.texi (GTY Options): Add description of param<n>_is
	options, use_params option.
	* ggc.h (ggc_mark_rtx): Update for changed name mangling.
	* gengtype-lex.l: Produce token for param<n>_is.
	* gengtype-yacc.y: Parse param<n>_is.

	* gengtype.c (adjust_field_tree_exp): Don't name a variable 'rindex'.

	* rtl.c: Update comment describing rtx_format.
	* rtl.h (union rtunion): Separate definition and typedef.
	(struct rtx_def): Use gengtype to mark.
	* Makefile.in (gengtype.o): Also depend on rtl.def.
	* ggc.h (ggc_mark_rtx_children): Delete prototype.
	(ggc_mark_rtx): Change to alias of gengtype-generated routine.
	* ggc-common.c (ggc_mark_rtx_children): Delete.
	(ggc_mark_rtx_children_1): Delete.
	(gt_ggc_m_rtx_def): Delete.
	* gengtype.c (adjust_field_rtx_def): New.
	(adjust_field_type): Call adjust_field_rtx_def.
	(write_gc_structure_fields): Add 'default' case to switch if none
	is specified; remove unused code.

	* tree.h (struct tree_exp): Update for change to meaning
	of special.
	* gengtype.c (adjust_field_tree_exp): New function.
	(adjust_field_type): Handle `tree_exp' special here.
	(write_gc_structure_fields): Don't handle `tree_exp' special here.
	Handle new `dot' option.

	* gengtype.h: Make `info' a pointer-to-const.
	* gengtype-yacc.y (yacc_ids): Use xasprintf.

	* gengtype.c (write_gc_structure_fields): Remove implementation
	of `always' option, add `default' option.
	* doc/gty.texi (GTY Options): Remove documentation of `always',
	add `default'.

Index: gcc/cp/ChangeLog
2002-09-12  Geoffrey Keating  <geoffk@apple.com>

	* cp-tree.h (union lang_tree_node): Add chain_next option.

Index: gcc/f/ChangeLog
2002-09-12  Geoffrey Keating  <geoffk@apple.com>

	* com.c (union lang_tree_node): Add chain_next option.

Index: gcc/java/ChangeLog
2002-09-12  Geoffrey Keating  <geoffk@apple.com>

	* java-tree.h (union lang_tree_node): Add chain_next option.

From-SVN: r57206
parent a7f6d760
2002-09-16 Geoffrey Keating <geoffk@apple.com>
* ggc-common.c (ggc_mark_rtx_children_1): Update for changed name
mangling.
The following changes are merged from pch-branch:
* doc/gty.texi (GTY Options): Document %a.
* gengtype.c (do_scalar_typedef): New function.
(process_gc_options): Handle `length' option.
(set_gc_used_type): A pointer to an array of structures doesn't
qualify as a pointer to a structure.
(output_escaped_param): Add `%a' escape.
(write_gc_structure_fields): Allow 'desc' on array of unions.
(main): Define `uint8', `jword' and `JCF_u2' as scalars; use
do_scalar_typedef.
* gengtype.c (enum rtx_code): Make global.
(rtx_format): Make global.
(rtx_next): New.
(gen_rtx_next): New.
(write_rtx_next): New.
(adjust_field_rtx_def): Skip fields marked by chain_next.
(open_base_files): Delete redundant prototype.
(write_enum_defn): New.
(output_mangled_typename): Correct abort call.
(write_gc_marker_routine_for_structure): Handle chain_next and
chain_prev options.
(finish_root_table): Don't output redundant \n.
(main): Call gen_rtx_next, write_rtx_next, write_enum_defn.
* c-tree.h (union lang_tree_node): Add chain_next option.
* gengtype.h (NUM_PARAM): New definition.
(struct type): For TYPE_PARAM_STRUCT, allow multiple parameters.
* gengtype.c (find_param_structure): New.
(adjust_field_type): Handle param<n>_is option.
(process_gc_options): Detect use_params option. Update callers.
(set_gc_used_type): Add 'param' parameter, update callers. Handle
'use_params' option.
(open_base_files): Add splay-tree.h to list of files included.
(output_mangled_typename): New.
(write_gc_structure_fields): Update 'param' parameter to support
multiple parameters. Change name mangling. Allow parameterized
fields to have an apparent scalar type. Handle param<n>_is options,
use_param option.
(write_gc_marker_routine_for_structure): Update for change to name
mangling. Better guess the output file for parameterized types.
(write_gc_types): Update for change to name mangling.
(write_gc_root): Update for change to name mangling. Handle (ignore)
param<n>_is options.
* doc/gty.texi (GTY Options): Add description of param<n>_is
options, use_params option.
* ggc.h (ggc_mark_rtx): Update for changed name mangling.
* gengtype-lex.l: Produce token for param<n>_is.
* gengtype-yacc.y: Parse param<n>_is.
* gengtype.c (adjust_field_tree_exp): Don't name a variable 'rindex'.
* rtl.c: Update comment describing rtx_format.
* rtl.h (union rtunion): Separate definition and typedef.
(struct rtx_def): Use gengtype to mark.
* Makefile.in (gengtype.o): Also depend on rtl.def.
* ggc.h (ggc_mark_rtx_children): Delete prototype.
(ggc_mark_rtx): Change to alias of gengtype-generated routine.
* ggc-common.c (ggc_mark_rtx_children): Delete.
(ggc_mark_rtx_children_1): Delete.
(gt_ggc_m_rtx_def): Delete.
* gengtype.c (adjust_field_rtx_def): New.
(adjust_field_type): Call adjust_field_rtx_def.
(write_gc_structure_fields): Add 'default' case to switch if none
is specified; remove unused code.
* tree.h (struct tree_exp): Update for change to meaning
of special.
* gengtype.c (adjust_field_tree_exp): New function.
(adjust_field_type): Handle `tree_exp' special here.
(write_gc_structure_fields): Don't handle `tree_exp' special here.
Handle new `dot' option.
* gengtype.h: Make `info' a pointer-to-const.
* gengtype-yacc.y (yacc_ids): Use xasprintf.
* gengtype.c (write_gc_structure_fields): Remove implementation
of `always' option, add `default' option.
* doc/gty.texi (GTY Options): Remove documentation of `always',
add `default'.
2002-09-16 Hans-Peter Nilsson <hp@bitrange.com> 2002-09-16 Hans-Peter Nilsson <hp@bitrange.com>
* output.h: Remove #ifdef RTX_CODE and #ifdef TREE_CODE. * output.h: Remove #ifdef RTX_CODE and #ifdef TREE_CODE.
......
...@@ -2053,7 +2053,8 @@ gengtype$(build_exeext) : gengtype.o gengtype-lex.o gengtype-yacc.o \ ...@@ -2053,7 +2053,8 @@ gengtype$(build_exeext) : gengtype.o gengtype-lex.o gengtype-yacc.o \
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
gengtype.o gengtype-lex.o gengtype-yacc.o $(HOST_LIBS) gengtype.o gengtype-lex.o gengtype-yacc.o $(HOST_LIBS)
gengtype.o : gengtype.c gengtype.h $(HCONFIG_H) $(SYSTEM_H) real.h gtyp-gen.h gengtype.o : gengtype.c gengtype.h $(HCONFIG_H) $(SYSTEM_H) real.h rtl.def \
gtyp-gen.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
$(srcdir)/gengtype.c $(OUTPUT_OPTION) $(srcdir)/gengtype.c $(OUTPUT_OPTION)
......
...@@ -48,7 +48,8 @@ struct lang_identifier GTY(()) ...@@ -48,7 +48,8 @@ struct lang_identifier GTY(())
/* The resulting tree type. */ /* The resulting tree type. */
union lang_tree_node union lang_tree_node
GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"))) GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
{ {
union tree_node GTY ((tag ("0"), union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)"))) desc ("tree_node_structure (&%h)")))
......
2002-09-16 Geoffrey Keating <geoffk@apple.com>
* cp-tree.h (union lang_tree_node): Add chain_next option.
2002-09-16 Nathan Sidwell <nathan@codesourcery.com> 2002-09-16 Nathan Sidwell <nathan@codesourcery.com>
* parse.y (parse_finish_call_expr): Check lookup_member result. * parse.y (parse_finish_call_expr): Check lookup_member result.
......
...@@ -505,7 +505,8 @@ enum cp_tree_node_structure_enum { ...@@ -505,7 +505,8 @@ enum cp_tree_node_structure_enum {
}; };
/* The resulting tree type. */ /* The resulting tree type. */
union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"))) union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"),
chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
{ {
struct tree_common GTY ((tag ("TS_CP_COMMON"))) common; struct tree_common GTY ((tag ("TS_CP_COMMON"))) common;
union tree_node GTY ((tag ("TS_CP_GENERIC"), union tree_node GTY ((tag ("TS_CP_GENERIC"),
......
...@@ -72,6 +72,10 @@ immediately contains the current structure. ...@@ -72,6 +72,10 @@ immediately contains the current structure.
@item %0 @item %0
This expands to an expression that evaluates to the outermost structure This expands to an expression that evaluates to the outermost structure
that contains the current structure. that contains the current structure.
@item %a
This expands to the string of the form @code{[i1][i2]...} that indexes
the array item currently being marked. For instance, if the field
being marked is @code{foo}, then @code{%1.foo%a} is the same as @code{%h}.
@end table @end table
The available options are: The available options are:
...@@ -121,10 +125,10 @@ field really isn't ever used. ...@@ -121,10 +125,10 @@ field really isn't ever used.
@findex desc @findex desc
@findex tag @findex tag
@findex always @findex default
@item desc @item desc
@itemx tag @itemx tag
@itemx always @itemx default
The type machinery needs to be told which field of a @code{union} is The type machinery needs to be told which field of a @code{union} is
currently active. This is done by giving each field a constant @code{tag} currently active. This is done by giving each field a constant @code{tag}
...@@ -146,7 +150,9 @@ it discriminates. Use @code{%1} to mean the structure containing it. ...@@ -146,7 +150,9 @@ it discriminates. Use @code{%1} to mean the structure containing it.
(There are no escapes available to the @code{tag} option, since it's (There are no escapes available to the @code{tag} option, since it's
supposed to be a constant.) supposed to be a constant.)
You can use @code{always} to mean that this field is always used. Each @code{tag} should be different. If no @code{tag} is matched,
the field marked with @code{default} is used if there is one, otherwise
no field in the union will be marked.
@findex param_is @findex param_is
@findex use_param @findex use_param
...@@ -154,15 +160,39 @@ You can use @code{always} to mean that this field is always used. ...@@ -154,15 +160,39 @@ You can use @code{always} to mean that this field is always used.
@itemx use_param @itemx use_param
Sometimes it's convenient to define some data structure to work on Sometimes it's convenient to define some data structure to work on
generic pointers (that is, @code{PTR}), and then use it with specific types. generic pointers (that is, @code{PTR}) and then use it with a specific
@code{param_is} specifies the real type pointed to, and @code{use_param} type. @code{param_is} specifies the real type pointed to, and
says where in the generic data structure that type should be put. @code{use_param} says where in the generic data structure that type
should be put.
For instance, to have a @code{htab_t} that points to trees, one should write For instance, to have a @code{htab_t} that points to trees, one should write
@verbatim @verbatim
htab_t GTY ((param_is (union tree_node))) ict; htab_t GTY ((param_is (union tree_node))) ict;
@end verbatim @end verbatim
@findex param@var{n}_is
@findex use_param@var{n}
@item param@var{n}_is
@itemx use_param@var{n}
In more complicated cases, the data structure might need to work on
several different types, which might not necessarily all be pointers.
For this, @code{param1_is} through @code{param9_is} may be used to
specify the real type of a field identified by @code{use_param1} through
@code{use_param9}.
@findex use_params
@item use_params
When a structure contains another structure that is parameterised,
there's no need to do anything special, the inner stucture inherits the
parameters of the outer one. When a structure contains a pointer to a
parameterised structure, the type machinery won't automatically detect
this (it could, it just doesn't yet), so it's necessary to tell it that
the pointed-to structure should use the same parameters as the outer
structure. This is done by marking the pointer with the
@code{use_params} option.
@findex deletable @findex deletable
@item deletable @item deletable
......
2002-09-16 Geoffrey Keating <geoffk@apple.com>
* com.c (union lang_tree_node): Add chain_next option.
2002-09-16 Richard Henderson <rth@redhat.com> 2002-09-16 Richard Henderson <rth@redhat.com>
* target.c (ffetarget_real1): Don't pass FFETARGET_ATOF_ * target.c (ffetarget_real1): Don't pass FFETARGET_ATOF_
......
...@@ -605,7 +605,8 @@ struct lang_identifier GTY(()) ...@@ -605,7 +605,8 @@ struct lang_identifier GTY(())
/* The resulting tree type. */ /* The resulting tree type. */
union lang_tree_node union lang_tree_node
GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"))) GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
{ {
union tree_node GTY ((tag ("0"), union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)"))) desc ("tree_node_structure (&%h)")))
......
...@@ -203,8 +203,11 @@ ITYPE {IWORD}({WS}{IWORD})* ...@@ -203,8 +203,11 @@ ITYPE {IWORD}({WS}{IWORD})*
"struct"/[^[:alnum:]_] { return STRUCT; } "struct"/[^[:alnum:]_] { return STRUCT; }
"enum"/[^[:alnum:]_] { return ENUM; } "enum"/[^[:alnum:]_] { return ENUM; }
"ptr_alias"/[^[:alnum:]_] { return ALIAS; } "ptr_alias"/[^[:alnum:]_] { return ALIAS; }
"param_is"/[^[:alnum:]_] { return PARAM_IS; }
[0-9]+ { return NUM; } [0-9]+ { return NUM; }
"param"[0-9]*"_is"/[^[:alnum:]_] {
yylval.s = xmemdup (yytext, yyleng, yyleng+1);
return PARAM_IS;
}
{IWORD}({WS}{IWORD})*/[^[:alnum:]_] | {IWORD}({WS}{IWORD})*/[^[:alnum:]_] |
"ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")" { "ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")" {
......
...@@ -42,7 +42,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -42,7 +42,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
%token STRUCT "struct" %token STRUCT "struct"
%token ENUM "enum" %token ENUM "enum"
%token ALIAS "ptr_alias" %token ALIAS "ptr_alias"
%token PARAM_IS "param_is" %token <s>PARAM_IS
%token NUM %token NUM
%token PERCENTPERCENT "%%" %token PERCENTPERCENT "%%"
%token <t>SCALAR %token <t>SCALAR
...@@ -174,8 +174,7 @@ yacc_ids: /* empty */ ...@@ -174,8 +174,7 @@ yacc_ids: /* empty */
p->opt = xmalloc (sizeof (*(p->opt))); p->opt = xmalloc (sizeof (*(p->opt)));
p->opt->name = "tag"; p->opt->name = "tag";
p->opt->next = NULL; p->opt->next = NULL;
p->opt->info = xmalloc (3 + strlen ($2)); p->opt->info = xasprintf ("'%s'", $2);
sprintf (p->opt->info, "'%s'", $2);
$$ = p; $$ = p;
} }
; ;
...@@ -263,14 +262,14 @@ options: GTY_TOKEN '(' '(' optionseqopt ')' ')' ...@@ -263,14 +262,14 @@ options: GTY_TOKEN '(' '(' optionseqopt ')' ')'
type_option : ALIAS type_option : ALIAS
{ $$ = "ptr_alias"; } { $$ = "ptr_alias"; }
| PARAM_IS | PARAM_IS
{ $$ = "param_is"; } { $$ = $1; }
; ;
option: type_option '(' type ')' option: type_option '(' type ')'
{ {
options_p o = xmalloc (sizeof (*o)); options_p o = xmalloc (sizeof (*o));
o->name = $1; o->name = $1;
o->info = $3; o->info = adjust_field_type ($3, NULL);
$$ = o; $$ = o;
} }
| ID '(' STRING ')' | ID '(' STRING ')'
......
...@@ -26,10 +26,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -26,10 +26,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Nonzero iff an error has occurred. */ /* Nonzero iff an error has occurred. */
static int hit_error = 0; static int hit_error = 0;
static void gen_rtx_next PARAMS ((void));
static void write_rtx_next PARAMS ((void));
static void open_base_files PARAMS ((void)); static void open_base_files PARAMS ((void));
static void close_output_files PARAMS ((void)); static void close_output_files PARAMS ((void));
/* Report an error at POS, printing MSG. */ /* Report an error at POS, printing MSG. */
void void
...@@ -89,6 +90,12 @@ static type_p structures; ...@@ -89,6 +90,12 @@ static type_p structures;
static type_p param_structs; static type_p param_structs;
static pair_p variables; static pair_p variables;
static void do_scalar_typedef PARAMS ((const char *, struct fileloc *));
static type_p find_param_structure
PARAMS ((type_p t, type_p param[NUM_PARAM]));
static type_p adjust_field_tree_exp PARAMS ((type_p t, options_p opt));
static type_p adjust_field_rtx_def PARAMS ((type_p t, options_p opt));
/* Define S as a typedef to T at POS. */ /* Define S as a typedef to T at POS. */
void void
...@@ -118,6 +125,16 @@ do_typedef (s, t, pos) ...@@ -118,6 +125,16 @@ do_typedef (s, t, pos)
typedefs = p; typedefs = p;
} }
/* Define S as a typename of a scalar. */
static void
do_scalar_typedef (s, pos)
const char *s;
struct fileloc *pos;
{
do_typedef (s, create_scalar_type (s, strlen (s)), pos);
}
/* Return the type previously defined for S. Use POS to report errors. */ /* Return the type previously defined for S. Use POS to report errors. */
type_p type_p
...@@ -235,6 +252,34 @@ find_structure (name, isunion) ...@@ -235,6 +252,34 @@ find_structure (name, isunion)
return s; return s;
} }
/* Return the previously-defined parameterised structure for structure
T and parameters PARAM, or a new parameterised empty structure or
union if none was defined previously. */
static type_p
find_param_structure (t, param)
type_p t;
type_p param[NUM_PARAM];
{
type_p res;
for (res = param_structs; res; res = res->next)
if (res->u.param_struct.stru == t
&& memcmp (res->u.param_struct.param, param,
sizeof (type_p) * NUM_PARAM) == 0)
break;
if (res == NULL)
{
res = xcalloc (1, sizeof (*res));
res->kind = TYPE_PARAM_STRUCT;
res->next = param_structs;
param_structs = res;
res->u.param_struct.stru = t;
memcpy (res->u.param_struct.param, param, sizeof (type_p) * NUM_PARAM);
}
return res;
}
/* Return a scalar type with name NAME. */ /* Return a scalar type with name NAME. */
type_p type_p
...@@ -280,13 +325,420 @@ create_array (t, len) ...@@ -280,13 +325,420 @@ create_array (t, len)
return v; return v;
} }
/* Add a variable named S of type T with options O defined at POS,
to `variables'. */
void
note_variable (s, t, o, pos)
const char *s;
type_p t;
options_p o;
struct fileloc *pos;
{
pair_p n;
n = xmalloc (sizeof (*n));
n->name = s;
n->type = t;
n->line = *pos;
n->opt = o;
n->next = variables;
variables = n;
}
enum rtx_code {
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) ENUM ,
#include "rtl.def"
#undef DEF_RTL_EXPR
NUM_RTX_CODE
};
/* We really don't care how long a CONST_DOUBLE is. */
#define CONST_DOUBLE_FORMAT "ww"
static const char * const rtx_format[NUM_RTX_CODE] = {
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
#include "rtl.def"
#undef DEF_RTL_EXPR
};
static char rtx_next[NUM_RTX_CODE];
/* Generate the contents of the rtx_next array. This really doesn't belong
in gengtype at all, but it's needed for adjust_field_rtx_def. */
static void
gen_rtx_next ()
{
int i;
for (i = 0; i < NUM_RTX_CODE; i++)
{
int k;
rtx_next[i] = -1;
if (strncmp (rtx_format[i], "iuu", 3) == 0)
rtx_next[i] = 2;
else if (i == COND_EXEC || i == SET || i == EXPR_LIST || i == INSN_LIST)
rtx_next[i] = 1;
else
for (k = strlen (rtx_format[i]) - 1; k >= 0; k--)
if (rtx_format[i][k] == 'e' || rtx_format[i][k] == 'u')
rtx_next[i] = k;
}
}
/* Write out the contents of the rtx_next array. */
static void
write_rtx_next ()
{
outf_p f = get_output_file_with_visibility (NULL);
int i;
oprintf (f, "\n/* Used to implement the RTX_NEXT macro. */\n");
oprintf (f, "const unsigned char rtx_next[NUM_RTX_CODE] = {\n");
for (i = 0; i < NUM_RTX_CODE; i++)
if (rtx_next[i] == -1)
oprintf (f, " 0,\n");
else
oprintf (f,
" offsetof (struct rtx_def, fld) + %d * sizeof (rtunion),\n",
rtx_next[i]);
oprintf (f, "};\n");
}
/* Handle `special("rtx_def")'. This is a special case for field
`fld' of struct rtx_def, which is an array of unions whose values
are based in a complex way on the type of RTL. */
static type_p
adjust_field_rtx_def (t, opt)
type_p t;
options_p opt ATTRIBUTE_UNUSED;
{
pair_p flds = NULL;
options_p nodot;
int i;
type_p rtx_tp, rtvec_tp, tree_tp, mem_attrs_tp, note_union_tp, scalar_tp;
type_p bitmap_tp, basic_block_tp;
static const char * const rtx_name[NUM_RTX_CODE] = {
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) NAME ,
#include "rtl.def"
#undef DEF_RTL_EXPR
};
if (t->kind != TYPE_ARRAY)
{
error_at_line (&lexer_line,
"special `rtx_def' must be applied to an array");
return &string_type;
}
nodot = xmalloc (sizeof (*nodot));
nodot->next = NULL;
nodot->name = "dot";
nodot->info = "";
rtx_tp = create_pointer (find_structure ("rtx_def", 0));
rtvec_tp = create_pointer (find_structure ("rtvec_def", 0));
tree_tp = create_pointer (find_structure ("tree_node", 1));
mem_attrs_tp = create_pointer (find_structure ("mem_attrs", 0));
bitmap_tp = create_pointer (find_structure ("bitmap_element_def", 0));
basic_block_tp = create_pointer (find_structure ("basic_block_def", 0));
scalar_tp = create_scalar_type ("rtunion scalar", 14);
{
pair_p note_flds = NULL;
int c;
for (c = 0; c < 3; c++)
{
pair_p old_note_flds = note_flds;
note_flds = xmalloc (sizeof (*note_flds));
note_flds->line.file = __FILE__;
note_flds->line.line = __LINE__;
note_flds->name = "rttree";
note_flds->type = tree_tp;
note_flds->opt = xmalloc (sizeof (*note_flds->opt));
note_flds->opt->next = nodot;
note_flds->opt->name = "tag";
note_flds->next = old_note_flds;
}
note_flds->type = rtx_tp;
note_flds->name = "rtx";
note_flds->opt->info = "NOTE_INSN_EXPECTED_VALUE";
note_flds->next->opt->info = "NOTE_INSN_BLOCK_BEG";
note_flds->next->next->opt->info = "NOTE_INSN_BLOCK_END";
new_structure ("rtx_def_note_subunion", 1, &lexer_line, note_flds, NULL);
}
note_union_tp = find_structure ("rtx_def_note_subunion", 1);
for (i = 0; i < NUM_RTX_CODE; i++)
{
pair_p old_flds = flds;
pair_p subfields = NULL;
size_t aindex, nmindex;
const char *sname;
char *ftag;
for (aindex = 0; aindex < strlen (rtx_format[i]); aindex++)
{
pair_p old_subf = subfields;
type_p t;
const char *subname;
switch (rtx_format[i][aindex])
{
case '*':
case 'i':
case 'n':
case 'w':
t = scalar_tp;
subname = "rtint";
break;
case '0':
if (i == MEM && aindex == 1)
t = mem_attrs_tp, subname = "rtmem";
else if (i == JUMP_INSN && aindex == 9)
t = rtx_tp, subname = "rtx";
else if (i == CODE_LABEL && aindex == 4)
t = scalar_tp, subname = "rtint";
else if (i == CODE_LABEL && aindex == 5)
t = rtx_tp, subname = "rtx";
else if (i == LABEL_REF
&& (aindex == 1 || aindex == 2))
t = rtx_tp, subname = "rtx";
else if (i == NOTE && aindex == 4)
t = note_union_tp, subname = "";
else if (i == NOTE && aindex >= 7)
t = scalar_tp, subname = "rtint";
else if (i == ADDR_DIFF_VEC && aindex == 4)
t = scalar_tp, subname = "rtint";
else if (i == VALUE && aindex == 0)
t = scalar_tp, subname = "rtint";
else if (i == REG && aindex == 1)
t = scalar_tp, subname = "rtint";
else if (i == SCRATCH && aindex == 0)
t = scalar_tp, subname = "rtint";
else if (i == BARRIER && aindex >= 3)
t = scalar_tp, subname = "rtint";
else
{
error_at_line (&lexer_line,
"rtx type `%s' has `0' in position %d, can't handle",
rtx_name[i], aindex);
t = &string_type;
subname = "rtint";
}
break;
case 's':
case 'S':
case 'T':
t = &string_type;
subname = "rtstr";
break;
case 'e':
case 'u':
t = rtx_tp;
subname = "rtx";
break;
case 'E':
case 'V':
t = rtvec_tp;
subname = "rtvec";
break;
case 't':
t = tree_tp;
subname = "rttree";
break;
case 'b':
t = bitmap_tp;
subname = "rtbit";
break;
case 'B':
t = basic_block_tp;
subname = "bb";
break;
default:
error_at_line (&lexer_line,
"rtx type `%s' has `%c' in position %d, can't handle",
rtx_name[i], rtx_format[i][aindex],
aindex);
t = &string_type;
subname = "rtint";
break;
}
subfields = xmalloc (sizeof (*subfields));
subfields->next = old_subf;
subfields->type = t;
subfields->name = xasprintf ("[%d].%s", aindex, subname);
subfields->line.file = __FILE__;
subfields->line.line = __LINE__;
if (t == note_union_tp)
{
subfields->opt = xmalloc (sizeof (*subfields->opt));
subfields->opt->next = nodot;
subfields->opt->name = "desc";
subfields->opt->info = "NOTE_LINE_NUMBER (&%0)";
}
else if (t == basic_block_tp)
{
/* We don't presently GC basic block structures... */
subfields->opt = xmalloc (sizeof (*subfields->opt));
subfields->opt->next = nodot;
subfields->opt->name = "skip";
subfields->opt->info = NULL;
}
else if ((size_t) rtx_next[i] == aindex)
{
/* The 'next' field will be marked by the chain_next option. */
subfields->opt = xmalloc (sizeof (*subfields->opt));
subfields->opt->next = nodot;
subfields->opt->name = "skip";
subfields->opt->info = NULL;
}
else
subfields->opt = nodot;
}
flds = xmalloc (sizeof (*flds));
flds->next = old_flds;
flds->name = "";
sname = xasprintf ("rtx_def_%s", rtx_name[i]);
new_structure (sname, 0, &lexer_line, subfields, NULL);
flds->type = find_structure (sname, 0);
flds->line.file = __FILE__;
flds->line.line = __LINE__;
flds->opt = xmalloc (sizeof (*flds->opt));
flds->opt->next = nodot;
flds->opt->name = "tag";
ftag = xstrdup (rtx_name[i]);
for (nmindex = 0; nmindex < strlen (ftag); nmindex++)
ftag[nmindex] = TOUPPER (ftag[nmindex]);
flds->opt->info = ftag;
}
new_structure ("rtx_def_subunion", 1, &lexer_line, flds, nodot);
return find_structure ("rtx_def_subunion", 1);
}
/* Handle `special("tree_exp")'. This is a special case for
field `operands' of struct tree_exp, which although it claims to contain
pointers to trees, actually sometimes contains pointers to RTL too.
Passed T, the old type of the field, and OPT its options. Returns
a new type for the field. */
static type_p
adjust_field_tree_exp (t, opt)
type_p t;
options_p opt ATTRIBUTE_UNUSED;
{
pair_p flds;
options_p nodot;
size_t i;
static const struct {
const char *name;
int first_rtl;
int num_rtl;
} data[] = {
{ "SAVE_EXPR", 2, 1 },
{ "GOTO_SUBROUTINE_EXPR", 0, 2 },
{ "RTL_EXPR", 0, 2 },
{ "WITH_CLEANUP_EXPR", 2, 1 },
{ "METHOD_CALL_EXPR", 3, 1 }
};
if (t->kind != TYPE_ARRAY)
{
error_at_line (&lexer_line,
"special `tree_exp' must be applied to an array");
return &string_type;
}
nodot = xmalloc (sizeof (*nodot));
nodot->next = NULL;
nodot->name = "dot";
nodot->info = "";
flds = xmalloc (sizeof (*flds));
flds->next = NULL;
flds->name = "";
flds->type = t;
flds->line.file = __FILE__;
flds->line.line = __LINE__;
flds->opt = xmalloc (sizeof (*flds->opt));
flds->opt->next = nodot;
flds->opt->name = "length";
flds->opt->info = "TREE_CODE_LENGTH (TREE_CODE ((tree) &%0))";
{
options_p oldopt = flds->opt;
flds->opt = xmalloc (sizeof (*flds->opt));
flds->opt->next = oldopt;
flds->opt->name = "default";
flds->opt->info = "";
}
for (i = 0; i < ARRAY_SIZE (data); i++)
{
pair_p old_flds = flds;
pair_p subfields = NULL;
int r_index;
const char *sname;
for (r_index = 0;
r_index < data[i].first_rtl + data[i].num_rtl;
r_index++)
{
pair_p old_subf = subfields;
subfields = xmalloc (sizeof (*subfields));
subfields->next = old_subf;
subfields->name = xasprintf ("[%d]", r_index);
if (r_index < data[i].first_rtl)
subfields->type = t->u.a.p;
else
subfields->type = create_pointer (find_structure ("rtx_def", 0));
subfields->line.file = __FILE__;
subfields->line.line = __LINE__;
subfields->opt = nodot;
}
flds = xmalloc (sizeof (*flds));
flds->next = old_flds;
flds->name = "";
sname = xasprintf ("tree_exp_%s", data[i].name);
new_structure (sname, 0, &lexer_line, subfields, NULL);
flds->type = find_structure (sname, 0);
flds->line.file = __FILE__;
flds->line.line = __LINE__;
flds->opt = xmalloc (sizeof (*flds->opt));
flds->opt->next = nodot;
flds->opt->name = "tag";
flds->opt->info = data[i].name;
}
new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot);
return find_structure ("tree_exp_subunion", 1);
}
/* Perform any special processing on a type T, about to become the type /* Perform any special processing on a type T, about to become the type
of a field. Return the appropriate type for the field. of a field. Return the appropriate type for the field.
At present: At present:
- Converts pointer-to-char, with no length parameter, to TYPE_STRING; - Converts pointer-to-char, with no length parameter, to TYPE_STRING;
- Similarly for arrays of pointer-to-char; - Similarly for arrays of pointer-to-char;
- Converts structures for which a parameter is provided to - Converts structures for which a parameter is provided to
TYPE_PARAM_STRUCT. TYPE_PARAM_STRUCT;
- Handles "special" options.
*/ */
type_p type_p
...@@ -296,30 +748,61 @@ adjust_field_type (t, opt) ...@@ -296,30 +748,61 @@ adjust_field_type (t, opt)
{ {
int length_p = 0; int length_p = 0;
const int pointer_p = t->kind == TYPE_POINTER; const int pointer_p = t->kind == TYPE_POINTER;
type_p params[NUM_PARAM];
int params_p = 0;
int i;
for (i = 0; i < NUM_PARAM; i++)
params[i] = NULL;
for (; opt; opt = opt->next) for (; opt; opt = opt->next)
if (strcmp (opt->name, "length") == 0) if (strcmp (opt->name, "length") == 0)
length_p = 1; length_p = 1;
else if (strcmp (opt->name, "param_is") == 0) else if (strcmp (opt->name, "param_is") == 0
|| (strncmp (opt->name, "param", 5) == 0
&& ISDIGIT (opt->name[5])
&& strcmp (opt->name + 6, "_is") == 0))
{ {
type_p realt; int num = ISDIGIT (opt->name[5]) ? opt->name[5] - '0' : 0;
if (pointer_p) if (! UNION_OR_STRUCT_P (t)
t = t->u.p; && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
{
for (realt = param_structs; realt; realt = realt->next) error_at_line (&lexer_line,
if (realt->u.param_struct.stru == t "option `%s' may only be applied to structures or structure pointers",
&& realt->u.param_struct.param == (type_p) opt->info) opt->name);
return pointer_p ? create_pointer (realt) : realt; return t;
realt = xcalloc (1, sizeof (*realt)); }
realt->kind = TYPE_PARAM_STRUCT;
realt->next = param_structs; params_p = 1;
param_structs = realt; if (params[num] != NULL)
realt->u.param_struct.stru = t; error_at_line (&lexer_line, "duplicate `%s' option", opt->name);
realt->u.param_struct.param = (type_p) opt->info; if (! ISDIGIT (opt->name[5]))
return pointer_p ? create_pointer (realt) : realt; params[num] = create_pointer ((type_p) opt->info);
else
params[num] = (type_p) opt->info;
} }
else if (strcmp (opt->name, "special") == 0)
{
const char *special_name = (const char *)opt->info;
if (strcmp (special_name, "tree_exp") == 0)
t = adjust_field_tree_exp (t, opt);
else if (strcmp (special_name, "rtx_def") == 0)
t = adjust_field_rtx_def (t, opt);
else
error_at_line (&lexer_line, "unknown special `%s'", special_name);
}
if (params_p)
{
type_p realt;
if (pointer_p)
t = t->u.p;
realt = find_param_structure (t, params);
t = pointer_p ? create_pointer (realt) : realt;
}
if (! length_p if (! length_p
&& pointer_p && pointer_p
&& t->u.p->kind == TYPE_SCALAR && t->u.p->kind == TYPE_SCALAR
...@@ -335,26 +818,6 @@ adjust_field_type (t, opt) ...@@ -335,26 +818,6 @@ adjust_field_type (t, opt)
return t; return t;
} }
/* Add a variable named S of type T with options O defined at POS,
to `variables'. */
void
note_variable (s, t, o, pos)
const char *s;
type_p t;
options_p o;
struct fileloc *pos;
{
pair_p n;
n = xmalloc (sizeof (*n));
n->name = s;
n->type = t;
n->line = *pos;
n->opt = o;
n->next = variables;
variables = n;
}
/* Create a union for YYSTYPE, as yacc would do it, given a fieldlist FIELDS /* Create a union for YYSTYPE, as yacc would do it, given a fieldlist FIELDS
and information about the correspondance between token types and fields and information about the correspondance between token types and fields
in TYPEINFO. POS is used for error messages. */ in TYPEINFO. POS is used for error messages. */
...@@ -419,36 +882,44 @@ note_yacc_type (o, fields, typeinfo, pos) ...@@ -419,36 +882,44 @@ note_yacc_type (o, fields, typeinfo, pos)
do_typedef ("YYSTYPE", find_structure ("yy_union", 1), pos); do_typedef ("YYSTYPE", find_structure ("yy_union", 1), pos);
} }
static void process_gc_options PARAMS ((options_p, enum gc_used_enum, int *)); static void process_gc_options PARAMS ((options_p, enum gc_used_enum,
static void set_gc_used_type PARAMS ((type_p, enum gc_used_enum)); int *, int *, int *));
static void set_gc_used_type PARAMS ((type_p, enum gc_used_enum, type_p *));
static void set_gc_used PARAMS ((pair_p)); static void set_gc_used PARAMS ((pair_p));
/* Handle OPT for set_gc_used_type. */ /* Handle OPT for set_gc_used_type. */
static void static void
process_gc_options (opt, level, maybe_undef) process_gc_options (opt, level, maybe_undef, pass_param, length)
options_p opt; options_p opt;
enum gc_used_enum level; enum gc_used_enum level;
int *maybe_undef; int *maybe_undef;
int *pass_param;
int *length;
{ {
options_p o; options_p o;
for (o = opt; o; o = o->next) for (o = opt; o; o = o->next)
if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO) if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO)
set_gc_used_type ((type_p) o->info, GC_POINTED_TO); set_gc_used_type ((type_p) o->info, GC_POINTED_TO, NULL);
else if (strcmp (o->name, "maybe_undef") == 0) else if (strcmp (o->name, "maybe_undef") == 0)
*maybe_undef = 1; *maybe_undef = 1;
else if (strcmp (o->name, "use_params") == 0)
*pass_param = 1;
else if (strcmp (o->name, "length") == 0)
*length = 1;
} }
/* Set the gc_used field of T to LEVEL, and handle the types it references. */ /* Set the gc_used field of T to LEVEL, and handle the types it references. */
static void static void
set_gc_used_type (t, level) set_gc_used_type (t, level, param)
type_p t; type_p t;
enum gc_used_enum level; enum gc_used_enum level;
type_p param[NUM_PARAM];
{ {
if (t->gc_used >= level) if (t->gc_used >= level)
return; return;
t->gc_used = level; t->gc_used = level;
switch (t->kind) switch (t->kind)
...@@ -459,37 +930,56 @@ set_gc_used_type (t, level) ...@@ -459,37 +930,56 @@ set_gc_used_type (t, level)
pair_p f; pair_p f;
int dummy; int dummy;
process_gc_options (t->u.s.opt, level, &dummy); process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy);
for (f = t->u.s.fields; f; f = f->next) for (f = t->u.s.fields; f; f = f->next)
{ {
int maybe_undef = 0; int maybe_undef = 0;
process_gc_options (t->u.s.opt, level, &maybe_undef); int pass_param = 0;
int length = 0;
process_gc_options (f->opt, level, &maybe_undef, &pass_param,
&length);
if (maybe_undef && f->type->kind == TYPE_POINTER) if (length && f->type->kind == TYPE_POINTER)
set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO); set_gc_used_type (f->type->u.p, GC_USED, NULL);
else if (maybe_undef && f->type->kind == TYPE_POINTER)
set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO, NULL);
else if (pass_param && f->type->kind == TYPE_POINTER && param)
set_gc_used_type (find_param_structure (f->type->u.p, param),
GC_POINTED_TO, NULL);
else else
set_gc_used_type (f->type, GC_USED); set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL);
} }
break; break;
} }
case TYPE_POINTER: case TYPE_POINTER:
set_gc_used_type (t->u.p, GC_POINTED_TO); set_gc_used_type (t->u.p, GC_POINTED_TO, NULL);
break; break;
case TYPE_ARRAY: case TYPE_ARRAY:
set_gc_used_type (t->u.a.p, GC_USED); set_gc_used_type (t->u.a.p, GC_USED, param);
break; break;
case TYPE_LANG_STRUCT: case TYPE_LANG_STRUCT:
for (t = t->u.s.lang_struct; t; t = t->next) for (t = t->u.s.lang_struct; t; t = t->next)
set_gc_used_type (t, level); set_gc_used_type (t, level, param);
break; break;
case TYPE_PARAM_STRUCT: case TYPE_PARAM_STRUCT:
set_gc_used_type (t->u.param_struct.param, GC_POINTED_TO); {
set_gc_used_type (t->u.param_struct.stru, GC_USED); int i;
for (i = 0; i < NUM_PARAM; i++)
if (t->u.param_struct.param[i] != 0)
set_gc_used_type (t->u.param_struct.param[i], GC_USED, NULL);
}
if (t->u.param_struct.stru->gc_used == GC_POINTED_TO)
level = GC_POINTED_TO;
else
level = GC_USED;
t->u.param_struct.stru->gc_used = GC_UNUSED;
set_gc_used_type (t->u.param_struct.stru, level,
t->u.param_struct.param);
break; break;
default: default:
...@@ -497,7 +987,7 @@ set_gc_used_type (t, level) ...@@ -497,7 +987,7 @@ set_gc_used_type (t, level)
} }
} }
/* Set the gc_used fileds of all the types pointed to by VARIABLES. */ /* Set the gc_used fields of all the types pointed to by VARIABLES. */
static void static void
set_gc_used (variables) set_gc_used (variables)
...@@ -505,7 +995,7 @@ set_gc_used (variables) ...@@ -505,7 +995,7 @@ set_gc_used (variables)
{ {
pair_p p; pair_p p;
for (p = variables; p; p = p->next) for (p = variables; p; p = p->next)
set_gc_used_type (p->type, GC_USED); set_gc_used_type (p->type, GC_USED, NULL);
} }
/* File mapping routines. For each input file, there is one output .c file /* File mapping routines. For each input file, there is one output .c file
...@@ -609,8 +1099,6 @@ oprintf VPARAMS ((outf_p o, const char *format, ...)) ...@@ -609,8 +1099,6 @@ oprintf VPARAMS ((outf_p o, const char *format, ...))
/* Open the global header file and the language-specific header files. */ /* Open the global header file and the language-specific header files. */
static void open_base_files PARAMS((void));
static void static void
open_base_files () open_base_files ()
{ {
...@@ -626,7 +1114,7 @@ open_base_files () ...@@ -626,7 +1114,7 @@ open_base_files ()
{ {
/* The order of files here matters very much. */ /* The order of files here matters very much. */
static const char *const ifiles [] = { static const char *const ifiles [] = {
"config.h", "system.h", "varray.h", "hashtab.h", "config.h", "system.h", "varray.h", "hashtab.h", "splay-tree.h",
"bitmap.h", "tree.h", "rtl.h", "function.h", "insn-config.h", "bitmap.h", "tree.h", "rtl.h", "function.h", "insn-config.h",
"expr.h", "hard-reg-set.h", "basic-block.h", "cselib.h", "expr.h", "hard-reg-set.h", "basic-block.h", "cselib.h",
"insn-addr.h", "ssa.h", "optabs.h", "libfuncs.h", "insn-addr.h", "ssa.h", "optabs.h", "libfuncs.h",
...@@ -878,11 +1366,14 @@ struct flist { ...@@ -878,11 +1366,14 @@ struct flist {
static void output_escaped_param PARAMS ((outf_p , const char *, const char *, static void output_escaped_param PARAMS ((outf_p , const char *, const char *,
const char *, const char *, const char *, const char *,
struct fileloc *)); struct fileloc *));
static void output_mangled_typename PARAMS ((outf_p, type_p));
static void write_gc_structure_fields static void write_gc_structure_fields
PARAMS ((outf_p , type_p, const char *, const char *, options_p, PARAMS ((outf_p , type_p, const char *, const char *, options_p,
int, struct fileloc *, lang_bitmap, type_p)); int, struct fileloc *, lang_bitmap, type_p *));
static void write_gc_marker_routine_for_structure PARAMS ((type_p, type_p)); static void write_gc_marker_routine_for_structure PARAMS ((type_p, type_p,
type_p *));
static void write_gc_types PARAMS ((type_p structures, type_p param_structs)); static void write_gc_types PARAMS ((type_p structures, type_p param_structs));
static void write_enum_defn PARAMS ((type_p structures, type_p param_structs));
static void put_mangled_filename PARAMS ((outf_p , const char *)); static void put_mangled_filename PARAMS ((outf_p , const char *));
static void finish_root_table PARAMS ((struct flist *flp, const char *pfx, static void finish_root_table PARAMS ((struct flist *flp, const char *pfx,
const char *tname, const char *lastname, const char *tname, const char *lastname,
...@@ -911,15 +1402,70 @@ output_escaped_param (of, param, val, prev_val, oname, line) ...@@ -911,15 +1402,70 @@ output_escaped_param (of, param, val, prev_val, oname, line)
for (p = param; *p; p++) for (p = param; *p; p++)
if (*p != '%') if (*p != '%')
oprintf (of, "%c", *p); oprintf (of, "%c", *p);
else if (*++p == 'h') else switch (*++p)
oprintf (of, "(%s)", val); {
else if (*p == '0') case 'h':
oprintf (of, "(*x)"); oprintf (of, "(%s)", val);
else if (*p == '1') break;
oprintf (of, "(%s)", prev_val); case '0':
else oprintf (of, "(*x)");
error_at_line (line, "`%s' option contains bad escape %c%c", break;
oname, '%', *p); case '1':
oprintf (of, "(%s)", prev_val);
break;
case 'a':
{
const char *pp = val + strlen (val);
while (pp[-1] == ']')
while (*pp != '[')
pp--;
oprintf (of, "%s", pp);
}
break;
default:
error_at_line (line, "`%s' option contains bad escape %c%c",
oname, '%', *p);
}
}
/* Print a mangled name representing T to OF. */
static void
output_mangled_typename (of, t)
outf_p of;
type_p t;
{
if (t == NULL)
oprintf (of, "Z");
else switch (t->kind)
{
case TYPE_POINTER:
oprintf (of, "P");
output_mangled_typename (of, t->u.p);
break;
case TYPE_SCALAR:
oprintf (of, "I");
break;
case TYPE_STRING:
oprintf (of, "S");
break;
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_LANG_STRUCT:
oprintf (of, "%d%s", strlen (t->u.s.tag), t->u.s.tag);
break;
case TYPE_PARAM_STRUCT:
{
int i;
for (i = 0; i < NUM_PARAM; i++)
if (t->u.param_struct.param[i] != NULL)
output_mangled_typename (of, t->u.param_struct.param[i]);
output_mangled_typename (of, t->u.param_struct.stru);
}
break;
case TYPE_ARRAY:
abort ();
}
} }
/* Write out code to OF which marks the fields of S. VAL references /* Write out code to OF which marks the fields of S. VAL references
...@@ -940,10 +1486,10 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -940,10 +1486,10 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
int indent; int indent;
struct fileloc *line; struct fileloc *line;
lang_bitmap bitmap; lang_bitmap bitmap;
type_p param; type_p * param;
{ {
pair_p f; pair_p f;
int tagcounter = -1; int seen_default = 0;
if (! s->u.s.line.file) if (! s->u.s.line.file)
error_at_line (line, "incomplete structure `%s'", s->u.s.tag); error_at_line (line, "incomplete structure `%s'", s->u.s.tag);
...@@ -958,7 +1504,6 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -958,7 +1504,6 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
const char *tagexpr = NULL; const char *tagexpr = NULL;
options_p oo; options_p oo;
tagcounter = ++gc_counter;
for (oo = opts; oo; oo = oo->next) for (oo = opts; oo; oo = oo->next)
if (strcmp (oo->name, "desc") == 0) if (strcmp (oo->name, "desc") == 0)
tagexpr = (const char *)oo->info; tagexpr = (const char *)oo->info;
...@@ -968,29 +1513,26 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -968,29 +1513,26 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
error_at_line (line, "missing `desc' option"); error_at_line (line, "missing `desc' option");
} }
oprintf (of, "%*s{\n", indent, ""); oprintf (of, "%*sswitch (", indent, "");
indent += 2;
oprintf (of, "%*sunsigned int tag%d = (", indent, "", tagcounter);
output_escaped_param (of, tagexpr, val, prev_val, "desc", line); output_escaped_param (of, tagexpr, val, prev_val, "desc", line);
oprintf (of, ");\n"); oprintf (of, ")\n");
indent += 2;
oprintf (of, "%*s{\n", indent, "");
} }
for (f = s->u.s.fields; f; f = f->next) for (f = s->u.s.fields; f; f = f->next)
{ {
const char *tagid = NULL; const char *tagid = NULL;
const char *length = NULL; const char *length = NULL;
const char *special = NULL;
int skip_p = 0; int skip_p = 0;
int always_p = 0; int default_p = 0;
int maybe_undef_p = 0; int maybe_undef_p = 0;
int use_param_p = 0; int use_param_num = -1;
int use_params_p = 0;
int needs_cast_p = 0;
options_p oo; options_p oo;
type_p t = f->type; type_p t = f->type;
const char *dot = ".";
if (t->kind == TYPE_SCALAR
|| (t->kind == TYPE_ARRAY
&& t->u.a.p->kind == TYPE_SCALAR))
continue;
for (oo = f->opt; oo; oo = oo->next) for (oo = f->opt; oo; oo = oo->next)
if (strcmp (oo->name, "length") == 0) if (strcmp (oo->name, "length") == 0)
...@@ -1000,62 +1542,88 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1000,62 +1542,88 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
else if (strcmp (oo->name, "tag") == 0) else if (strcmp (oo->name, "tag") == 0)
tagid = (const char *)oo->info; tagid = (const char *)oo->info;
else if (strcmp (oo->name, "special") == 0) else if (strcmp (oo->name, "special") == 0)
special = (const char *)oo->info; ;
else if (strcmp (oo->name, "skip") == 0) else if (strcmp (oo->name, "skip") == 0)
skip_p = 1; skip_p = 1;
else if (strcmp (oo->name, "always") == 0) else if (strcmp (oo->name, "default") == 0)
always_p = 1; default_p = 1;
else if (strcmp (oo->name, "desc") == 0 && UNION_P (t)) else if (strcmp (oo->name, "desc") == 0)
; ;
else if (strcmp (oo->name, "descbits") == 0 && UNION_P (t)) else if (strcmp (oo->name, "descbits") == 0)
; ;
else if (strcmp (oo->name, "param_is") == 0) else if (strcmp (oo->name, "param_is") == 0)
; ;
else if (strcmp (oo->name, "use_param") == 0) else if (strncmp (oo->name, "use_param", 9) == 0
use_param_p = 1; && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
else if (strcmp (oo->name, "use_params") == 0)
use_params_p = 1;
else if (strcmp (oo->name, "dot") == 0)
dot = (const char *)oo->info;
else else
error_at_line (&f->line, "unknown field option `%s'\n", oo->name); error_at_line (&f->line, "unknown field option `%s'\n", oo->name);
if (skip_p) if (skip_p)
continue; continue;
if (use_params_p)
{
int pointer_p = t->kind == TYPE_POINTER;
if (pointer_p)
t = t->u.p;
t = find_param_structure (t, param);
if (pointer_p)
t = create_pointer (t);
}
if (use_param_p) if (use_param_num != -1)
{ {
if (param != NULL) if (param != NULL && param[use_param_num] != NULL)
{ {
type_p t1; type_p nt = param[use_param_num];
type_p nt = param;
int arraycount = 0;
for (t1 = t; t->kind == TYPE_ARRAY; t = t->u.a.p) if (t->kind == TYPE_ARRAY)
arraycount++;
for (; t->kind == TYPE_POINTER; t = t->u.p)
nt = create_pointer (nt);
while (arraycount-- > 0)
nt = create_array (nt, t->u.a.len); nt = create_array (nt, t->u.a.len);
else if (length != NULL && t->kind == TYPE_POINTER)
nt = create_pointer (nt);
needs_cast_p = (t->kind != TYPE_POINTER
&& nt->kind == TYPE_POINTER);
t = nt; t = nt;
} }
else if (s->kind == TYPE_UNION && ! always_p && tagid) else if (s->kind != TYPE_UNION)
;
else
error_at_line (&f->line, "no parameter defined"); error_at_line (&f->line, "no parameter defined");
} }
if (t->kind == TYPE_SCALAR
|| (t->kind == TYPE_ARRAY
&& t->u.a.p->kind == TYPE_SCALAR))
continue;
seen_default |= default_p;
if (maybe_undef_p if (maybe_undef_p
&& (t->kind != TYPE_POINTER && (t->kind != TYPE_POINTER
|| t->u.p->kind != TYPE_STRUCT)) || t->u.p->kind != TYPE_STRUCT))
error_at_line (&f->line, error_at_line (&f->line,
"field `%s' has invalid option `maybe_undef_p'\n", "field `%s' has invalid option `maybe_undef_p'\n",
f->name); f->name);
if (s->kind == TYPE_UNION && ! always_p ) if (s->kind == TYPE_UNION)
{ {
if (! tagid) if (tagid)
{
oprintf (of, "%*scase %s:\n", indent, "", tagid);
}
else if (default_p)
{
oprintf (of, "%*sdefault:\n", indent, "");
}
else
{ {
error_at_line (&f->line, "field `%s' has no tag", f->name); error_at_line (&f->line, "field `%s' has no tag", f->name);
continue; continue;
} }
oprintf (of, "%*sif (tag%d == (%s)) {\n", indent, "",
tagcounter, tagid);
indent += 2; indent += 2;
} }
...@@ -1087,7 +1655,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1087,7 +1655,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
{ {
char *newval; char *newval;
newval = xasprintf ("%s.%s", val, f->name); newval = xasprintf ("%s%s%s", val, dot, f->name);
write_gc_structure_fields (of, t, newval, val, f->opt, indent, write_gc_structure_fields (of, t, newval, val, f->opt, indent,
&f->line, bitmap, param); &f->line, bitmap, param);
free (newval); free (newval);
...@@ -1099,17 +1667,20 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1099,17 +1667,20 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
{ {
if (maybe_undef_p if (maybe_undef_p
&& t->u.p->u.s.line.file == NULL) && t->u.p->u.s.line.file == NULL)
oprintf (of, "%*sif (%s.%s) abort();\n", indent, "", oprintf (of, "%*sif (%s%s%s) abort();\n", indent, "",
val, f->name); val, dot, f->name);
else if (UNION_OR_STRUCT_P (t->u.p)) else if (UNION_OR_STRUCT_P (t->u.p)
oprintf (of, "%*sgt_ggc_m_%s (%s.%s);\n", indent, "", || t->u.p->kind == TYPE_PARAM_STRUCT)
t->u.p->u.s.tag, val, f->name); {
else if (t->u.p->kind == TYPE_PARAM_STRUCT) oprintf (of, "%*sgt_ggc_m_", indent, "");
oprintf (of, "%*sgt_ggc_mm_%d%s_%s (%s.%s);\n", indent, "", output_mangled_typename (of, t->u.p);
(int) strlen (t->u.p->u.param_struct.param->u.s.tag), oprintf (of, " (");
t->u.p->u.param_struct.param->u.s.tag, if (needs_cast_p)
t->u.p->u.param_struct.stru->u.s.tag, oprintf (of, "(%s %s *)",
val, f->name); UNION_P (t->u.p) ? "union" : "struct",
t->u.p->u.s.tag);
oprintf (of, "%s%s%s);\n", val, dot, f->name);
}
else else
error_at_line (&f->line, "field `%s' is pointer to scalar", error_at_line (&f->line, "field `%s' is pointer to scalar",
f->name); f->name);
...@@ -1117,18 +1688,18 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1117,18 +1688,18 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
} }
else if (t->u.p->kind == TYPE_SCALAR else if (t->u.p->kind == TYPE_SCALAR
|| t->u.p->kind == TYPE_STRING) || t->u.p->kind == TYPE_STRING)
oprintf (of, "%*sggc_mark (%s.%s);\n", indent, "", oprintf (of, "%*sggc_mark (%s%s%s);\n", indent, "",
val, f->name); val, dot, f->name);
else else
{ {
int loopcounter = ++gc_counter; int loopcounter = ++gc_counter;
oprintf (of, "%*sif (%s.%s != NULL) {\n", indent, "", oprintf (of, "%*sif (%s%s%s != NULL) {\n", indent, "",
val, f->name); val, dot, f->name);
indent += 2; indent += 2;
oprintf (of, "%*ssize_t i%d;\n", indent, "", loopcounter); oprintf (of, "%*ssize_t i%d;\n", indent, "", loopcounter);
oprintf (of, "%*sggc_set_mark (%s.%s);\n", indent, "", oprintf (of, "%*sggc_set_mark (%s%s%s);\n", indent, "",
val, f->name); val, dot, f->name);
oprintf (of, "%*sfor (i%d = 0; i%d < (size_t)(", indent, "", oprintf (of, "%*sfor (i%d = 0; i%d < (size_t)(", indent, "",
loopcounter, loopcounter); loopcounter, loopcounter);
output_escaped_param (of, length, val, prev_val, "length", line); output_escaped_param (of, length, val, prev_val, "length", line);
...@@ -1141,7 +1712,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1141,7 +1712,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
{ {
char *newval; char *newval;
newval = xasprintf ("%s.%s[i%d]", val, f->name, newval = xasprintf ("%s%s%s[i%d]", val, dot, f->name,
loopcounter); loopcounter);
write_gc_structure_fields (of, t->u.p, newval, val, write_gc_structure_fields (of, t->u.p, newval, val,
f->opt, indent, &f->line, f->opt, indent, &f->line,
...@@ -1150,10 +1721,14 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1150,10 +1721,14 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
break; break;
} }
case TYPE_POINTER: case TYPE_POINTER:
if (UNION_OR_STRUCT_P (t->u.p->u.p)) if (UNION_OR_STRUCT_P (t->u.p->u.p)
oprintf (of, "%*sgt_ggc_m_%s (%s.%s[i%d]);\n", indent, "", || t->u.p->u.p->kind == TYPE_PARAM_STRUCT)
t->u.p->u.p->u.s.tag, val, f->name, {
loopcounter); oprintf (of, "%*sgt_ggc_m_", indent, "");
output_mangled_typename (of, t->u.p->u.p);
oprintf (of, " (%s%s%s[i%d]);\n", val, dot, f->name,
loopcounter);
}
else else
error_at_line (&f->line, error_at_line (&f->line,
"field `%s' is array of pointer to scalar", "field `%s' is array of pointer to scalar",
...@@ -1195,17 +1770,6 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1195,17 +1770,6 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
oprintf (of, "%*s{\n", indent, ""); oprintf (of, "%*s{\n", indent, "");
indent += 2; indent += 2;
if (special != NULL && strcmp (special, "tree_exp") == 0)
{
oprintf (of, "%*sconst size_t tree_exp_size = (",
indent, "");
output_escaped_param (of, length, val, prev_val,
"length", line);
oprintf (of, ");\n");
length = "first_rtl_op (TREE_CODE ((tree)&%h))";
}
for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++) for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
{ {
oprintf (of, "%*ssize_t i%d_%d;\n", oprintf (of, "%*ssize_t i%d_%d;\n",
...@@ -1230,11 +1794,12 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1230,11 +1794,12 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
} }
if (ta->kind == TYPE_POINTER if (ta->kind == TYPE_POINTER
&& (ta->u.p->kind == TYPE_STRUCT && (UNION_OR_STRUCT_P (ta->u.p)
|| ta->u.p->kind == TYPE_UNION)) || ta->u.p->kind == TYPE_PARAM_STRUCT))
{ {
oprintf (of, "%*sgt_ggc_m_%s (%s.%s", oprintf (of, "%*sgt_ggc_m_", indent, "");
indent, "", ta->u.p->u.s.tag, val, f->name); output_mangled_typename (of, ta->u.p);
oprintf (of, " (%s%s%s", val, dot, f->name);
for (ta = t, i = 0; for (ta = t, i = 0;
ta->kind == TYPE_ARRAY; ta->kind == TYPE_ARRAY;
ta = ta->u.a.p, i++) ta = ta->u.a.p, i++)
...@@ -1251,7 +1816,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1251,7 +1816,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
len += sizeof ("[i_]") + 2*6; len += sizeof ("[i_]") + 2*6;
newval = xmalloc (len); newval = xmalloc (len);
sprintf (newval, "%s.%s", val, f->name); sprintf (newval, "%s%s%s", val, dot, f->name);
for (ta = t, i = 0; for (ta = t, i = 0;
ta->kind == TYPE_ARRAY; ta->kind == TYPE_ARRAY;
ta = ta->u.a.p, i++) ta = ta->u.a.p, i++)
...@@ -1263,7 +1828,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1263,7 +1828,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
free (newval); free (newval);
} }
else if (ta->kind == TYPE_POINTER && ta->u.p->kind == TYPE_SCALAR else if (ta->kind == TYPE_POINTER && ta->u.p->kind == TYPE_SCALAR
&& use_param_p && param == NULL) && use_param_num != -1 && param == NULL)
oprintf (of, "%*sabort();\n", indent, ""); oprintf (of, "%*sabort();\n", indent, "");
else else
error_at_line (&f->line, error_at_line (&f->line,
...@@ -1275,16 +1840,6 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1275,16 +1840,6 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
oprintf (of, "%*s}\n", indent, ""); oprintf (of, "%*s}\n", indent, "");
} }
if (special != NULL && strcmp (special, "tree_exp") == 0)
{
oprintf (of,
"%*sfor (; i%d_0 < tree_exp_size; i%d_0++)\n",
indent, "", loopcounter, loopcounter);
oprintf (of, "%*s gt_ggc_m_rtx_def (%s.%s[i%d_0]);\n",
indent, "", val, f->name, loopcounter);
special = NULL;
}
indent -= 2; indent -= 2;
oprintf (of, "%*s}\n", indent, ""); oprintf (of, "%*s}\n", indent, "");
break; break;
...@@ -1297,18 +1852,21 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1297,18 +1852,21 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
break; break;
} }
if (s->kind == TYPE_UNION && ! always_p ) if (s->kind == TYPE_UNION)
{ {
oprintf (of, "%*sbreak;\n", indent, "");
indent -= 2; indent -= 2;
oprintf (of, "%*s}\n", indent, "");
} }
if (special)
error_at_line (&f->line, "unhandled special `%s'", special);
} }
if (s->kind == TYPE_UNION) if (s->kind == TYPE_UNION)
{ {
indent -= 2; if (! seen_default)
{
oprintf (of, "%*sdefault:\n", indent, "");
oprintf (of, "%*s break;\n", indent, "");
}
oprintf (of, "%*s}\n", indent, ""); oprintf (of, "%*s}\n", indent, "");
indent -= 2;
} }
} }
...@@ -1316,36 +1874,96 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap, ...@@ -1316,36 +1874,96 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
enclosing PARAM_IS option. */ enclosing PARAM_IS option. */
static void static void
write_gc_marker_routine_for_structure (s, param) write_gc_marker_routine_for_structure (orig_s, s, param)
type_p orig_s;
type_p s; type_p s;
type_p param; type_p * param;
{ {
outf_p f; outf_p f;
if (param == NULL) const char *fn = s->u.s.line.file;
f = get_output_file_with_visibility (s->u.s.line.file); int i;
else const char *chain_next = NULL;
f = get_output_file_with_visibility (param->u.s.line.file); const char *chain_prev = NULL;
options_p opt;
/* This is a hack, and not the good kind either. */
for (i = NUM_PARAM - 1; i >= 0; i--)
if (param && param[i] && param[i]->kind == TYPE_POINTER
&& UNION_OR_STRUCT_P (param[i]->u.p))
fn = param[i]->u.p->u.s.line.file;
f = get_output_file_with_visibility (fn);
oprintf (f, "%c", '\n'); for (opt = s->u.s.opt; opt; opt = opt->next)
if (strcmp (opt->name, "chain_next") == 0)
chain_next = (const char *) opt->info;
else if (strcmp (opt->name, "chain_prev") == 0)
chain_prev = (const char *) opt->info;
if (chain_prev != NULL && chain_next == NULL)
error_at_line (&s->u.s.line, "chain_prev without chain_next");
oprintf (f, "\n");
oprintf (f, "void\n"); oprintf (f, "void\n");
if (param == NULL) if (param == NULL)
oprintf (f, "gt_ggc_mx_%s (x_p)\n", s->u.s.tag); oprintf (f, "gt_ggc_mx_%s", s->u.s.tag);
else else
oprintf (f, "gt_ggc_mm_%d%s_%s (x_p)\n", (int) strlen (param->u.s.tag), {
param->u.s.tag, s->u.s.tag); oprintf (f, "gt_ggc_m_");
output_mangled_typename (f, orig_s);
}
oprintf (f, " (x_p)\n");
oprintf (f, " void *x_p;\n"); oprintf (f, " void *x_p;\n");
oprintf (f, "{\n"); oprintf (f, "{\n");
oprintf (f, " %s %s * const x = (%s %s *)x_p;\n", oprintf (f, " %s %s * %sx = (%s %s *)x_p;\n",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag, s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
chain_next == NULL ? "const " : "",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag); s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
oprintf (f, " if (! ggc_test_and_set_mark (x))\n"); if (chain_next != NULL)
oprintf (f, " return;\n"); oprintf (f, " %s %s * xlimit = x;\n",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
if (chain_next == NULL)
oprintf (f, " if (ggc_test_and_set_mark (x))\n");
else
{
oprintf (f, " while (ggc_test_and_set_mark (xlimit))\n");
oprintf (f, " xlimit = (");
output_escaped_param (f, chain_next, "*xlimit", "*xlimit",
"chain_next", &s->u.s.line);
oprintf (f, ");\n");
if (chain_prev != NULL)
{
oprintf (f, " if (x != xlimit)\n");
oprintf (f, " for (;;)\n");
oprintf (f, " {\n");
oprintf (f, " %s %s * const xprev = (",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
output_escaped_param (f, chain_prev, "*x", "*x",
"chain_prev", &s->u.s.line);
oprintf (f, ");\n");
oprintf (f, " if (xprev == NULL) break;\n");
oprintf (f, " x = xprev;\n");
oprintf (f, " ggc_set_mark (xprev);\n");
oprintf (f, " }\n");
}
oprintf (f, " while (x != xlimit)\n");
}
oprintf (f, " {\n");
gc_counter = 0; gc_counter = 0;
write_gc_structure_fields (f, s, "(*x)", "not valid postage", write_gc_structure_fields (f, s, "(*x)", "not valid postage",
s->u.s.opt, 2, &s->u.s.line, s->u.s.bitmap, s->u.s.opt, 6, &s->u.s.line, s->u.s.bitmap,
param); param);
if (chain_next != NULL)
{
oprintf (f, " x = (");
output_escaped_param (f, chain_next, "*x", "*x",
"chain_next", &s->u.s.line);
oprintf (f, ");\n");
}
oprintf (f, " }\n");
oprintf (f, "}\n"); oprintf (f, "}\n");
} }
...@@ -1369,8 +1987,9 @@ write_gc_types (structures, param_structs) ...@@ -1369,8 +1987,9 @@ write_gc_types (structures, param_structs)
&& s->u.s.line.file == NULL) && s->u.s.line.file == NULL)
continue; continue;
oprintf (header_file, oprintf (header_file, "#define gt_ggc_m_");
"#define gt_ggc_m_%s(X) do { \\\n", s->u.s.tag); output_mangled_typename (header_file, s);
oprintf (header_file, "(X) do { \\\n");
oprintf (header_file, oprintf (header_file,
" if (X != NULL) gt_ggc_mx_%s (X);\\\n", s->u.s.tag); " if (X != NULL) gt_ggc_mx_%s (X);\\\n", s->u.s.tag);
oprintf (header_file, oprintf (header_file,
...@@ -1410,31 +2029,22 @@ write_gc_types (structures, param_structs) ...@@ -1410,31 +2029,22 @@ write_gc_types (structures, param_structs)
{ {
type_p ss; type_p ss;
for (ss = s->u.s.lang_struct; ss; ss = ss->next) for (ss = s->u.s.lang_struct; ss; ss = ss->next)
write_gc_marker_routine_for_structure (ss, NULL); write_gc_marker_routine_for_structure (s, ss, NULL);
} }
else else
write_gc_marker_routine_for_structure (s, NULL); write_gc_marker_routine_for_structure (s, s, NULL);
} }
for (s = param_structs; s; s = s->next) for (s = param_structs; s; s = s->next)
if (s->gc_used == GC_POINTED_TO) if (s->gc_used == GC_POINTED_TO)
{ {
type_p param = s->u.param_struct.param; type_p * param = s->u.param_struct.param;
type_p stru = s->u.param_struct.stru; type_p stru = s->u.param_struct.stru;
if (param->kind != TYPE_STRUCT && param->kind != TYPE_UNION
&& param->kind != TYPE_LANG_STRUCT)
{
error_at_line (&s->u.param_struct.line,
"unsupported parameter type");
continue;
}
/* Declare the marker procedure. */ /* Declare the marker procedure. */
oprintf (header_file, oprintf (header_file, "extern void gt_ggc_m_");
"extern void gt_ggc_mm_%d%s_%s PARAMS ((void *));\n", output_mangled_typename (header_file, s);
(int) strlen (param->u.s.tag), param->u.s.tag, oprintf (header_file, " PARAMS ((void *));\n");
stru->u.s.tag);
if (stru->u.s.line.file == NULL) if (stru->u.s.line.file == NULL)
{ {
...@@ -1447,13 +2057,48 @@ write_gc_types (structures, param_structs) ...@@ -1447,13 +2057,48 @@ write_gc_types (structures, param_structs)
{ {
type_p ss; type_p ss;
for (ss = stru->u.s.lang_struct; ss; ss = ss->next) for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
write_gc_marker_routine_for_structure (ss, param); write_gc_marker_routine_for_structure (s, ss, param);
} }
else else
write_gc_marker_routine_for_structure (stru, param); write_gc_marker_routine_for_structure (s, stru, param);
}
}
/* Write out the 'enum' definition for gt_types_enum. */
static void
write_enum_defn (structures, param_structs)
type_p structures;
type_p param_structs;
{
type_p s;
oprintf (header_file, "\n/* Enumeration of types known. */\n");
oprintf (header_file, "enum gt_types_enum {\n");
for (s = structures; s; s = s->next)
if (s->gc_used == GC_POINTED_TO
|| s->gc_used == GC_MAYBE_POINTED_TO)
{
if (s->gc_used == GC_MAYBE_POINTED_TO
&& s->u.s.line.file == NULL)
continue;
oprintf (header_file, " gt_ggc_e_");
output_mangled_typename (header_file, s);
oprintf (header_file, ", \n");
} }
for (s = param_structs; s; s = s->next)
if (s->gc_used == GC_POINTED_TO)
{
oprintf (header_file, " gt_e_");
output_mangled_typename (header_file, s);
oprintf (header_file, ", \n");
}
oprintf (header_file, " gt_types_enum_last\n");
oprintf (header_file, "};\n");
} }
/* Mangle FN and print it to F. */ /* Mangle FN and print it to F. */
static void static void
...@@ -1540,7 +2185,7 @@ finish_root_table (flp, pfx, lastname, tname, name) ...@@ -1540,7 +2185,7 @@ finish_root_table (flp, pfx, lastname, tname, name)
if (bitmap & 1) if (bitmap & 1)
{ {
oprintf (base_files[fnum], " NULL\n"); oprintf (base_files[fnum], " NULL\n");
oprintf (base_files[fnum], "};\n\n"); oprintf (base_files[fnum], "};\n");
} }
} }
} }
...@@ -1667,10 +2312,8 @@ write_gc_root (f, v, type, name, has_length, line, if_marked) ...@@ -1667,10 +2312,8 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
} }
else if (! has_length && tp->kind == TYPE_PARAM_STRUCT) else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
{ {
oprintf (f, " &gt_ggc_mm_%d%s_%s", oprintf (f, " &gt_ggc_m_");
(int) strlen (tp->u.param_struct.param->u.s.tag), output_mangled_typename (f, tp);
tp->u.param_struct.param->u.s.tag,
tp->u.param_struct.stru->u.s.tag);
} }
else if (has_length else if (has_length
&& (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp))) && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
...@@ -1724,6 +2367,10 @@ write_gc_roots (variables) ...@@ -1724,6 +2367,10 @@ write_gc_roots (variables)
deletable_p = 1; deletable_p = 1;
else if (strcmp (o->name, "param_is") == 0) else if (strcmp (o->name, "param_is") == 0)
; ;
else if (strncmp (o->name, "param", 5) == 0
&& ISDIGIT (o->name[5])
&& strcmp (o->name + 6, "_is") == 0)
;
else if (strcmp (o->name, "if_marked") == 0) else if (strcmp (o->name, "if_marked") == 0)
; ;
else else
...@@ -1768,7 +2415,8 @@ write_gc_roots (variables) ...@@ -1768,7 +2415,8 @@ write_gc_roots (variables)
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag); s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
oprintf (f, " if (ggc_test_and_set_mark (x))\n"); oprintf (f, " if (ggc_test_and_set_mark (x))\n");
oprintf (f, " for (i = 0; i < (%s); i++)\n", length); oprintf (f, " for (i = 0; i < (%s); i++)\n", length);
if (s->kind != TYPE_STRUCT && s->kind != TYPE_UNION) if (! UNION_OR_STRUCT_P (s)
&& ! s->kind == TYPE_PARAM_STRUCT)
{ {
error_at_line (&v->line, error_at_line (&v->line,
"global `%s' has unsupported ** type", "global `%s' has unsupported ** type",
...@@ -1776,7 +2424,9 @@ write_gc_roots (variables) ...@@ -1776,7 +2424,9 @@ write_gc_roots (variables)
continue; continue;
} }
oprintf (f, " gt_ggc_m_%s (x[i]);\n", s->u.s.tag); oprintf (f, " gt_ggc_m_");
output_mangled_typename (f, s);
oprintf (f, " (x[i]);\n");
} }
else else
{ {
...@@ -1906,7 +2556,7 @@ write_gc_roots (variables) ...@@ -1906,7 +2556,7 @@ write_gc_roots (variables)
oprintf (f, "[] = {\n"); oprintf (f, "[] = {\n");
} }
write_gc_root (f, v, create_pointer (v->type->u.p->u.param_struct.param), write_gc_root (f, v, v->type->u.p->u.param_struct.param[0],
v->name, length_p, &v->line, if_marked); v->name, length_p, &v->line, if_marked);
} }
...@@ -1925,20 +2575,19 @@ main(argc, argv) ...@@ -1925,20 +2575,19 @@ main(argc, argv)
static struct fileloc pos = { __FILE__, __LINE__ }; static struct fileloc pos = { __FILE__, __LINE__ };
unsigned j; unsigned j;
gen_rtx_next ();
srcdir_len = strlen (srcdir); srcdir_len = strlen (srcdir);
do_typedef ("CUMULATIVE_ARGS", do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
create_scalar_type ("CUMULATIVE_ARGS", do_scalar_typedef ("REAL_VALUE_TYPE", &pos);
strlen ("CUMULATIVE_ARGS")), do_scalar_typedef ("uint8", &pos);
&pos); do_scalar_typedef ("jword", &pos);
do_typedef ("REAL_VALUE_TYPE", do_scalar_typedef ("JCF_u2", &pos);
create_scalar_type ("REAL_VALUE_TYPE",
strlen ("REAL_VALUE_TYPE")),
&pos);
do_typedef ("PTR", create_pointer (create_scalar_type ("void", do_typedef ("PTR", create_pointer (create_scalar_type ("void",
strlen ("void"))), strlen ("void"))),
&pos); &pos);
do_typedef ("HARD_REG_SET", create_array ( do_typedef ("HARD_REG_SET", create_array (
create_scalar_type ("unsigned long", strlen ("unsigned long")), create_scalar_type ("unsigned long", strlen ("unsigned long")),
"2"), &pos); "2"), &pos);
...@@ -1965,8 +2614,10 @@ main(argc, argv) ...@@ -1965,8 +2614,10 @@ main(argc, argv)
set_gc_used (variables); set_gc_used (variables);
open_base_files (); open_base_files ();
write_enum_defn (structures, param_structs);
write_gc_types (structures, param_structs); write_gc_types (structures, param_structs);
write_gc_roots (variables); write_gc_roots (variables);
write_rtx_next ();
close_output_files (); close_output_files ();
return (hit_error != 0); return (hit_error != 0);
......
...@@ -41,7 +41,7 @@ enum typekind { ...@@ -41,7 +41,7 @@ enum typekind {
typedef struct options { typedef struct options {
struct options *next; struct options *next;
const char *name; const char *name;
void *info; const void *info;
} *options_p; } *options_p;
typedef struct pair *pair_p; typedef struct pair *pair_p;
...@@ -57,6 +57,8 @@ struct pair { ...@@ -57,6 +57,8 @@ struct pair {
options_p opt; options_p opt;
}; };
#define NUM_PARAM 10
/* A description of a type. */ /* A description of a type. */
struct type { struct type {
enum typekind kind; enum typekind kind;
...@@ -85,7 +87,7 @@ struct type { ...@@ -85,7 +87,7 @@ struct type {
} a; } a;
struct { struct {
type_p stru; type_p stru;
type_p param; type_p param[NUM_PARAM];
struct fileloc line; struct fileloc line;
} param_struct; } param_struct;
} u; } u;
......
...@@ -34,7 +34,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -34,7 +34,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Statistics about the allocation. */ /* Statistics about the allocation. */
static ggc_statistics *ggc_stats; static ggc_statistics *ggc_stats;
static void ggc_mark_rtx_children_1 PARAMS ((rtx));
static int ggc_htab_delete PARAMS ((void **, void *)); static int ggc_htab_delete PARAMS ((void **, void *));
/* Maintain global roots that are preserved during GC. */ /* Maintain global roots that are preserved during GC. */
...@@ -132,140 +131,6 @@ ggc_mark_roots () ...@@ -132,140 +131,6 @@ ggc_mark_roots ()
htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti); htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti);
} }
/* R had not been previously marked, but has now been marked via
ggc_set_mark. Now recurse and process the children. */
void
ggc_mark_rtx_children (r)
rtx r;
{
rtx i, last;
/* Special case the instruction chain. This is a data structure whose
chain length is potentially unbounded, and which contain references
within the chain (e.g. label_ref and insn_list). If do nothing here,
we risk blowing the stack recursing through a long chain of insns.
Combat this by marking all of the instructions in the chain before
marking the contents of those instructions. */
switch (GET_CODE (r))
{
case INSN:
case JUMP_INSN:
case CALL_INSN:
case NOTE:
case CODE_LABEL:
case BARRIER:
for (i = NEXT_INSN (r); ; i = NEXT_INSN (i))
if (! ggc_test_and_set_mark (i))
break;
last = i;
for (i = NEXT_INSN (r); i != last; i = NEXT_INSN (i))
ggc_mark_rtx_children_1 (i);
default:
break;
}
ggc_mark_rtx_children_1 (r);
}
static void
ggc_mark_rtx_children_1 (r)
rtx r;
{
const char *fmt;
int i;
rtx next_rtx;
do
{
enum rtx_code code = GET_CODE (r);
/* This gets set to a child rtx to eliminate tail recursion. */
next_rtx = NULL;
/* Collect statistics, if appropriate. */
if (ggc_stats)
{
++ggc_stats->num_rtxs[(int) code];
ggc_stats->size_rtxs[(int) code] += ggc_get_size (r);
}
/* ??? If (some of) these are really pass-dependent info, do we
have any right poking our noses in? */
switch (code)
{
case MEM:
gt_ggc_m_mem_attrs (MEM_ATTRS (r));
break;
case JUMP_INSN:
ggc_mark_rtx (JUMP_LABEL (r));
break;
case CODE_LABEL:
ggc_mark_rtx (LABEL_REFS (r));
break;
case LABEL_REF:
ggc_mark_rtx (LABEL_NEXTREF (r));
ggc_mark_rtx (CONTAINING_INSN (r));
break;
case ADDRESSOF:
ggc_mark_tree (ADDRESSOF_DECL (r));
break;
case NOTE:
switch (NOTE_LINE_NUMBER (r))
{
case NOTE_INSN_EXPECTED_VALUE:
ggc_mark_rtx (NOTE_EXPECTED_VALUE (r));
break;
case NOTE_INSN_BLOCK_BEG:
case NOTE_INSN_BLOCK_END:
ggc_mark_tree (NOTE_BLOCK (r));
break;
default:
break;
}
break;
default:
break;
}
for (fmt = GET_RTX_FORMAT (GET_CODE (r)), i = 0; *fmt ; ++fmt, ++i)
{
rtx exp;
switch (*fmt)
{
case 'e': case 'u':
exp = XEXP (r, i);
if (ggc_test_and_set_mark (exp))
{
if (next_rtx == NULL)
next_rtx = exp;
else
ggc_mark_rtx_children (exp);
}
break;
case 'V': case 'E':
gt_ggc_m_rtvec_def (XVEC (r, i));
break;
}
}
}
while ((r = next_rtx) != NULL);
}
/* Various adaptor functions. */
void
gt_ggc_mx_rtx_def (x)
void *x;
{
ggc_mark_rtx((rtx)x);
}
/* Allocate a block of memory, then clear it. */ /* Allocate a block of memory, then clear it. */
void * void *
ggc_alloc_cleared (size) ggc_alloc_cleared (size)
......
/* Garbage collection for the GNU compiler. /* Garbage collection for the GNU compiler.
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -62,21 +62,13 @@ extern const struct ggc_cache_tab * const gt_ggc_cache_rtab[]; ...@@ -62,21 +62,13 @@ extern const struct ggc_cache_tab * const gt_ggc_cache_rtab[];
extern void ggc_mark_roots PARAMS ((void)); extern void ggc_mark_roots PARAMS ((void));
extern void ggc_mark_rtx_children PARAMS ((struct rtx_def *));
/* If EXPR is not NULL and previously unmarked, mark it and evaluate /* If EXPR is not NULL and previously unmarked, mark it and evaluate
to true. Otherwise evaluate to false. */ to true. Otherwise evaluate to false. */
#define ggc_test_and_set_mark(EXPR) \ #define ggc_test_and_set_mark(EXPR) \
((EXPR) != NULL && ((void *) (EXPR)) != (void *) 1 && ! ggc_set_mark (EXPR)) ((EXPR) != NULL && ((void *) (EXPR)) != (void *) 1 && ! ggc_set_mark (EXPR))
#define ggc_mark_rtx(EXPR) \ #define ggc_mark_rtx gt_ggc_m_7rtx_def
do { \ #define ggc_mark_tree gt_ggc_m_9tree_node
rtx const r__ = (EXPR); \
if (ggc_test_and_set_mark (r__)) \
ggc_mark_rtx_children (r__); \
} while (0)
#define ggc_mark_tree gt_ggc_m_tree_node
#define ggc_mark(EXPR) \ #define ggc_mark(EXPR) \
do { \ do { \
......
2002-09-16 Geoffrey Keating <geoffk@apple.com>
* java-tree.h (union lang_tree_node): Add chain_next option.
2002-09-16 Richard Henderson <rth@redhat.com> 2002-09-16 Richard Henderson <rth@redhat.com>
* jcf-parse.c (get_constant): Runtime check for IEEE format; * jcf-parse.c (get_constant): Runtime check for IEEE format;
......
...@@ -693,7 +693,8 @@ struct lang_identifier GTY(()) ...@@ -693,7 +693,8 @@ struct lang_identifier GTY(())
/* The resulting tree type. */ /* The resulting tree type. */
union lang_tree_node union lang_tree_node
GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"))) GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
{ {
union tree_node GTY ((tag ("0"), union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)"))) desc ("tree_node_structure (&%h)")))
......
...@@ -186,6 +186,7 @@ const char * const rtx_format[NUM_RTX_CODE] = { ...@@ -186,6 +186,7 @@ const char * const rtx_format[NUM_RTX_CODE] = {
"u" a pointer to another insn "u" a pointer to another insn
prints the uid of the insn. prints the uid of the insn.
"b" is a pointer to a bitmap header. "b" is a pointer to a bitmap header.
"B" is a basic block pointer.
"t" is a tree pointer. */ "t" is a tree pointer. */
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT , #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
......
...@@ -62,6 +62,8 @@ extern const char * const rtx_format[NUM_RTX_CODE]; ...@@ -62,6 +62,8 @@ extern const char * const rtx_format[NUM_RTX_CODE];
extern const char rtx_class[NUM_RTX_CODE]; extern const char rtx_class[NUM_RTX_CODE];
#define GET_RTX_CLASS(CODE) (rtx_class[(int) (CODE)]) #define GET_RTX_CLASS(CODE) (rtx_class[(int) (CODE)])
extern const unsigned char rtx_next[NUM_RTX_CODE];
/* The flags and bitfields of an ADDR_DIFF_VEC. BASE is the base label /* The flags and bitfields of an ADDR_DIFF_VEC. BASE is the base label
relative to which the offsets are calculated, as explained in rtl.def. */ relative to which the offsets are calculated, as explained in rtl.def. */
...@@ -103,7 +105,7 @@ typedef struct mem_attrs GTY(()) ...@@ -103,7 +105,7 @@ typedef struct mem_attrs GTY(())
/* Common union for an element of an rtx. */ /* Common union for an element of an rtx. */
typedef union rtunion_def union rtunion_def
{ {
HOST_WIDE_INT rtwint; HOST_WIDE_INT rtwint;
int rtint; int rtint;
...@@ -118,11 +120,13 @@ typedef union rtunion_def ...@@ -118,11 +120,13 @@ typedef union rtunion_def
tree rttree; tree rttree;
struct basic_block_def *bb; struct basic_block_def *bb;
mem_attrs *rtmem; mem_attrs *rtmem;
} rtunion; };
typedef union rtunion_def rtunion;
/* RTL expression ("rtx"). */ /* RTL expression ("rtx"). */
struct rtx_def struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
chain_prev ("RTX_PREV (&%h)")))
{ {
/* The kind of expression this is. */ /* The kind of expression this is. */
ENUM_BITFIELD(rtx_code) code: 16; ENUM_BITFIELD(rtx_code) code: 16;
...@@ -198,11 +202,29 @@ struct rtx_def ...@@ -198,11 +202,29 @@ struct rtx_def
/* The first element of the operands of this rtx. /* The first element of the operands of this rtx.
The number of operands and their types are controlled The number of operands and their types are controlled
by the `code' field, according to rtl.def. */ by the `code' field, according to rtl.def. */
rtunion fld[1]; rtunion GTY ((special ("rtx_def"),
desc ("GET_CODE (&%0)"))) fld[1];
}; };
#define NULL_RTX (rtx) 0 #define NULL_RTX (rtx) 0
/* The "next" and "previous" RTX, relative to this one. */
#define RTX_NEXT(X) (rtx_next[GET_CODE (X)] == 0 ? NULL \
: *(rtx *)(((char *)X) + rtx_next[GET_CODE (X)]))
/* FIXME: the "NEXT_INSN (PREV_INSN (X)) == X" condition shouldn't be needed.
*/
#define RTX_PREV(X) ((GET_CODE (X) == INSN \
|| GET_CODE (X) == CALL_INSN \
|| GET_CODE (X) == JUMP_INSN \
|| GET_CODE (X) == NOTE \
|| GET_CODE (X) == BARRIER \
|| GET_CODE (X) == CODE_LABEL) \
&& PREV_INSN (X) != NULL \
&& NEXT_INSN (PREV_INSN (X)) == X \
? PREV_INSN (X) : NULL)
/* Define macros to access the `code' field of the rtx. */ /* Define macros to access the `code' field of the rtx. */
#define GET_CODE(RTX) ((enum rtx_code) (RTX)->code) #define GET_CODE(RTX) ((enum rtx_code) (RTX)->code)
......
...@@ -889,7 +889,7 @@ struct tree_exp GTY(()) ...@@ -889,7 +889,7 @@ struct tree_exp GTY(())
struct tree_common common; struct tree_common common;
int complexity; int complexity;
tree GTY ((special ("tree_exp"), tree GTY ((special ("tree_exp"),
length ("TREE_CODE_LENGTH (TREE_CODE ((tree) &%h))"))) desc ("TREE_CODE ((tree) &%0)")))
operands[1]; operands[1];
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment