summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-16 18:33:23 +0000
committergeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-16 18:33:23 +0000
commitc849df63447c7b03c27d991e60a26e9b98b57013 (patch)
treec61dabe0ee2f12a433921e41d3b1799e3b26b2f5
parent7d89a8eb42b1ab1ce5a769e32eec2e0a4eefc081 (diff)
downloadgcc-c849df63447c7b03c27d991e60a26e9b98b57013.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@57206 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog87
-rw-r--r--gcc/Makefile.in3
-rw-r--r--gcc/c-tree.h3
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/doc/gty.texi42
-rw-r--r--gcc/f/ChangeLog4
-rw-r--r--gcc/f/com.c3
-rw-r--r--gcc/gengtype-lex.l5
-rw-r--r--gcc/gengtype-yacc.y9
-rw-r--r--gcc/gengtype.c1081
-rw-r--r--gcc/gengtype.h6
-rw-r--r--gcc/ggc-common.c135
-rw-r--r--gcc/ggc.h14
-rw-r--r--gcc/java/ChangeLog4
-rw-r--r--gcc/java/java-tree.h3
-rw-r--r--gcc/rtl.c1
-rw-r--r--gcc/rtl.h30
-rw-r--r--gcc/tree.h2
19 files changed, 1054 insertions, 385 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9efa47f3cff..47c56942e7e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,90 @@
+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.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index df9ba312cc3..d95232419f6 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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)
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 531cc284559..159c235224e 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -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)")))
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a4ddb5a6dc8..4a480412cf5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,7 @@
+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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 96c615d5643..bbfdd3a889c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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"),
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index cbd9caa516c..e0d9a33cde6 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -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
diff --git a/gcc/f/ChangeLog b/gcc/f/ChangeLog
index 658babde4cb..e71c8c72e32 100644
--- a/gcc/f/ChangeLog
+++ b/gcc/f/ChangeLog
@@ -1,3 +1,7 @@
+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_
diff --git a/gcc/f/com.c b/gcc/f/com.c
index 5a6bc7e8d28..931858afac1 100644
--- a/gcc/f/com.c
+++ b/gcc/f/com.c
@@ -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)")))
diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l
index bd848a7da0d..91cdde29580 100644
--- a/gcc/gengtype-lex.l
+++ b/gcc/gengtype-lex.l
@@ -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}?")" {
diff --git a/gcc/gengtype-yacc.y b/gcc/gengtype-yacc.y
index 3ff92d345ef..87837b407be 100644
--- a/gcc/gengtype-yacc.y
+++ b/gcc/gengtype-yacc.y
@@ -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 ')'
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index f180a1fd41e..9ec9863de8c 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -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);
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index 20e496da05c..0c23d95f44a 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -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;
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index dcff4614001..2674cec52a1 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -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)
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 0cd87f4dad9..b672cbecfaf 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -1,5 +1,5 @@
/* 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 { \
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index ac1b565950f..e1eb6f14558 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,7 @@
+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;
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index a08ec5830fc..324156d2336 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -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)")))
diff --git a/gcc/rtl.c b/gcc/rtl.c
index 7b6c0a1f9bd..292dcc35184 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -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 ,
diff --git a/gcc/rtl.h b/gcc/rtl.h
index d27b9a2d41c..0fd7e6775b9 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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)
diff --git a/gcc/tree.h b/gcc/tree.h
index 856a18d517e..6eab3307c8c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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];
};