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>
* 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 \
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
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) \
$(srcdir)/gengtype.c $(OUTPUT_OPTION)
......
......@@ -48,7 +48,8 @@ struct lang_identifier GTY(())
/* The resulting tree type. */
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"),
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>
* parse.y (parse_finish_call_expr): Check lookup_member result.
......
......@@ -505,7 +505,8 @@ enum cp_tree_node_structure_enum {
};
/* 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;
union tree_node GTY ((tag ("TS_CP_GENERIC"),
......
......@@ -72,6 +72,10 @@ immediately contains the current structure.
@item %0
This expands to an expression that evaluates to the outermost 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
The available options are:
......@@ -121,10 +125,10 @@ field really isn't ever used.
@findex desc
@findex tag
@findex always
@findex default
@item desc
@itemx tag
@itemx always
@itemx default
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}
......@@ -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
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 use_param
......@@ -154,15 +160,39 @@ You can use @code{always} to mean that this field is always used.
@itemx use_param
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.
@code{param_is} specifies the real type pointed to, and @code{use_param}
says where in the generic data structure that type should be put.
generic pointers (that is, @code{PTR}) and then use it with a specific
type. @code{param_is} specifies the real type pointed to, and
@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
@verbatim
htab_t GTY ((param_is (union tree_node))) ict;
@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
@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>
* target.c (ffetarget_real1): Don't pass FFETARGET_ATOF_
......
......@@ -605,7 +605,8 @@ struct lang_identifier GTY(())
/* The resulting tree type. */
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"),
desc ("tree_node_structure (&%h)")))
......
......@@ -203,8 +203,11 @@ ITYPE {IWORD}({WS}{IWORD})*
"struct"/[^[:alnum:]_] { return STRUCT; }
"enum"/[^[:alnum:]_] { return ENUM; }
"ptr_alias"/[^[:alnum:]_] { return ALIAS; }
"param_is"/[^[:alnum:]_] { return PARAM_IS; }
[0-9]+ { return NUM; }
"param"[0-9]*"_is"/[^[:alnum:]_] {
yylval.s = xmemdup (yytext, yyleng, yyleng+1);
return PARAM_IS;
}
{IWORD}({WS}{IWORD})*/[^[:alnum:]_] |
"ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")" {
......
......@@ -42,7 +42,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
%token STRUCT "struct"
%token ENUM "enum"
%token ALIAS "ptr_alias"
%token PARAM_IS "param_is"
%token <s>PARAM_IS
%token NUM
%token PERCENTPERCENT "%%"
%token <t>SCALAR
......@@ -174,8 +174,7 @@ yacc_ids: /* empty */
p->opt = xmalloc (sizeof (*(p->opt)));
p->opt->name = "tag";
p->opt->next = NULL;
p->opt->info = xmalloc (3 + strlen ($2));
sprintf (p->opt->info, "'%s'", $2);
p->opt->info = xasprintf ("'%s'", $2);
$$ = p;
}
;
......@@ -263,14 +262,14 @@ options: GTY_TOKEN '(' '(' optionseqopt ')' ')'
type_option : ALIAS
{ $$ = "ptr_alias"; }
| PARAM_IS
{ $$ = "param_is"; }
{ $$ = $1; }
;
option: type_option '(' type ')'
{
options_p o = xmalloc (sizeof (*o));
o->name = $1;
o->info = $3;
o->info = adjust_field_type ($3, NULL);
$$ = o;
}
| ID '(' STRING ')'
......
......@@ -26,10 +26,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Nonzero iff an error has occurred. */
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 close_output_files PARAMS ((void));
/* Report an error at POS, printing MSG. */
void
......@@ -89,6 +90,12 @@ static type_p structures;
static type_p param_structs;
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. */
void
......@@ -118,6 +125,16 @@ do_typedef (s, t, pos)
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. */
type_p
......@@ -235,6 +252,34 @@ find_structure (name, isunion)
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. */
type_p
......@@ -280,13 +325,420 @@ create_array (t, len)
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
of a field. Return the appropriate type for the field.
At present:
- Converts pointer-to-char, with no length parameter, to TYPE_STRING;
- Similarly for arrays of pointer-to-char;
- Converts structures for which a parameter is provided to
TYPE_PARAM_STRUCT.
TYPE_PARAM_STRUCT;
- Handles "special" options.
*/
type_p
......@@ -296,30 +748,61 @@ adjust_field_type (t, opt)
{
int length_p = 0;
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)
if (strcmp (opt->name, "length") == 0)
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)
t = t->u.p;
for (realt = param_structs; realt; realt = realt->next)
if (realt->u.param_struct.stru == t
&& realt->u.param_struct.param == (type_p) opt->info)
return pointer_p ? create_pointer (realt) : realt;
realt = xcalloc (1, sizeof (*realt));
realt->kind = TYPE_PARAM_STRUCT;
realt->next = param_structs;
param_structs = realt;
realt->u.param_struct.stru = t;
realt->u.param_struct.param = (type_p) opt->info;
return pointer_p ? create_pointer (realt) : realt;
if (! UNION_OR_STRUCT_P (t)
&& (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
{
error_at_line (&lexer_line,
"option `%s' may only be applied to structures or structure pointers",
opt->name);
return t;
}
params_p = 1;
if (params[num] != NULL)
error_at_line (&lexer_line, "duplicate `%s' option", opt->name);
if (! ISDIGIT (opt->name[5]))
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
&& pointer_p
&& t->u.p->kind == TYPE_SCALAR
......@@ -335,26 +818,6 @@ adjust_field_type (t, opt)
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
and information about the correspondance between token types and fields
in TYPEINFO. POS is used for error messages. */
......@@ -419,36 +882,44 @@ note_yacc_type (o, fields, typeinfo, 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 set_gc_used_type PARAMS ((type_p, enum gc_used_enum));
static void process_gc_options PARAMS ((options_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));
/* Handle OPT for set_gc_used_type. */
static void
process_gc_options (opt, level, maybe_undef)
process_gc_options (opt, level, maybe_undef, pass_param, length)
options_p opt;
enum gc_used_enum level;
int *maybe_undef;
int *pass_param;
int *length;
{
options_p o;
for (o = opt; o; o = o->next)
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)
*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. */
static void
set_gc_used_type (t, level)
set_gc_used_type (t, level, param)
type_p t;
enum gc_used_enum level;
type_p param[NUM_PARAM];
{
if (t->gc_used >= level)
return;
t->gc_used = level;
switch (t->kind)
......@@ -459,37 +930,56 @@ set_gc_used_type (t, level)
pair_p f;
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)
{
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)
set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO);
if (length && f->type->kind == TYPE_POINTER)
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
set_gc_used_type (f->type, GC_USED);
set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL);
}
break;
}
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;
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;
case TYPE_LANG_STRUCT:
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;
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;
default:
......@@ -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
set_gc_used (variables)
......@@ -505,7 +995,7 @@ set_gc_used (variables)
{
pair_p p;
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
......@@ -609,8 +1099,6 @@ oprintf VPARAMS ((outf_p o, const char *format, ...))
/* Open the global header file and the language-specific header files. */
static void open_base_files PARAMS((void));
static void
open_base_files ()
{
......@@ -626,7 +1114,7 @@ open_base_files ()
{
/* The order of files here matters very much. */
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",
"expr.h", "hard-reg-set.h", "basic-block.h", "cselib.h",
"insn-addr.h", "ssa.h", "optabs.h", "libfuncs.h",
......@@ -878,11 +1366,14 @@ struct flist {
static void output_escaped_param PARAMS ((outf_p , const char *, const char *,
const char *, const char *,
struct fileloc *));
static void output_mangled_typename PARAMS ((outf_p, type_p));
static void write_gc_structure_fields
PARAMS ((outf_p , type_p, const char *, const char *, options_p,
int, struct fileloc *, lang_bitmap, type_p));
static void write_gc_marker_routine_for_structure PARAMS ((type_p, type_p));
int, struct fileloc *, lang_bitmap, 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_enum_defn PARAMS ((type_p structures, type_p param_structs));
static void put_mangled_filename PARAMS ((outf_p , const char *));
static void finish_root_table PARAMS ((struct flist *flp, const char *pfx,
const char *tname, const char *lastname,
......@@ -911,15 +1402,70 @@ output_escaped_param (of, param, val, prev_val, oname, line)
for (p = param; *p; p++)
if (*p != '%')
oprintf (of, "%c", *p);
else if (*++p == 'h')
oprintf (of, "(%s)", val);
else if (*p == '0')
oprintf (of, "(*x)");
else if (*p == '1')
oprintf (of, "(%s)", prev_val);
else
error_at_line (line, "`%s' option contains bad escape %c%c",
oname, '%', *p);
else switch (*++p)
{
case 'h':
oprintf (of, "(%s)", val);
break;
case '0':
oprintf (of, "(*x)");
break;
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
......@@ -940,10 +1486,10 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
int indent;
struct fileloc *line;
lang_bitmap bitmap;
type_p param;
type_p * param;
{
pair_p f;
int tagcounter = -1;
int seen_default = 0;
if (! s->u.s.line.file)
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,
const char *tagexpr = NULL;
options_p oo;
tagcounter = ++gc_counter;
for (oo = opts; oo; oo = oo->next)
if (strcmp (oo->name, "desc") == 0)
tagexpr = (const char *)oo->info;
......@@ -968,29 +1513,26 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
error_at_line (line, "missing `desc' option");
}
oprintf (of, "%*s{\n", indent, "");
indent += 2;
oprintf (of, "%*sunsigned int tag%d = (", indent, "", tagcounter);
oprintf (of, "%*sswitch (", indent, "");
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)
{
const char *tagid = NULL;
const char *length = NULL;
const char *special = NULL;
int skip_p = 0;
int always_p = 0;
int default_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;
type_p t = f->type;
if (t->kind == TYPE_SCALAR
|| (t->kind == TYPE_ARRAY
&& t->u.a.p->kind == TYPE_SCALAR))
continue;
const char *dot = ".";
for (oo = f->opt; oo; oo = oo->next)
if (strcmp (oo->name, "length") == 0)
......@@ -1000,62 +1542,88 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
else if (strcmp (oo->name, "tag") == 0)
tagid = (const char *)oo->info;
else if (strcmp (oo->name, "special") == 0)
special = (const char *)oo->info;
;
else if (strcmp (oo->name, "skip") == 0)
skip_p = 1;
else if (strcmp (oo->name, "always") == 0)
always_p = 1;
else if (strcmp (oo->name, "desc") == 0 && UNION_P (t))
else if (strcmp (oo->name, "default") == 0)
default_p = 1;
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, "use_param") == 0)
use_param_p = 1;
else if (strncmp (oo->name, "use_param", 9) == 0
&& (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
error_at_line (&f->line, "unknown field option `%s'\n", oo->name);
if (skip_p)
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;
int arraycount = 0;
type_p nt = param[use_param_num];
for (t1 = t; t->kind == TYPE_ARRAY; t = t->u.a.p)
arraycount++;
for (; t->kind == TYPE_POINTER; t = t->u.p)
nt = create_pointer (nt);
while (arraycount-- > 0)
if (t->kind == TYPE_ARRAY)
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;
}
else if (s->kind == TYPE_UNION && ! always_p && tagid)
;
else
else if (s->kind != TYPE_UNION)
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
&& (t->kind != TYPE_POINTER
|| t->u.p->kind != TYPE_STRUCT))
error_at_line (&f->line,
"field `%s' has invalid option `maybe_undef_p'\n",
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);
continue;
}
oprintf (of, "%*sif (tag%d == (%s)) {\n", indent, "",
tagcounter, tagid);
indent += 2;
}
......@@ -1087,7 +1655,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
{
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,
&f->line, bitmap, param);
free (newval);
......@@ -1099,17 +1667,20 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
{
if (maybe_undef_p
&& t->u.p->u.s.line.file == NULL)
oprintf (of, "%*sif (%s.%s) abort();\n", indent, "",
val, f->name);
else if (UNION_OR_STRUCT_P (t->u.p))
oprintf (of, "%*sgt_ggc_m_%s (%s.%s);\n", indent, "",
t->u.p->u.s.tag, val, f->name);
else if (t->u.p->kind == TYPE_PARAM_STRUCT)
oprintf (of, "%*sgt_ggc_mm_%d%s_%s (%s.%s);\n", indent, "",
(int) strlen (t->u.p->u.param_struct.param->u.s.tag),
t->u.p->u.param_struct.param->u.s.tag,
t->u.p->u.param_struct.stru->u.s.tag,
val, f->name);
oprintf (of, "%*sif (%s%s%s) abort();\n", indent, "",
val, dot, f->name);
else if (UNION_OR_STRUCT_P (t->u.p)
|| t->u.p->kind == TYPE_PARAM_STRUCT)
{
oprintf (of, "%*sgt_ggc_m_", indent, "");
output_mangled_typename (of, t->u.p);
oprintf (of, " (");
if (needs_cast_p)
oprintf (of, "(%s %s *)",
UNION_P (t->u.p) ? "union" : "struct",
t->u.p->u.s.tag);
oprintf (of, "%s%s%s);\n", val, dot, f->name);
}
else
error_at_line (&f->line, "field `%s' is pointer to scalar",
f->name);
......@@ -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
|| t->u.p->kind == TYPE_STRING)
oprintf (of, "%*sggc_mark (%s.%s);\n", indent, "",
val, f->name);
oprintf (of, "%*sggc_mark (%s%s%s);\n", indent, "",
val, dot, f->name);
else
{
int loopcounter = ++gc_counter;
oprintf (of, "%*sif (%s.%s != NULL) {\n", indent, "",
val, f->name);
oprintf (of, "%*sif (%s%s%s != NULL) {\n", indent, "",
val, dot, f->name);
indent += 2;
oprintf (of, "%*ssize_t i%d;\n", indent, "", loopcounter);
oprintf (of, "%*sggc_set_mark (%s.%s);\n", indent, "",
val, f->name);
oprintf (of, "%*sggc_set_mark (%s%s%s);\n", indent, "",
val, dot, f->name);
oprintf (of, "%*sfor (i%d = 0; i%d < (size_t)(", indent, "",
loopcounter, loopcounter);
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,
{
char *newval;
newval = xasprintf ("%s.%s[i%d]", val, f->name,
newval = xasprintf ("%s%s%s[i%d]", val, dot, f->name,
loopcounter);
write_gc_structure_fields (of, t->u.p, newval, val,
f->opt, indent, &f->line,
......@@ -1150,10 +1721,14 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
break;
}
case TYPE_POINTER:
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->u.s.tag, val, f->name,
loopcounter);
if (UNION_OR_STRUCT_P (t->u.p->u.p)
|| t->u.p->u.p->kind == TYPE_PARAM_STRUCT)
{
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
error_at_line (&f->line,
"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,
oprintf (of, "%*s{\n", indent, "");
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++)
{
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,
}
if (ta->kind == TYPE_POINTER
&& (ta->u.p->kind == TYPE_STRUCT
|| ta->u.p->kind == TYPE_UNION))
&& (UNION_OR_STRUCT_P (ta->u.p)
|| ta->u.p->kind == TYPE_PARAM_STRUCT))
{
oprintf (of, "%*sgt_ggc_m_%s (%s.%s",
indent, "", ta->u.p->u.s.tag, val, f->name);
oprintf (of, "%*sgt_ggc_m_", indent, "");
output_mangled_typename (of, ta->u.p);
oprintf (of, " (%s%s%s", val, dot, f->name);
for (ta = t, i = 0;
ta->kind == TYPE_ARRAY;
ta = ta->u.a.p, i++)
......@@ -1251,7 +1816,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
len += sizeof ("[i_]") + 2*6;
newval = xmalloc (len);
sprintf (newval, "%s.%s", val, f->name);
sprintf (newval, "%s%s%s", val, dot, f->name);
for (ta = t, i = 0;
ta->kind == TYPE_ARRAY;
ta = ta->u.a.p, i++)
......@@ -1263,7 +1828,7 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
free (newval);
}
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, "");
else
error_at_line (&f->line,
......@@ -1275,16 +1840,6 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
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;
oprintf (of, "%*s}\n", indent, "");
break;
......@@ -1297,18 +1852,21 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
break;
}
if (s->kind == TYPE_UNION && ! always_p )
if (s->kind == TYPE_UNION)
{
oprintf (of, "%*sbreak;\n", indent, "");
indent -= 2;
oprintf (of, "%*s}\n", indent, "");
}
if (special)
error_at_line (&f->line, "unhandled special `%s'", special);
}
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, "");
indent -= 2;
}
}
......@@ -1316,36 +1874,96 @@ write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
enclosing PARAM_IS option. */
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 param;
type_p * param;
{
outf_p f;
if (param == NULL)
f = get_output_file_with_visibility (s->u.s.line.file);
else
f = get_output_file_with_visibility (param->u.s.line.file);
const char *fn = s->u.s.line.file;
int i;
const char *chain_next = NULL;
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");
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
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, "{\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,
chain_next == NULL ? "const " : "",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
oprintf (f, " if (! ggc_test_and_set_mark (x))\n");
oprintf (f, " return;\n");
if (chain_next != NULL)
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;
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);
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");
}
......@@ -1369,8 +1987,9 @@ write_gc_types (structures, param_structs)
&& s->u.s.line.file == NULL)
continue;
oprintf (header_file,
"#define gt_ggc_m_%s(X) do { \\\n", s->u.s.tag);
oprintf (header_file, "#define gt_ggc_m_");
output_mangled_typename (header_file, s);
oprintf (header_file, "(X) do { \\\n");
oprintf (header_file,
" if (X != NULL) gt_ggc_mx_%s (X);\\\n", s->u.s.tag);
oprintf (header_file,
......@@ -1410,31 +2029,22 @@ write_gc_types (structures, param_structs)
{
type_p ss;
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
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)
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;
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. */
oprintf (header_file,
"extern void gt_ggc_mm_%d%s_%s PARAMS ((void *));\n",
(int) strlen (param->u.s.tag), param->u.s.tag,
stru->u.s.tag);
oprintf (header_file, "extern void gt_ggc_m_");
output_mangled_typename (header_file, s);
oprintf (header_file, " PARAMS ((void *));\n");
if (stru->u.s.line.file == NULL)
{
......@@ -1447,13 +2057,48 @@ write_gc_types (structures, param_structs)
{
type_p ss;
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
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. */
static void
......@@ -1540,7 +2185,7 @@ finish_root_table (flp, pfx, lastname, tname, name)
if (bitmap & 1)
{
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)
}
else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
{
oprintf (f, " &gt_ggc_mm_%d%s_%s",
(int) strlen (tp->u.param_struct.param->u.s.tag),
tp->u.param_struct.param->u.s.tag,
tp->u.param_struct.stru->u.s.tag);
oprintf (f, " &gt_ggc_m_");
output_mangled_typename (f, tp);
}
else if (has_length
&& (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
......@@ -1724,6 +2367,10 @@ write_gc_roots (variables)
deletable_p = 1;
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
......@@ -1768,7 +2415,8 @@ write_gc_roots (variables)
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
oprintf (f, " if (ggc_test_and_set_mark (x))\n");
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,
"global `%s' has unsupported ** type",
......@@ -1776,7 +2424,9 @@ write_gc_roots (variables)
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
{
......@@ -1906,7 +2556,7 @@ write_gc_roots (variables)
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);
}
......@@ -1925,20 +2575,19 @@ main(argc, argv)
static struct fileloc pos = { __FILE__, __LINE__ };
unsigned j;
gen_rtx_next ();
srcdir_len = strlen (srcdir);
do_typedef ("CUMULATIVE_ARGS",
create_scalar_type ("CUMULATIVE_ARGS",
strlen ("CUMULATIVE_ARGS")),
&pos);
do_typedef ("REAL_VALUE_TYPE",
create_scalar_type ("REAL_VALUE_TYPE",
strlen ("REAL_VALUE_TYPE")),
&pos);
do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
do_scalar_typedef ("REAL_VALUE_TYPE", &pos);
do_scalar_typedef ("uint8", &pos);
do_scalar_typedef ("jword", &pos);
do_scalar_typedef ("JCF_u2", &pos);
do_typedef ("PTR", create_pointer (create_scalar_type ("void",
strlen ("void"))),
&pos);
do_typedef ("HARD_REG_SET", create_array (
create_scalar_type ("unsigned long", strlen ("unsigned long")),
"2"), &pos);
......@@ -1965,8 +2614,10 @@ main(argc, argv)
set_gc_used (variables);
open_base_files ();
write_enum_defn (structures, param_structs);
write_gc_types (structures, param_structs);
write_gc_roots (variables);
write_rtx_next ();
close_output_files ();
return (hit_error != 0);
......
......@@ -41,7 +41,7 @@ enum typekind {
typedef struct options {
struct options *next;
const char *name;
void *info;
const void *info;
} *options_p;
typedef struct pair *pair_p;
......@@ -57,6 +57,8 @@ struct pair {
options_p opt;
};
#define NUM_PARAM 10
/* A description of a type. */
struct type {
enum typekind kind;
......@@ -85,7 +87,7 @@ struct type {
} a;
struct {
type_p stru;
type_p param;
type_p param[NUM_PARAM];
struct fileloc line;
} param_struct;
} u;
......
......@@ -34,7 +34,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Statistics about the allocation. */
static ggc_statistics *ggc_stats;
static void ggc_mark_rtx_children_1 PARAMS ((rtx));
static int ggc_htab_delete PARAMS ((void **, void *));
/* Maintain global roots that are preserved during GC. */
......@@ -132,140 +131,6 @@ ggc_mark_roots ()
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. */
void *
ggc_alloc_cleared (size)
......
/* 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.
......@@ -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_rtx_children PARAMS ((struct rtx_def *));
/* If EXPR is not NULL and previously unmarked, mark it and evaluate
to true. Otherwise evaluate to false. */
#define ggc_test_and_set_mark(EXPR) \
((EXPR) != NULL && ((void *) (EXPR)) != (void *) 1 && ! ggc_set_mark (EXPR))
#define ggc_mark_rtx(EXPR) \
do { \
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_rtx gt_ggc_m_7rtx_def
#define ggc_mark_tree gt_ggc_m_9tree_node
#define ggc_mark(EXPR) \
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>
* jcf-parse.c (get_constant): Runtime check for IEEE format;
......
......@@ -693,7 +693,8 @@ struct lang_identifier GTY(())
/* The resulting tree type. */
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"),
desc ("tree_node_structure (&%h)")))
......
......@@ -186,6 +186,7 @@ const char * const rtx_format[NUM_RTX_CODE] = {
"u" a pointer to another insn
prints the uid of the insn.
"b" is a pointer to a bitmap header.
"B" is a basic block pointer.
"t" is a tree pointer. */
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
......
......@@ -62,6 +62,8 @@ extern const char * const rtx_format[NUM_RTX_CODE];
extern const char rtx_class[NUM_RTX_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
relative to which the offsets are calculated, as explained in rtl.def. */
......@@ -103,7 +105,7 @@ typedef struct mem_attrs GTY(())
/* Common union for an element of an rtx. */
typedef union rtunion_def
union rtunion_def
{
HOST_WIDE_INT rtwint;
int rtint;
......@@ -118,11 +120,13 @@ typedef union rtunion_def
tree rttree;
struct basic_block_def *bb;
mem_attrs *rtmem;
} rtunion;
};
typedef union rtunion_def rtunion;
/* 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. */
ENUM_BITFIELD(rtx_code) code: 16;
......@@ -198,11 +202,29 @@ struct rtx_def
/* The first element of the operands of this rtx.
The number of operands and their types are controlled
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
/* 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 GET_CODE(RTX) ((enum rtx_code) (RTX)->code)
......
......@@ -889,7 +889,7 @@ struct tree_exp GTY(())
struct tree_common common;
int complexity;
tree GTY ((special ("tree_exp"),
length ("TREE_CODE_LENGTH (TREE_CODE ((tree) &%h))")))
desc ("TREE_CODE ((tree) &%0)")))
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