@@ -33,19 +33,19 @@ along with GCC; see the file COPYING3. If not see
typedef HOST_WIDEST_INT gcov_type;
/* Control flow edge information. */
-struct GTY(()) edge_def {
+struct GTY((user)) edge_def {
/* The two blocks at the ends of the edge. */
basic_block src;
basic_block dest;
/* Instructions queued on the edge. */
union edge_def_insns {
- gimple_seq GTY ((tag ("true"))) g;
- rtx GTY ((tag ("false"))) r;
- } GTY ((desc ("current_ir_type () == IR_GIMPLE"))) insns;
+ gimple_seq g;
+ rtx r;
+ } insns;
/* Auxiliary info specific to a pass. */
- PTR GTY ((skip (""))) aux;
+ PTR aux;
/* Location of any goto implicit in the edge and associated BLOCK. */
tree goto_block;
@@ -65,6 +65,11 @@ DEF_VEC_P(edge);
DEF_VEC_ALLOC_P(edge,gc);
DEF_VEC_ALLOC_P(edge,heap);
+/* Garbage collection and PCH support for edge_def. */
+extern void gt_ggc_mx (edge_def *e);
+extern void gt_pch_nx (edge_def *e);
+extern void gt_pch_nx (edge_def *e, gt_pointer_operator, void *);
+
/* Masks for edge.flags. */
#define DEF_EDGE_FLAG(NAME,IDX) EDGE_##NAME = 1 << IDX ,
enum cfg_edge_flags {
@@ -196,5 +196,9 @@ enum memmodel
/* Suppose that higher bits are target dependant. */
#define MEMMODEL_MASK ((1<<16)-1)
+/* Support for user-provided GGC and PCH markers. The first parameter
+ is a pointer to a pointer, the second a cookie. */
+typedef void (*gt_pointer_operator) (void *, void *);
+
#endif /* coretypes.h */
@@ -68,6 +68,7 @@ These don't need to be marked.
@menu
* GTY Options:: What goes inside a @code{GTY(())}.
* GGC Roots:: Making global variables GGC roots.
+* User GC:: Adding user-provided GC marking routines.
* Files:: How the generated files work.
* Invoking the garbage collector:: How to invoke the garbage collector.
* Troubleshooting:: When something does not work as expected.
@@ -440,8 +441,128 @@ The @code{special} option is used to mark types that have to be dealt
with by special case machinery. The parameter is the name of the
special case. See @file{gengtype.c} for further details. Avoid
adding new special cases unless there is no other alternative.
+
+@findex user
+@item user
+
+The @code{user} option indicates that the code to mark structure
+fields is completely handled by user-provided routines. Section
+@ref{User GC} for details on what functions need to be provided.
@end table
+@node User GC
+@section Support for user-provided GC marking routines
+@cindex user gc
+The garbage collector supports types for which no automatic marking
+code is generated. For these types, the user is required to provide
+three functions: one to act as a marker for garbage collection, and
+two functions to act as marker and pointer walking for pre-compiled
+headers.
+
+Given a structure @code{struct GTY((user)) my_struct}, the following functions
+should be defined to mark @code{my_struct}:
+
+@smallexample
+void gt_ggc_mx (my_struct *p)
+@{
+ /* This marks field 'fld'. */
+ gt_ggc_mx (p->fld);
+@}
+
+void gt_pch_nx (my_struct *p)
+@{
+ /* This marks field 'fld'. */
+ gt_pch_nx (tp->fld);
+@}
+
+void gt_pch_nx (my_struct *p, gt_pointer_operator op, void *cookie)
+@{
+ /* For every field 'fld', call the given pointer operator. */
+ op (&(tp->fld), cookie);
+@}
+@end smallexample
+
+In general, each marker @code{M} should call @code{M} for every
+pointer field in the structure. Fields that are not allocated in GC
+or are not pointers can be ignored.
+
+For embedded lists (e.g., structures with a @code{next} or @code{prev}
+pointer), the marker must follow the chain and mark every element in
+it.
+
+Note that the rules for the pointer walker @code{gt_pch_nx (my_struct
+*, gt_pointer_operator, void *)} are slightly different. In this
+case, the operation @code{op} must be applied to the @emph{address} of
+every pointer field.
+
+@section User-provided marking routines for template types
+When a template type @code{TP} is marked with @code{GTY}, all
+instances of that type are considered user-provided types. This means
+that the individual instances of @code{TP} do not need to marked with
+@code{GTY}. The user needs to provide template functions to mark all
+the fields of the type.
+
+The following code snippets represent all the functions that need to
+be provided. Note that type @code{TP} may reference to more than one
+type. In these snippets, there is only one type @code{T}, but there
+could be more.
+
+@smallexample
+template<typename T>
+void gt_ggc_mx (TP<T> *tp)
+@{
+ extern void gt_ggc_mx (T&);
+
+ /* This marks field 'fld' of type 'T'. */
+ gt_ggc_mx (tp->fld);
+@}
+
+template<typename T>
+void gt_pch_nx (TP<T> *tp)
+@{
+ extern void gt_pch_nx (T&);
+
+ /* This marks field 'fld' of type 'T'. */
+ gt_pch_nx (tp->fld);
+@}
+
+template<typename T>
+void gt_pch_nx (TP<T *> *tp, gt_pointer_operator op, void *cookie)
+@{
+ /* For every field 'fld' of 'tp' with type 'T *', call the given
+ pointer operator. */
+ op (&(tp->fld), cookie);
+@}
+
+template<typename T>
+void gt_pch_nx (TP<T> *tp, gt_pointer_operator, void *cookie)
+@{
+ extern void gt_pch_nx (T *, gt_pointer_operator, void *);
+
+ /* For every field 'fld' of 'tp' with type 'T', call the pointer
+ walker for all the fields of T. */
+ gt_pch_nx (&(tp->fld), op, cookie);
+@}
+@end smallexample
+
+Support for user-defined types is currently limited. The following
+restrictions apply:
+
+@enumerate
+@item Type @code{TP} and all the argument types @code{T} must be
+marked with @code{GTY}.
+
+@item Type @code{TP} can only have type names in its argument list.
+
+@item The pointer walker functions are different for @code{TP<T>} and
+@code{TP<T *>}. In the case of @code{TP<T>}, references to
+@code{T} must be handled by calling @code{gt_pch_nx} (which
+will, in turn, walk all the pointers inside fields of @code{T}).
+In the case of @code{TP<T *>}, references to @code{T *} must be
+handled by calling the @code{op} function on the address of the
+pointer (see the code snippets above).
+@end enumerate
+
@node GGC Roots
@section Marking Roots for the Garbage Collector
@cindex roots, marking
@@ -1,6 +1,6 @@
/* -*- indented-text -*- */
/* Process source files and output type information.
- Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+ Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2012
Free Software Foundation, Inc.
This file is part of GCC.
@@ -91,19 +91,6 @@ EOID [^[:alnum:]_]
BEGIN(in_struct);
return STATIC;
}
-
-^{HWS}DEF_VEC_[OP]/{EOID} {
- BEGIN(in_struct);
- return DEFVEC_OP;
-}
-^{HWS}DEF_VEC_I/{EOID} {
- BEGIN(in_struct);
- return DEFVEC_I;
-}
-^{HWS}DEF_VEC_ALLOC_[IOP]/{EOID} {
- BEGIN(in_struct);
- return DEFVEC_ALLOC;
-}
}
<in_struct>{
@@ -121,6 +108,7 @@ EOID [^[:alnum:]_]
"enum"/{EOID} { return ENUM; }
"ptr_alias"/{EOID} { return PTR_ALIAS; }
"nested_ptr"/{EOID} { return NESTED_PTR; }
+"user"/{EOID} { return USER_GTY; }
[0-9]+ { return NUM; }
"param"[0-9]*"_is"/{EOID} {
*yylval = XDUPVAR (const char, yytext, yyleng, yyleng+1);
@@ -1,5 +1,5 @@
/* Process source files and output type information.
- Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2010, 2012 Free Software Foundation, Inc.
This file is part of GCC.
@@ -77,9 +77,6 @@ static const char *const token_names[] = {
"struct",
"enum",
"VEC",
- "DEF_VEC_[OP]",
- "DEF_VEC_I",
- "DEF_VEC_ALLOC_[IOP]",
"...",
"ptr_alias",
"nested_ptr",
@@ -212,28 +209,70 @@ string_seq (void)
return s1;
}
-/* typedef_name: either an ID, or VEC(x,y) which is translated to VEC_x_y.
- Use only where VEC(x,y) is legitimate, i.e. in positions where a
- typedef name may appear. */
+
+/* The caller has detected a template declaration that starts
+ with TMPL_NAME. Parse up to the closing '>'. This recognizes
+ simple template declarations of the form ID<ID1,ID2,...,IDn>.
+ It does not try to parse anything more sophisticated than that.
+
+ Returns the template declaration string "ID<ID1,ID2,...,IDn>". */
+
+static const char *
+require_template_declaration (const char *tmpl_name)
+{
+ char *str;
+
+ /* Recognize the opening '<'. */
+ require ('<');
+ str = concat (tmpl_name, "<", (char *) 0);
+
+ /* Read the comma-separated list of identifiers. */
+ while (token () != '>')
+ {
+ const char *id = require2 (ID, ',');
+ if (id == NULL)
+ id = ",";
+ str = concat (str, id, (char *) 0);
+ }
+
+ /* Recognize the closing '>'. */
+ require ('>');
+ str = concat (str, ">", (char *) 0);
+
+ return str;
+}
+
+
+/* typedef_name: either an ID, or VEC(x,y), or a template type
+ specification of the form ID<t1,t2,...,tn>.
+
+ FIXME cxx-conversion. VEC(x,y) is currently translated to the
+ template 'vec_t<x>'. This is to support the transition to C++ and
+ avoid re-writing all the 'VEC(x,y)' declarations in the code. This
+ needs to be fixed when the branch is merged into trunk. */
+
static const char *
typedef_name (void)
{
if (token () == VEC_TOKEN)
{
- const char *c1, *c2, *r;
+ const char *c1, *r;
advance ();
require ('(');
c1 = require2 (ID, SCALAR);
require (',');
- c2 = require (ID);
+ require (ID);
require (')');
- r = concat ("VEC_", c1, "_", c2, (char *) 0);
+ r = concat ("vec_t<", c1, ">", (char *) 0);
free (CONST_CAST (char *, c1));
- free (CONST_CAST (char *, c2));
return r;
}
+
+ const char *id = require (ID);
+ if (token () == '<')
+ return require_template_declaration (id);
else
- return require (ID);
+ return id;
}
/* Absorb a sequence of tokens delimited by balanced ()[]{}. */
@@ -460,6 +499,10 @@ option (options_p prev)
advance ();
return nestedptr_optvalue (prev);
+ case USER_GTY:
+ advance ();
+ return create_string_option (prev, "user", "");
+
default:
parse_error ("expected an option keyword, have %s", print_cur_token ());
advance ();
@@ -694,6 +737,18 @@ struct_field_seq (void)
return nreverse_pairs (f);
}
+/* Return true if OPTS contain the option named STR. */
+
+static bool
+opts_have (options_p opts, const char *str)
+{
+ for (options_p opt = opts; opt; opt = opt->next)
+ if (strcmp (opt->name, str) == 0)
+ return true;
+ return false;
+}
+
+
/* This is called type(), but what it parses (sort of) is what C calls
declaration-specifiers and specifier-qualifier-list:
@@ -735,7 +790,7 @@ type (options_p *optsp, bool nested)
GTY_BEFORE_ID,
GTY_AFTER_ID
} is_gty = NO_GTY;
- bool is_union = (token () == UNION);
+ enum typekind kind = (token () == UNION) ? TYPE_UNION : TYPE_STRUCT;
advance ();
/* Top-level structures that are not explicitly tagged GTY(())
@@ -766,6 +821,7 @@ type (options_p *optsp, bool nested)
if (is_gty)
{
+ bool is_user_gty = opts_have (opts, "user");
if (token () == '{')
{
pair_p fields;
@@ -773,17 +829,28 @@ type (options_p *optsp, bool nested)
if (is_gty == GTY_AFTER_ID)
parse_error ("GTY must be specified before identifier");
- advance ();
- fields = struct_field_seq ();
- require ('}');
- return new_structure (s, is_union, &lexer_line, fields, opts);
+ if (!is_user_gty)
+ {
+ advance ();
+ fields = struct_field_seq ();
+ require ('}');
+ }
+ else
+ {
+ /* Do not look inside user defined structures. */
+ fields = NULL;
+ kind = TYPE_USER_STRUCT;
+ consume_balanced ('{', '}');
+ }
+
+ return new_structure (s, kind, &lexer_line, fields, opts);
}
}
else if (token () == '{')
consume_balanced ('{', '}');
if (opts)
*optsp = opts;
- return find_structure (s, is_union);
+ return find_structure (s, kind);
}
case ENUM:
@@ -891,55 +958,6 @@ extern_or_static (void)
}
}
-/* Definition of a generic VEC structure:
-
- 'DEF_VEC_[IPO]' '(' id ')' ';'
-
- Scalar VECs require slightly different treatment than otherwise -
- that's handled in note_def_vec, we just pass it along.*/
-static void
-def_vec (void)
-{
- bool is_scalar = (token () == DEFVEC_I);
- const char *type;
-
- require2 (DEFVEC_OP, DEFVEC_I);
- require ('(');
- type = require2 (ID, SCALAR);
- require (')');
- require (';');
-
- if (!type)
- return;
-
- note_def_vec (type, is_scalar, &lexer_line);
- note_def_vec_alloc (type, "none", &lexer_line);
-}
-
-/* Definition of an allocation strategy for a VEC structure:
-
- 'DEF_VEC_ALLOC_[IPO]' '(' id ',' id ')' ';'
-
- For purposes of gengtype, this just declares a wrapper structure. */
-static void
-def_vec_alloc (void)
-{
- const char *type, *astrat;
-
- require (DEFVEC_ALLOC);
- require ('(');
- type = require2 (ID, SCALAR);
- require (',');
- astrat = require (ID);
- require (')');
- require (';');
-
- if (!type || !astrat)
- return;
-
- note_def_vec_alloc (type, astrat, &lexer_line);
-}
-
/* Parse the file FNAME for GC-relevant declarations and definitions.
This is the only entry point to this file. */
void
@@ -964,15 +982,6 @@ parse_file (const char *fname)
typedef_decl ();
break;
- case DEFVEC_OP:
- case DEFVEC_I:
- def_vec ();
- break;
-
- case DEFVEC_ALLOC:
- def_vec_alloc ();
- break;
-
case EOF_TOKEN:
goto eof;
@@ -51,6 +51,7 @@ type_lineloc (const_type_p ty)
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_LANG_STRUCT:
+ case TYPE_USER_STRUCT:
return CONST_CAST (struct fileloc*, &ty->u.s.line);
case TYPE_PARAM_STRUCT:
return CONST_CAST (struct fileloc*, &ty->u.param_struct.line);
@@ -798,6 +799,22 @@ write_state_struct_type (type_p current)
write_state_type (current->u.s.lang_struct);
}
+/* Write a GTY user-defined struct type. */
+static void
+write_state_user_struct_type (type_p current)
+{
+ DBGPRINTF ("user_struct type @ %p #%d '%s'", (void *) current,
+ current->state_number, current->u.s.tag);
+ fprintf (state_file, "user_struct ");
+ write_state_common_type_content (current);
+ if (current->u.s.tag != NULL)
+ write_state_a_string (current->u.s.tag);
+ else
+ fprintf (state_file, "nil");
+ write_state_fileloc (type_lineloc (current));
+ write_state_fields (current->u.s.fields);
+}
+
/* write a GTY union type. */
static void
write_state_union_type (type_p current)
@@ -828,7 +845,7 @@ write_state_lang_struct_type (type_p current)
DBGPRINTF ("homonymous #%d hty @ %p #%d '%s'", nbhomontype,
(void *) hty, hty->state_number, hty->u.s.tag);
/* Every member of the homonymous list should have the same tag. */
- gcc_assert (UNION_OR_STRUCT_P (hty));
+ gcc_assert (union_or_struct_p (hty));
gcc_assert (hty->u.s.lang_struct == current);
if (!homoname)
homoname = hty->u.s.tag;
@@ -947,6 +964,9 @@ write_state_type (type_p current)
case TYPE_STRUCT:
write_state_struct_type (current);
break;
+ case TYPE_USER_STRUCT:
+ write_state_user_struct_type (current);
+ break;
case TYPE_UNION:
write_state_union_type (current);
break;
@@ -1365,6 +1385,42 @@ read_state_struct_type (type_p type)
}
+/* Read a GTY-ed user-provided struct TYPE. */
+
+static void
+read_state_user_struct_type (type_p type)
+{
+ struct state_token_st *t0;
+
+ type->kind = TYPE_USER_STRUCT;
+ read_state_common_type_content (type);
+ t0 = peek_state_token (0);
+ if (state_token_kind (t0) == STOK_STRING)
+ {
+ if (state_token_is_name (t0, "nil"))
+ {
+ type->u.s.tag = NULL;
+ DBGPRINTF ("read anonymous struct type @%p #%d",
+ (void *) type, type->state_number);
+ }
+ else
+ {
+ type->u.s.tag = xstrdup (t0->stok_un.stok_string);
+ DBGPRINTF ("read struct type @%p #%d '%s'",
+ (void *) type, type->state_number, type->u.s.tag);
+ }
+
+ next_state_tokens (1);
+ read_state_fileloc (&(type->u.s.line));
+ read_state_fields (&(type->u.s.fields));
+ }
+ else
+ {
+ fatal_reading_state (t0, "Bad tag in user-struct type");
+ }
+}
+
+
/* Read a GTY-ed union type. */
static void
read_state_union_type (type_p type)
@@ -1655,6 +1711,12 @@ read_state_type (type_p *current)
next_state_tokens (1);
read_state_array_type (*current);
}
+ else if (state_token_is_name (t0, "user_struct"))
+ {
+ *current = XCNEW (struct type);
+ next_state_tokens (1);
+ read_state_user_struct_type (*current);
+ }
else
fatal_reading_state (t0, "bad type in (!type");
}
@@ -1,5 +1,6 @@
/* Process source files and output type information.
- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+ 2012
Free Software Foundation, Inc.
This file is part of GCC.
@@ -89,6 +90,10 @@ static const char *get_file_realbasename (const input_file *);
static int get_prefix_langdir_index (const char *);
static const char *get_file_langdir (const input_file *);
+
+static void dump_pair (int indent, pair_p p);
+static void dump_type (int indent, type_p p);
+static void dump_type_list (int indent, type_p p);
/* Nonzero iff an error has occurred. */
@@ -166,6 +171,7 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
int nb_types = 0, nb_scalar = 0, nb_string = 0;
int nb_struct = 0, nb_union = 0, nb_array = 0, nb_pointer = 0;
int nb_lang_struct = 0, nb_param_struct = 0;
+ int nb_user_struct = 0;
type_p p = NULL;
for (p = t; p; p = p->next)
{
@@ -181,6 +187,9 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
case TYPE_STRUCT:
nb_struct++;
break;
+ case TYPE_USER_STRUCT:
+ nb_user_struct++;
+ break;
case TYPE_UNION:
nb_union++;
break;
@@ -211,6 +220,8 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
if (nb_lang_struct > 0 || nb_param_struct > 0)
fprintf (stderr, "@@%%@@ %d lang_structs, %d param_structs\n",
nb_lang_struct, nb_param_struct);
+ if (nb_user_struct > 0)
+ fprintf (stderr, "@@%%@@ %d user_structs\n", nb_user_struct);
fprintf (stderr, "\n");
}
#endif /* ENABLE_CHECKING */
@@ -539,6 +550,50 @@ do_scalar_typedef (const char *s, struct fileloc *pos)
do_typedef (s, &scalar_nonchar, pos);
}
+
+/* Define TYPE_NAME to be a user defined type at location POS. */
+
+static type_p
+create_user_defined_type (const char *type_name, struct fileloc *pos)
+{
+ type_p ty = find_structure (type_name, TYPE_USER_STRUCT);
+ ty->u.s.line = *pos;
+ ty->u.s.bitmap = get_lang_bitmap (pos->file);
+ do_typedef (type_name, ty, pos);
+
+ /* If TYPE_NAME specifies a template, create references to the types in the
+ template by preteding that each type is a field of TY. This is needed to
+ make sure that the types referenced by the template are marked as used. */
+ char *str = xstrdup (type_name);
+ char *open_bracket = strchr (str, '<');
+ if (open_bracket)
+ {
+ /* We only accept simple template declarations (see
+ require_template_declaration), so we only need to parse a
+ comma-separated list of strings, implicitly assumed to
+ be type names. */
+ char *arg = open_bracket + 1;
+ char *type_id = strtok (arg, ",>");
+ pair_p fields = 0;
+ while (type_id)
+ {
+ /* Create a new field for every type found inside the template
+ parameter list. */
+ const char *field_name = xstrdup (type_id);
+ type_p arg_type = resolve_typedef (field_name, pos);
+ fields = create_field_at (fields, arg_type, field_name, 0, pos);
+ type_id = strtok (0, ",>");
+ }
+
+ /* Associate the field list to TY. */
+ ty->u.s.fields = fields;
+ }
+ free (str);
+
+ return ty;
+}
+
+
/* Return the type previously defined for S. Use POS to report errors. */
type_p
@@ -548,20 +603,30 @@ resolve_typedef (const char *s, struct fileloc *pos)
for (p = typedefs; p != NULL; p = p->next)
if (strcmp (p->name, s) == 0)
return p->type;
- error_at_line (pos, "unidentified type `%s'", s);
- return &scalar_nonchar; /* treat as "int" */
+
+ /* If we did not find a typedef registered, assume this is a name
+ for a user-defined type which will need to provide its own
+ marking functions.
+
+ FIXME cxx-conversion. Emit an error once explicit annotations
+ for marking user types are implemented. */
+ return create_user_defined_type (s, pos);
}
-/* Create and return a new structure with tag NAME (or a union iff
- ISUNION is nonzero), at POS with fields FIELDS and options O. */
+/* Create and return a new structure with tag NAME at POS with fields
+ FIELDS and options O. The KIND of structure must be one of
+ TYPE_STRUCT, TYPE_UNION or TYPE_USER_STRUCT. */
type_p
-new_structure (const char *name, int isunion, struct fileloc *pos,
+new_structure (const char *name, enum typekind kind, struct fileloc *pos,
pair_p fields, options_p o)
{
type_p si;
type_p s = NULL;
lang_bitmap bitmap = get_lang_bitmap (pos->file);
+ bool isunion = (kind == TYPE_UNION);
+
+ gcc_assert (union_or_struct_p (kind));
for (si = structures; si != NULL; si = si->next)
if (strcmp (name, si->u.s.tag) == 0 && UNION_P (si) == isunion)
@@ -621,7 +686,7 @@ new_structure (const char *name, int isunion, struct fileloc *pos,
error_at_line (&s->u.s.line, "previous definition here");
}
- s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
+ s->kind = kind;
s->u.s.tag = name;
s->u.s.line = *pos;
s->u.s.fields = fields;
@@ -633,14 +698,18 @@ new_structure (const char *name, int isunion, struct fileloc *pos,
return s;
}
-/* Return the previously-defined structure with tag NAME (or a union
- iff ISUNION is nonzero), or a new empty structure or union if none
- was defined previously. */
+/* Return the previously-defined structure or union with tag NAME,
+ or a new empty structure or union if none was defined previously.
+ The KIND of structure must be one of TYPE_STRUCT, TYPE_UNION or
+ TYPE_USER_STRUCT. */
type_p
-find_structure (const char *name, int isunion)
+find_structure (const char *name, enum typekind kind)
{
type_p s;
+ bool isunion = (kind == TYPE_UNION);
+
+ gcc_assert (union_or_struct_p (kind));
for (s = structures; s != NULL; s = s->next)
if (strcmp (name, s->u.s.tag) == 0 && UNION_P (s) == isunion)
@@ -651,7 +720,7 @@ find_structure (const char *name, int isunion)
s->next = structures;
s->state_number = -type_count;
structures = s;
- s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
+ s->kind = kind;
s->u.s.tag = name;
structures = s;
return s;
@@ -851,7 +920,7 @@ create_optional_field_ (pair_p next, type_p type, const char *name,
union_fields->opt =
create_string_option (union_fields->opt, "tag", "1");
union_type =
- new_structure (xasprintf ("%s_%d", "fake_union", id++), 1,
+ new_structure (xasprintf ("%s_%d", "fake_union", id++), TYPE_UNION,
&lexer_line, union_fields, NULL);
/* Create the field and give it the new fake union type. Add a "desc"
@@ -993,16 +1062,16 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
nodot = create_string_option (NULL, "dot", "");
- 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));
+ rtx_tp = create_pointer (find_structure ("rtx_def", TYPE_STRUCT));
+ rtvec_tp = create_pointer (find_structure ("rtvec_def", TYPE_STRUCT));
+ tree_tp = create_pointer (find_structure ("tree_node", TYPE_UNION));
+ mem_attrs_tp = create_pointer (find_structure ("mem_attrs", TYPE_STRUCT));
reg_attrs_tp =
- create_pointer (find_structure ("reg_attrs", 0));
+ create_pointer (find_structure ("reg_attrs", TYPE_STRUCT));
basic_block_tp =
- create_pointer (find_structure ("basic_block_def", 0));
+ create_pointer (find_structure ("basic_block_def", TYPE_STRUCT));
constant_tp =
- create_pointer (find_structure ("constant_descriptor_rtx", 0));
+ create_pointer (find_structure ("constant_descriptor_rtx", TYPE_STRUCT));
scalar_tp = &scalar_nonchar; /* rtunion int */
{
@@ -1042,7 +1111,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
note_flds->opt =
create_string_option (nodot, "tag", note_insn_name[c]);
}
- note_union_tp = new_structure ("rtx_def_note_subunion", 1,
+ note_union_tp = new_structure ("rtx_def_note_subunion", TYPE_UNION,
&lexer_line, note_flds, NULL);
}
/* Create a type to represent the various forms of SYMBOL_REF_DATA. */
@@ -1052,7 +1121,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
sym_flds->opt = create_string_option (nodot, "default", "");
sym_flds = create_field (sym_flds, constant_tp, "rt_constant");
sym_flds->opt = create_string_option (nodot, "tag", "1");
- symbol_union_tp = new_structure ("rtx_def_symbol_subunion", 1,
+ symbol_union_tp = new_structure ("rtx_def_symbol_subunion", TYPE_UNION,
&lexer_line, sym_flds, NULL);
}
for (i = 0; i < NUM_RTX_CODE; i++)
@@ -1185,14 +1254,15 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
{
/* Add the "block_sym" field if SYMBOL_REF_HAS_BLOCK_INFO_P
holds. */
- type_p field_tp = find_structure ("block_symbol", 0);
+ type_p field_tp = find_structure ("block_symbol", TYPE_STRUCT);
subfields
= create_optional_field (subfields, field_tp, "block_sym",
"SYMBOL_REF_HAS_BLOCK_INFO_P (&%0)");
}
sname = xasprintf ("rtx_def_%s", rtx_name[i]);
- substruct = new_structure (sname, 0, &lexer_line, subfields, NULL);
+ substruct = new_structure (sname, TYPE_STRUCT, &lexer_line, subfields,
+ NULL);
ftag = xstrdup (rtx_name[i]);
for (nmindex = 0; nmindex < strlen (ftag); nmindex++)
@@ -1200,7 +1270,8 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
flds = create_field (flds, substruct, "");
flds->opt = create_string_option (nodot, "tag", ftag);
}
- return new_structure ("rtx_def_subunion", 1, &lexer_line, flds, nodot);
+ return new_structure ("rtx_def_subunion", TYPE_UNION, &lexer_line, flds,
+ nodot);
}
/* Handle `special("tree_exp")'. This is a special case for
@@ -1229,7 +1300,8 @@ adjust_field_tree_exp (type_p t, options_p opt ATTRIBUTE_UNUSED)
"TREE_OPERAND_LENGTH ((tree) &%0)");
flds->opt = create_string_option (flds->opt, "default", "");
- return new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot);
+ return new_structure ("tree_exp_subunion", TYPE_UNION, &lexer_line, flds,
+ nodot);
}
/* Perform any special processing on a type T, about to become the type
@@ -1275,8 +1347,8 @@ adjust_field_type (type_p t, options_p opt)
{
int num = ISDIGIT (opt->name[5]) ? opt->name[5] - '0' : 0;
- if (!UNION_OR_STRUCT_P (t)
- && (t->kind != TYPE_POINTER || !UNION_OR_STRUCT_P (t->u.p)))
+ 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",
@@ -1369,6 +1441,7 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
{
case TYPE_STRUCT:
case TYPE_UNION:
+ case TYPE_USER_STRUCT:
{
pair_p f;
int dummy;
@@ -1468,7 +1541,7 @@ static outf_p
create_file (const char *name, const char *oname)
{
static const char *const hdr[] = {
- " Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.\n",
+ " Copyright (C) 2004, 2007, 2009, 2012 Free Software Foundation, Inc.\n",
"\n",
"This file is part of GCC.\n",
"\n",
@@ -2176,7 +2249,6 @@ close_output_files (void)
for (of = output_files; of; of = of->next)
{
-
if (!is_file_equal (of))
{
FILE *newfile = NULL;
@@ -2303,9 +2375,38 @@ struct walk_type_data
bool fn_wants_lvalue;
bool in_record_p;
int loopcounter;
+ bool in_ptr_field;
bool have_this_obj;
};
+
+/* Given a string TYPE_NAME, representing a C++ typename, return a valid
+ pre-processor identifier to use in a #define directive. This replaces
+ special characters used in C++ identifiers like '>', '<' and ':' with
+ '_'.
+
+ If no C++ special characters are found in TYPE_NAME, return
+ TYPE_NAME. Otherwise, return a copy of TYPE_NAME with the special
+ characters replaced with '_'. In this case, the caller is
+ responsible for freeing the allocated string. */
+
+static const char *
+filter_type_name (const char *type_name)
+{
+ if (strchr (type_name, '<') || strchr (type_name, ':'))
+ {
+ size_t i;
+ char *s = xstrdup (type_name);
+ for (i = 0; i < strlen (s); i++)
+ if (s[i] == '<' || s[i] == '>' || s[i] == ':')
+ s[i] = '_';
+ return s;
+ }
+ else
+ return type_name;
+}
+
+
/* Print a mangled name representing T to OF. */
static void
@@ -2332,8 +2433,14 @@ output_mangled_typename (outf_p of, const_type_p t)
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_LANG_STRUCT:
- oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag),
- t->u.s.tag);
+ case TYPE_USER_STRUCT:
+ {
+ const char *id_for_tag = filter_type_name (t->u.s.tag);
+ oprintf (of, "%lu%s", (unsigned long) strlen (id_for_tag),
+ id_for_tag);
+ if (id_for_tag != t->u.s.tag)
+ free (CONST_CAST(char *, id_for_tag));
+ }
break;
case TYPE_PARAM_STRUCT:
{
@@ -2390,6 +2497,7 @@ output_escaped_param (struct walk_type_data *d, const char *param,
}
}
+
/* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
which is of type T. Write code to D->OF to constrain execution (at
the point that D->PROCESS_FIELD is called) to the appropriate
@@ -2470,7 +2578,7 @@ walk_type (type_p t, struct walk_type_data *d)
if (pointer_p)
t = t->u.p;
- if (!UNION_OR_STRUCT_P (t))
+ if (!union_or_struct_p (t))
error_at_line (d->line, "`use_params' option on unimplemented type");
else
t = find_param_structure (t, d->param);
@@ -2498,7 +2606,7 @@ walk_type (type_p t, struct walk_type_data *d)
}
if (maybe_undef_p
- && (t->kind != TYPE_POINTER || !UNION_OR_STRUCT_P (t->u.p)))
+ && (t->kind != TYPE_POINTER || !union_or_struct_p (t->u.p)))
{
error_at_line (d->line,
"field `%s' has invalid option `maybe_undef_p'\n",
@@ -2521,6 +2629,7 @@ walk_type (type_p t, struct walk_type_data *d)
case TYPE_POINTER:
{
+ d->in_ptr_field = true;
if (maybe_undef_p && t->u.p->u.s.line.file == NULL)
{
oprintf (d->of, "%*sgcc_assert (!%s);\n", d->indent, "", d->val);
@@ -2548,7 +2657,7 @@ walk_type (type_p t, struct walk_type_data *d)
if (!length)
{
- if (!UNION_OR_STRUCT_P (t->u.p)
+ if (!union_or_struct_p (t->u.p)
&& t->u.p->kind != TYPE_PARAM_STRUCT)
{
error_at_line (d->line,
@@ -2561,7 +2670,7 @@ walk_type (type_p t, struct walk_type_data *d)
{
const char *oldprevval2 = d->prev_val[2];
- if (!UNION_OR_STRUCT_P (nested_ptr_d->type))
+ if (!union_or_struct_p (nested_ptr_d->type))
{
error_at_line (d->line,
"field `%s' has invalid "
@@ -2638,6 +2747,7 @@ walk_type (type_p t, struct walk_type_data *d)
d->indent -= 2;
oprintf (d->of, "%*s}\n", d->indent, "");
}
+ d->in_ptr_field = false;
}
break;
@@ -2921,6 +3031,10 @@ walk_type (type_p t, struct walk_type_data *d)
}
break;
+ case TYPE_USER_STRUCT:
+ d->process_field (t, d);
+ break;
+
default:
gcc_unreachable ();
}
@@ -2978,7 +3092,7 @@ write_types_process_field (type_p f, const struct walk_type_data *d)
oprintf (d->of, ", gt_e_");
output_mangled_typename (d->of, f);
}
- else if (UNION_OR_STRUCT_P (f) && f->u.p->u.s.line.file != NULL)
+ else if (union_or_struct_p (f) && f->u.p->u.s.line.file != NULL)
{
oprintf (d->of, ", gt_ggc_e_");
output_mangled_typename (d->of, f);
@@ -2998,13 +3112,27 @@ write_types_process_field (type_p f, const struct walk_type_data *d)
case TYPE_UNION:
case TYPE_LANG_STRUCT:
case TYPE_PARAM_STRUCT:
- oprintf (d->of, "%*sgt_%s_", d->indent, "", wtd->prefix);
- output_mangled_typename (d->of, f);
- oprintf (d->of, " (%s%s);\n", cast, d->val);
- if (d->reorder_fn && wtd->reorder_note_routine)
- oprintf (d->of, "%*s%s (%s%s, %s%s, %s);\n", d->indent, "",
- wtd->reorder_note_routine, cast, d->val, cast, d->val,
- d->reorder_fn);
+ case TYPE_USER_STRUCT:
+ if (f->kind == TYPE_USER_STRUCT && !d->in_ptr_field)
+ {
+ /* If F is a user-defined type and the field is not a
+ pointer to the type, then we should not generate the
+ standard pointer-marking code. All we need to do is call
+ the user-provided marking function to process the fields
+ of F. */
+ oprintf (d->of, "%*sgt_%sx (&(%s));\n", d->indent, "", wtd->prefix,
+ d->val);
+ }
+ else
+ {
+ oprintf (d->of, "%*sgt_%s_", d->indent, "", wtd->prefix);
+ output_mangled_typename (d->of, f);
+ oprintf (d->of, " (%s%s);\n", cast, d->val);
+ if (d->reorder_fn && wtd->reorder_note_routine)
+ oprintf (d->of, "%*s%s (%s%s, %s%s, %s);\n", d->indent, "",
+ wtd->reorder_note_routine, cast, d->val, cast, d->val,
+ d->reorder_fn);
+ }
break;
case TYPE_SCALAR:
@@ -3025,7 +3153,7 @@ output_type_enum (outf_p of, type_p s)
oprintf (of, ", gt_e_");
output_mangled_typename (of, s);
}
- else if (UNION_OR_STRUCT_P (s) && s->u.s.line.file != NULL)
+ else if (union_or_struct_p (s) && s->u.s.line.file != NULL)
{
oprintf (of, ", gt_ggc_e_");
output_mangled_typename (of, s);
@@ -3043,13 +3171,13 @@ get_output_file_for_structure (const_type_p s, type_p *param)
const input_file *fn;
int i;
- gcc_assert (UNION_OR_STRUCT_P (s));
+ gcc_assert (union_or_struct_p (s));
fn = s->u.s.line.file;
/* 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))
+ && union_or_struct_p (param[i]->u.p))
fn = param[i]->u.p->u.s.line.file;
/* The call to get_output_file_with_visibility may update fn by
@@ -3057,13 +3185,185 @@ get_output_file_for_structure (const_type_p s, type_p *param)
return get_output_file_with_visibility (CONST_CAST (input_file*, fn));
}
+
+/* Returns the specifier keyword for a string or union type S, empty string
+ otherwise. */
+
+static const char *
+get_type_specifier (const type_p s)
+{
+ if (s->kind == TYPE_STRUCT)
+ return "struct ";
+ else if (s->kind == TYPE_LANG_STRUCT)
+ return get_type_specifier (s->u.s.lang_struct);
+ else if (s->kind == TYPE_UNION)
+ return "union ";
+ return "";
+}
+
+
+/* Emits a declaration for type TY (assumed to be a union or a
+ structure) on stream OUT. */
+
+static void
+write_type_decl (outf_p out, type_p ty)
+{
+ if (union_or_struct_p (ty))
+ oprintf (out, "%s%s", get_type_specifier (ty), ty->u.s.tag);
+ else if (ty->kind == TYPE_SCALAR)
+ {
+ if (ty->u.scalar_is_char)
+ oprintf (out, "const char");
+ else
+ oprintf (out, "void");
+ }
+ else if (ty->kind == TYPE_POINTER)
+ {
+ write_type_decl (out, ty->u.p);
+ oprintf (out, " *");
+ }
+ else if (ty->kind == TYPE_ARRAY)
+ {
+ write_type_decl (out, ty->u.a.p);
+ oprintf (out, " *");
+ }
+ else if (ty->kind == TYPE_STRING)
+ {
+ oprintf (out, "const char *");
+ }
+ else
+ gcc_unreachable ();
+}
+
+
+/* Write on OF the name of the marker function for structure S. PREFIX
+ is the prefix to use (to distinguish ggc from pch markers). */
+
+static void
+write_marker_function_name (outf_p of, type_p s, const char *prefix)
+{
+ if (union_or_struct_p (s))
+ {
+ const char *id_for_tag = filter_type_name (s->u.s.tag);
+ oprintf (of, "gt_%sx_%s", prefix, id_for_tag);
+ if (id_for_tag != s->u.s.tag)
+ free (CONST_CAST(char *, id_for_tag));
+ }
+ else if (s->kind == TYPE_PARAM_STRUCT)
+ {
+ oprintf (of, "gt_%s_", prefix);
+ output_mangled_typename (of, s);
+ }
+ else
+ gcc_unreachable ();
+}
+
+
+/* Write on OF a user-callable routine to act as an entry point for
+ the marking routine for S, generated by write_func_for_structure.
+ PREFIX is the prefix to use to distinguish ggc and pch markers. */
+
+static void
+write_user_func_for_structure_ptr (outf_p of, type_p s, const char *prefix)
+{
+ /* Parameterized structures are not supported in user markers. There
+ is no way for the marker function to know which specific type
+ to use to generate the call to the void * entry point. For
+ instance, a marker for struct htab may need to call different
+ routines to mark the fields, depending on the paramN_is attributes.
+
+ A user-defined marker that accepts 'struct htab' as its argument
+ would not know which variant to call. Generating several entry
+ points accepting 'struct htab' would cause multiply-defined
+ errors during compilation. */
+ gcc_assert (union_or_struct_p (s));
+
+ type_p alias_of = NULL;
+ for (options_p opt = s->u.s.opt; opt; opt = opt->next)
+ if (strcmp (opt->name, "ptr_alias") == 0)
+ {
+ /* ALIAS_OF is set if ORIG_S is marked "ptr_alias". This means that
+ we do not generate marking code for ORIG_S here. Instead, a
+ forwarder #define in gtype-desc.h will cause every call to its
+ marker to call the target of this alias.
+
+ However, we still want to create a user entry code for the
+ aliased type. So, if ALIAS_OF is set, we only generate the
+ user-callable marker function. */
+ alias_of = opt->info.type;
+ break;
+ }
+
+ oprintf (of, "\nvoid\n");
+ oprintf (of, "gt_%sx (", prefix);
+ write_type_decl (of, s);
+ oprintf (of, " *& x)\n");
+ oprintf (of, "{\n");
+ oprintf (of, " if (x)\n ");
+ write_marker_function_name (of, alias_of ? alias_of : s, prefix);
+ oprintf (of, " ((void *) x);\n");
+ oprintf (of, "}\n");
+}
+
+
+/* Write a function to mark all the fields of type S on OF. PREFIX
+ and D are as in write_user_marking_functions. */
+
+static void
+write_user_func_for_structure_body (type_p s, const char *prefix,
+ struct walk_type_data *d)
+{
+ oprintf (d->of, "\nvoid\n");
+ oprintf (d->of, "gt_%sx (", prefix);
+ write_type_decl (d->of, s);
+ oprintf (d->of, "& x_r ATTRIBUTE_UNUSED)\n");
+ oprintf (d->of, "{\n");
+ oprintf (d->of, " ");
+ write_type_decl (d->of, s);
+ oprintf (d->of, " * ATTRIBUTE_UNUSED x = &x_r;\n");
+ d->val = "(*x)";
+ d->indent = 2;
+ walk_type (s, d);
+ oprintf (d->of, "}\n");
+}
+
+
+/* Emit the user-callable functions needed to mark all the types used
+ by the user structure S. PREFIX is the prefix to use to
+ distinguish ggc and pch markers. D contains data needed to pass to
+ walk_type when traversing the fields of a type.
+
+ For every type T referenced by S, two routines are generated: one
+ that takes 'T *', marks the pointer and calls the second routine,
+ which just marks the fields of T. */
+
+static void
+write_user_marking_functions (type_p s, const char *prefix,
+ struct walk_type_data *d)
+{
+ gcc_assert (s->kind == TYPE_USER_STRUCT);
+
+ for (pair_p fld = s->u.s.fields; fld; fld = fld->next)
+ {
+ type_p fld_type = fld->type;
+ if (fld_type->kind == TYPE_POINTER)
+ {
+ type_p pointed_to_type = fld_type->u.p;
+ if (union_or_struct_p (pointed_to_type))
+ write_user_func_for_structure_ptr (d->of, pointed_to_type, prefix);
+ }
+ else if (union_or_struct_p (fld_type))
+ write_user_func_for_structure_body (fld_type, prefix, d);
+ }
+}
+
+
/* For S, a structure that's part of ORIG_S, and using parameters
PARAM, write out a routine that:
- Takes a parameter, a void * but actually of type *S
- If SEEN_ROUTINE returns nonzero, calls write_types_process_field on each
field of S or its substructures and (in some cases) things
- that are pointed to by S.
-*/
+ that are pointed to by S. */
static void
write_func_for_structure (type_p orig_s, type_p s, type_p *param,
@@ -3113,22 +3413,19 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
oprintf (d.of, "\n");
oprintf (d.of, "void\n");
- if (param == NULL)
- oprintf (d.of, "gt_%sx_%s", wtd->prefix, orig_s->u.s.tag);
- else
- {
- oprintf (d.of, "gt_%s_", wtd->prefix);
- output_mangled_typename (d.of, orig_s);
- }
+ write_marker_function_name (d.of, orig_s, wtd->prefix);
oprintf (d.of, " (void *x_p)\n");
- oprintf (d.of, "{\n");
- oprintf (d.of, " %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 (d.of, "{\n ");
+ write_type_decl (d.of, s);
+ oprintf (d.of, " * %sx = (", chain_next == NULL ? "const " : "");
+ write_type_decl (d.of, s);
+ oprintf (d.of, " *)x_p;\n");
if (chain_next != NULL)
- oprintf (d.of, " %s %s * xlimit = x;\n",
- s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
+ {
+ oprintf (d.of, " ");
+ write_type_decl (d.of, s);
+ oprintf (d.of, " * xlimit = x;\n");
+ }
if (chain_next == NULL)
{
oprintf (d.of, " if (%s (x", wtd->marker_routine);
@@ -3211,9 +3508,17 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
{
oprintf (d.of, " %s (x);\n", mark_hook_name);
}
+
d.prev_val[2] = "*x";
d.indent = 6;
- walk_type (s, &d);
+ if (orig_s->kind != TYPE_USER_STRUCT)
+ walk_type (s, &d);
+ else
+ {
+ /* User structures have no fields to walk. Simply generate a call
+ to the user-provided structure marker. */
+ oprintf (d.of, "%*sgt_%sx (x);\n", d.indent, "", wtd->prefix);
+ }
if (chain_next != NULL)
{
@@ -3226,8 +3531,12 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
if (chain_circular != NULL)
oprintf (d.of, " while (x != xlimit);\n");
oprintf (d.of, "}\n");
+
+ if (orig_s->kind == TYPE_USER_STRUCT)
+ write_user_marking_functions (orig_s, wtd->prefix, &d);
}
+
/* Write out marker routines for STRUCTURES and PARAM_STRUCTS. */
static void
@@ -3238,23 +3547,27 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
type_p s;
oprintf (output_header, "\n/* %s*/\n", wtd->comment);
+
/* We first emit the macros and the declarations. Functions' code is
emitted afterwards. This is needed in plugin mode. */
- oprintf (output_header, "/* macros and declarations */\n");
+ oprintf (output_header, "/* Macros and declarations. */\n");
for (s = structures; s; s = s->next)
if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
{
options_p opt;
+ const char *s_id_for_tag;
if (s->gc_used == GC_MAYBE_POINTED_TO && s->u.s.line.file == NULL)
continue;
+ s_id_for_tag = filter_type_name (s->u.s.tag);
+
oprintf (output_header, "#define gt_%s_", wtd->prefix);
output_mangled_typename (output_header, s);
oprintf (output_header, "(X) do { \\\n");
oprintf (output_header,
" if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
- s->u.s.tag);
+ s_id_for_tag);
oprintf (output_header, " } while (0)\n");
for (opt = s->u.s.opt; opt; opt = opt->next)
@@ -3264,9 +3577,14 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
const_type_p const t = (const_type_p) opt->info.type;
if (t->kind == TYPE_STRUCT
|| t->kind == TYPE_UNION || t->kind == TYPE_LANG_STRUCT)
- oprintf (output_header,
- "#define gt_%sx_%s gt_%sx_%s\n",
- wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
+ {
+ const char *t_id_for_tag = filter_type_name (t->u.s.tag);
+ oprintf (output_header,
+ "#define gt_%sx_%s gt_%sx_%s\n",
+ wtd->prefix, s->u.s.tag, wtd->prefix, t_id_for_tag);
+ if (t_id_for_tag != t->u.s.tag)
+ free (CONST_CAST(char *, t_id_for_tag));
+ }
else
error_at_line (&s->u.s.line,
"structure alias is not a structure");
@@ -3278,7 +3596,10 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
/* Declare the marker procedure only once. */
oprintf (output_header,
"extern void gt_%sx_%s (void *);\n",
- wtd->prefix, s->u.s.tag);
+ wtd->prefix, s_id_for_tag);
+
+ if (s_id_for_tag != s->u.s.tag)
+ free (CONST_CAST(char *, s_id_for_tag));
if (s->u.s.line.file == NULL)
{
@@ -3400,6 +3721,90 @@ static const struct write_types_data pch_wtd = {
/* Write out the local pointer-walking routines. */
+/* process_field routine for local pointer-walking for user-callable
+ routines. The difference between this and
+ write_types_local_process_field is that, in this case, we do not
+ need to check whether the given pointer matches the address of the
+ parent structure. This check was already generated by the call
+ to gt_pch_nx in the main gt_pch_p_*() function that is calling
+ this code. */
+
+static void
+write_types_local_user_process_field (type_p f, const struct walk_type_data *d)
+{
+ switch (f->kind)
+ {
+ case TYPE_POINTER:
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ case TYPE_LANG_STRUCT:
+ case TYPE_PARAM_STRUCT:
+ case TYPE_STRING:
+ oprintf (d->of, "%*s op (&(%s), cookie);\n", d->indent, "", d->val);
+ break;
+
+ case TYPE_USER_STRUCT:
+ if (d->in_ptr_field)
+ oprintf (d->of, "%*s op (&(%s), cookie);\n", d->indent, "", d->val);
+ else
+ oprintf (d->of, "%*s gt_pch_nx (&(%s), op, cookie);\n",
+ d->indent, "", d->val);
+ break;
+
+ case TYPE_SCALAR:
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
+/* Write a function to PCH walk all the fields of type S on OF.
+ D contains data needed by walk_type to recurse into the fields of S. */
+
+static void
+write_pch_user_walking_for_structure_body (type_p s, struct walk_type_data *d)
+{
+ oprintf (d->of, "\nvoid\n");
+ oprintf (d->of, "gt_pch_nx (");
+ write_type_decl (d->of, s);
+ oprintf (d->of, "* x ATTRIBUTE_UNUSED,\n"
+ "\tATTRIBUTE_UNUSED gt_pointer_operator op,\n"
+ "\tATTRIBUTE_UNUSED void *cookie)\n");
+ oprintf (d->of, "{\n");
+ d->val = "(*x)";
+ d->indent = 2;
+ d->process_field = write_types_local_user_process_field;
+ walk_type (s, d);
+ oprintf (d->of, "}\n");
+}
+
+
+/* Emit the user-callable functions needed to mark all the types used
+ by the user structure S. PREFIX is the prefix to use to
+ distinguish ggc and pch markers. CHAIN_NEXT is set if S has the
+ chain_next option defined. D contains data needed to pass to
+ walk_type when traversing the fields of a type.
+
+ For every type T referenced by S, two routines are generated: one
+ that takes 'T *', marks the pointer and calls the second routine,
+ which just marks the fields of T. */
+
+static void
+write_pch_user_walking_functions (type_p s, struct walk_type_data *d)
+{
+ gcc_assert (s->kind == TYPE_USER_STRUCT);
+
+ for (pair_p fld = s->u.s.fields; fld; fld = fld->next)
+ {
+ type_p fld_type = fld->type;
+ if (union_or_struct_p (fld_type))
+ write_pch_user_walking_for_structure_body (fld_type, d);
+ }
+}
+
+
/* process_field routine for local pointer-walking. */
static void
@@ -3419,6 +3824,16 @@ write_types_local_process_field (type_p f, const struct walk_type_data *d)
oprintf (d->of, "%*s op (&(%s), cookie);\n", d->indent, "", d->val);
break;
+ case TYPE_USER_STRUCT:
+ oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
+ d->prev_val[3]);
+ if (d->in_ptr_field)
+ oprintf (d->of, "%*s op (&(%s), cookie);\n", d->indent, "", d->val);
+ else
+ oprintf (d->of, "%*s gt_pch_nx (&(%s), op, cookie);\n",
+ d->indent, "", d->val);
+ break;
+
case TYPE_SCALAR:
break;
@@ -3427,6 +3842,7 @@ write_types_local_process_field (type_p f, const struct walk_type_data *d)
}
}
+
/* For S, a structure that's part of ORIG_S, and using parameters
PARAM, write out a routine that:
- Is of type gt_note_pointers
@@ -3460,13 +3876,29 @@ write_local_func_for_structure (const_type_p orig_s, type_p s, type_p *param)
"\tATTRIBUTE_UNUSED gt_pointer_operator op,\n"
"\tATTRIBUTE_UNUSED void *cookie)\n");
oprintf (d.of, "{\n");
- oprintf (d.of, " %s %s * const x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
+ oprintf (d.of, " %s %s * x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
d.indent = 2;
d.have_this_obj = true;
- walk_type (s, &d);
+
+ if (s->kind != TYPE_USER_STRUCT)
+ walk_type (s, &d);
+ else
+ {
+ /* User structures have no fields to walk. Simply generate a
+ call to the user-provided PCH walker. */
+ oprintf (d.of, "%*sif ((void *)(%s) == this_obj)\n", d.indent, "",
+ d.prev_val[3]);
+ oprintf (d.of, "%*s gt_pch_nx (&(%s), op, cookie);\n",
+ d.indent, "", d.val);
+ }
+
oprintf (d.of, "}\n");
+
+ /* Write user-callable entry points for the PCH walking routines. */
+ if (orig_s->kind == TYPE_USER_STRUCT)
+ write_pch_user_walking_functions (s, &d);
}
/* Write out local marker routines for STRUCTURES and PARAM_STRUCTS. */
@@ -3478,6 +3910,7 @@ write_local (outf_p output_header, type_p structures, type_p param_structs)
if (!output_header)
return;
+
oprintf (output_header, "\n/* Local pointer-walking routines. */\n");
for (s = structures; s; s = s->next)
if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
@@ -3557,15 +3990,15 @@ write_local (outf_p output_header, type_p structures, type_p param_structs)
/* Nonzero if S is a type for which typed GC allocators should be output. */
#define USED_BY_TYPED_GC_P(s) \
- (((s->kind == TYPE_POINTER) \
- && ((s->u.p->gc_used == GC_POINTED_TO) \
- || (s->u.p->gc_used == GC_USED))) \
- || (UNION_OR_STRUCT_P (s) && \
- (((s)->gc_used == GC_POINTED_TO) \
- || ((s)->gc_used == GC_MAYBE_POINTED_TO \
- && s->u.s.line.file != NULL) \
- || ((s)->gc_used == GC_USED \
- && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))))))
+ ((s->kind == TYPE_POINTER \
+ && (s->u.p->gc_used == GC_POINTED_TO \
+ || s->u.p->gc_used == GC_USED)) \
+ || (union_or_struct_p (s) \
+ && ((s)->gc_used == GC_POINTED_TO \
+ || ((s)->gc_used == GC_MAYBE_POINTED_TO \
+ && s->u.s.line.file != NULL) \
+ || ((s)->gc_used == GC_USED \
+ && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))))))
/* Write out the 'enum' definition for gt_types_enum. */
@@ -3587,7 +4020,7 @@ write_enum_defn (type_p structures, type_p param_structs)
nbstruct++;
DBGPRINTF ("write_enum_defn s @ %p nbstruct %d",
(void*) s, nbstruct);
- if (UNION_OR_STRUCT_P (s))
+ if (union_or_struct_p (s))
DBGPRINTF ("write_enum_defn s %p #%d is unionorstruct tagged %s",
(void*) s, nbstruct, s->u.s.tag);
oprintf (header_file, " gt_ggc_e_");
@@ -3873,6 +4306,11 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
}
break;
+ case TYPE_USER_STRUCT:
+ write_root (f, v, type->u.a.p, name, has_length, line, if_marked,
+ emit_pch);
+ break;
+
case TYPE_POINTER:
{
type_p tp;
@@ -3882,13 +4320,16 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
tp = type->u.p;
- if (!has_length && UNION_OR_STRUCT_P (tp))
+ if (!has_length && union_or_struct_p (tp))
{
- oprintf (f, " >_ggc_mx_%s,\n", tp->u.s.tag);
+ const char *id_for_tag = filter_type_name (tp->u.s.tag);
+ oprintf (f, " >_ggc_mx_%s,\n", id_for_tag);
if (emit_pch)
- oprintf (f, " >_pch_nx_%s", tp->u.s.tag);
+ oprintf (f, " >_pch_nx_%s", id_for_tag);
else
oprintf (f, " NULL");
+ if (id_for_tag != tp->u.s.tag)
+ free (CONST_CAST(char *, id_for_tag));
}
else if (!has_length && tp->kind == TYPE_PARAM_STRUCT)
{
@@ -3903,7 +4344,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
oprintf (f, ",\n NULL");
}
else if (has_length
- && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
+ && (tp->kind == TYPE_POINTER || union_or_struct_p (tp)))
{
oprintf (f, " >_ggc_ma_%s,\n", name);
if (emit_pch)
@@ -4146,7 +4587,8 @@ write_roots (pair_p variables, bool emit_pch)
continue;
if (v->type->kind != TYPE_POINTER
|| v->type->u.p->kind != TYPE_PARAM_STRUCT
- || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0))
+ || v->type->u.p->u.param_struct.stru != find_structure ("htab",
+ TYPE_STRUCT))
{
error_at_line (&v->line,
"if_marked option used but not hash table");
@@ -4249,96 +4691,6 @@ write_roots (pair_p variables, bool emit_pch)
finish_root_table (flp, "pch_rs", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
"gt_pch_scalar_rtab");
}
-/* Record the definition of the vec_prefix structure, as defined in vec.h:
-
- struct vec_prefix GTY(()) {
- unsigned num;
- unsigned alloc;
- }; */
-static type_p
-vec_prefix_type (void)
-{
- static type_p prefix_type = NULL;
- if (prefix_type == NULL)
- {
- pair_p fields;
- static struct fileloc pos = { NULL, 0 };
- type_p len_ty = create_scalar_type ("unsigned");
- pos.file = input_file_by_name (__FILE__); pos.line = __LINE__;
- fields = create_field_at (0, len_ty, "alloc", 0, &pos);
- fields = create_field_at (fields, len_ty, "num", 0, &pos);
- prefix_type = new_structure ("vec_prefix", 0, &pos, fields, 0);
- prefix_type->u.s.bitmap = -1;
- }
- return prefix_type;
-}
-
-/* Record the definition of a generic VEC structure, as if we had expanded
- the macros in vec.h:
-
- typedef struct VEC_<type>_base GTY(()) {
- struct vec_prefix prefix;
- <type> GTY((length ("%h.prefix.num"))) vec[1];
- } VEC_<type>_base
-
- where the GTY(()) tags are only present if is_scalar is _false_. */
-
-void
-note_def_vec (const char *type_name, bool is_scalar, struct fileloc *pos)
-{
- pair_p fields;
- type_p t;
- options_p o;
- const char *name = concat ("VEC_", type_name, "_base", (char *) 0);
-
- if (is_scalar)
- {
- t = create_scalar_type (type_name);
- o = 0;
- }
- else
- {
- t = resolve_typedef (type_name, pos);
- o = create_string_option (0, "length", "%h.prefix.num");
- }
- /* We assemble the field list in reverse order. */
- fields = create_field_at (0, create_array (t, "1"), "vec", o, pos);
- fields = create_field_at (fields, vec_prefix_type (), "prefix", 0, pos);
-
- do_typedef (name, new_structure (name, 0, pos, fields, 0), pos);
-}
-
-/* Record the definition of an allocation-specific VEC structure, as if
- we had expanded the macros in vec.h:
-
- typedef struct VEC_<type>_<astrat> {
- VEC_<type>_base base;
- } VEC_<type>_<astrat>;
-*/
-void
-note_def_vec_alloc (const char *type, const char *astrat, struct fileloc *pos)
-{
- const char *astratname = concat ("VEC_", type, "_", astrat, (char *) 0);
- const char *basename = concat ("VEC_", type, "_base", (char *) 0);
-
- pair_p field = create_field_at (0, resolve_typedef (basename, pos),
- "base", 0, pos);
-
- do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos);
-}
-
-/* Returns the specifier keyword for a string or union type S, empty string
- otherwise. */
-
-static const char *
-get_type_specifier (const type_p s)
-{
- if (s->kind == TYPE_STRUCT || s->kind == TYPE_LANG_STRUCT)
- return "struct ";
- if (s->kind == TYPE_UNION)
- return "union ";
- return "";
-}
/* TRUE if type S has the GTY variable_size annotation. */
@@ -4374,8 +4726,10 @@ write_typed_alloc_def (outf_p f,
bool two_args = variable_size && (quantity == vector);
bool third_arg = ((zone == specific_zone)
&& (variable_size || (quantity == vector)));
+ const char *type_name_as_id;
gcc_assert (f != NULL);
- oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name);
+ type_name_as_id = filter_type_name (type_name);
+ oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name_as_id);
oprintf (f, "(%s%s%s%s%s) ",
(variable_size ? "SIZE" : ""),
(two_args ? ", " : ""),
@@ -4392,6 +4746,8 @@ write_typed_alloc_def (outf_p f,
if (quantity == vector)
oprintf (f, ", n");
oprintf (f, " MEM_STAT_INFO)))\n");
+ if (type_name_as_id != type_name)
+ free (CONST_CAST(char *, type_name_as_id));
}
/* Writes a typed allocator definition into output F for a struct or
@@ -4403,7 +4759,7 @@ write_typed_struct_alloc_def (outf_p f,
enum alloc_quantity quantity,
enum alloc_zone zone)
{
- gcc_assert (UNION_OR_STRUCT_P (s));
+ gcc_assert (union_or_struct_p (s));
write_typed_alloc_def (f, variable_size_p (s), get_type_specifier (s),
s->u.s.tag, allocator_type, quantity, zone);
}
@@ -4438,7 +4794,7 @@ write_typed_alloc_defns (outf_p f,
{
if (!USED_BY_TYPED_GC_P (s))
continue;
- gcc_assert (UNION_OR_STRUCT_P (s));
+ gcc_assert (union_or_struct_p (s));
/* In plugin mode onput output ggc_alloc macro definitions
relevant to plugin input files. */
if (nb_plugin_files > 0
@@ -4502,6 +4858,7 @@ output_typename (outf_p of, const_type_p t)
output_typename (of, t->u.p);
break;
case TYPE_STRUCT:
+ case TYPE_USER_STRUCT:
case TYPE_UNION:
case TYPE_LANG_STRUCT:
oprintf (of, "%s", t->u.s.tag);
@@ -4560,10 +4917,6 @@ write_splay_tree_allocators (const_type_p param_structs)
}
}
-static void dump_pair (int indent, pair_p p);
-static void dump_type (int indent, type_p p);
-static void dump_type_list (int indent, type_p p);
-
#define INDENT 2
/* Dumps the value of typekind KIND. */
@@ -4583,6 +4936,9 @@ dump_typekind (int indent, enum typekind kind)
case TYPE_STRUCT:
printf ("TYPE_STRUCT");
break;
+ case TYPE_USER_STRUCT:
+ printf ("TYPE_USER_STRUCT");
+ break;
case TYPE_UNION:
printf ("TYPE_UNION");
break;
@@ -4678,8 +5034,7 @@ dump_type_u_s (int indent, type_p t)
{
pair_p fields;
- gcc_assert (t->kind == TYPE_STRUCT || t->kind == TYPE_UNION
- || t->kind == TYPE_LANG_STRUCT);
+ gcc_assert (union_or_struct_p (t));
printf ("%*cu.s.tag = %s\n", indent, ' ', t->u.s.tag);
dump_fileloc (indent, t->u.s.line);
printf ("%*cu.s.fields =\n", indent, ' ');
@@ -4750,6 +5105,9 @@ dump_type (int indent, type_p t)
{
PTR *slot;
+ if (seen_types == NULL)
+ seen_types = htab_create (100, htab_hash_pointer, htab_eq_pointer, NULL);
+
printf ("%*cType at %p: ", indent, ' ', (void *) t);
slot = htab_find_slot (seen_types, t, INSERT);
if (*slot != NULL)
@@ -4775,6 +5133,7 @@ dump_type (int indent, type_p t)
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_LANG_STRUCT:
+ case TYPE_USER_STRUCT:
dump_type_u_s (indent + INDENT, t);
break;
case TYPE_POINTER:
@@ -4834,11 +5193,12 @@ dump_structures (const char *name, type_p structures)
static void
dump_everything (void)
{
- seen_types = htab_create (100, htab_hash_pointer, htab_eq_pointer, NULL);
dump_pair_list ("typedefs", typedefs);
dump_structures ("structures", structures);
dump_structures ("param_structs", param_structs);
dump_pair_list ("variables", variables);
+
+ /* Allocated with the first call to dump_type. */
htab_delete (seen_types);
}
@@ -1,5 +1,5 @@
/* Process source files and output type information.
- Copyright (C) 2002, 2003, 2004, 2007, 2008, 2010, 2011
+ Copyright (C) 2002, 2003, 2004, 2007, 2008, 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of GCC.
@@ -143,11 +143,14 @@ enum typekind {
TYPE_LANG_STRUCT, /* GCC front-end language specific structs.
Various languages may have homonymous but
different structs. */
- TYPE_PARAM_STRUCT /* Type for parametrized structs, e.g. hash_t
+ TYPE_PARAM_STRUCT, /* Type for parametrized structs, e.g. hash_t
hash-tables, ... See (param_is, use_param,
param1_is, param2_is,... use_param1,
use_param_2,... use_params) GTY
options. */
+ TYPE_USER_STRUCT /* User defined type. Walkers and markers for
+ this type are assumed to be provided by the
+ user. */
};
/* Discriminating kind for options. */
@@ -319,19 +322,27 @@ extern struct type scalar_char;
/* Test if a type is a union, either a plain one or a language
specific one. */
-#define UNION_P(x) \
- ((x)->kind == TYPE_UNION || \
- ((x)->kind == TYPE_LANG_STRUCT \
- && (x)->u.s.lang_struct->kind == TYPE_UNION))
+#define UNION_P(x) \
+ ((x)->kind == TYPE_UNION \
+ || ((x)->kind == TYPE_LANG_STRUCT \
+ && (x)->u.s.lang_struct->kind == TYPE_UNION))
/* Test if a type is a union or a structure, perhaps a language
specific one. */
-#define UNION_OR_STRUCT_P(x) \
- ((x)->kind == TYPE_UNION \
- || (x)->kind == TYPE_STRUCT \
- || (x)->kind == TYPE_LANG_STRUCT)
-
+static inline bool
+union_or_struct_p (enum typekind kind)
+{
+ return (kind == TYPE_UNION
+ || kind == TYPE_STRUCT
+ || kind == TYPE_LANG_STRUCT
+ || kind == TYPE_USER_STRUCT);
+}
+static inline bool
+union_or_struct_p (const_type_p x)
+{
+ return union_or_struct_p (x->kind);
+}
/* Give the file location of a type, if any. */
static inline struct fileloc*
@@ -339,7 +350,7 @@ type_fileloc (type_p t)
{
if (!t)
return NULL;
- if (UNION_OR_STRUCT_P(t))
+ if (union_or_struct_p (t))
return &t->u.s.line;
if (t->kind == TYPE_PARAM_STRUCT)
return &t->u.param_struct.line;
@@ -410,10 +421,10 @@ extern char *xasprintf (const char *, ...) ATTRIBUTE_PRINTF_1;
extern void do_typedef (const char *s, type_p t, struct fileloc *pos);
extern void do_scalar_typedef (const char *s, struct fileloc *pos);
extern type_p resolve_typedef (const char *s, struct fileloc *pos);
-extern type_p new_structure (const char *name, int isunion,
+extern type_p new_structure (const char *name, enum typekind kind,
struct fileloc *pos, pair_p fields,
options_p o);
-extern type_p find_structure (const char *s, int isunion);
+extern type_p find_structure (const char *s, enum typekind kind);
extern type_p create_scalar_type (const char *name);
extern type_p create_pointer (type_p t);
extern type_p create_array (type_p t, const char *len);
@@ -424,10 +435,6 @@ extern pair_p nreverse_pairs (pair_p list);
extern type_p adjust_field_type (type_p, options_p);
extern void note_variable (const char *s, type_p t, options_p o,
struct fileloc *pos);
-extern void note_def_vec (const char *type_name, bool is_scalar,
- struct fileloc *pos);
-extern void note_def_vec_alloc (const char *type, const char *astrat,
- struct fileloc *pos);
/* Lexer and parser routines. */
extern int yylex (const char **yylval);
@@ -453,12 +460,10 @@ enum
STRUCT,
ENUM,
VEC_TOKEN,
- DEFVEC_OP,
- DEFVEC_I,
- DEFVEC_ALLOC,
ELLIPSIS,
PTR_ALIAS,
NESTED_PTR,
+ USER_GTY,
PARAM_IS,
NUM,
SCALAR,
@@ -1441,6 +1441,26 @@ gt_ggc_m_S (const void *p)
return;
}
+
+/* User-callable entry point for marking string X. */
+
+void
+gt_ggc_mx (const char *& x)
+{
+ gt_ggc_m_S (x);
+}
+
+void
+gt_ggc_mx (unsigned char *& x)
+{
+ gt_ggc_m_S (x);
+}
+
+void
+gt_ggc_mx (unsigned char& x ATTRIBUTE_UNUSED)
+{
+}
+
/* If P is not marked, marks it and return false. Otherwise return true.
P must have been allocated by the GC allocator; it mustn't point to
static objects, stack variables, or memory allocated with malloc. */
@@ -1508,6 +1508,26 @@ gt_ggc_m_S (const void *p)
ggc_set_mark (p);
}
+
+/* User-callable entry point for marking string X. */
+
+void
+gt_ggc_mx (const char *& x)
+{
+ gt_ggc_m_S (x);
+}
+
+void
+gt_ggc_mx (unsigned char *& x)
+{
+ gt_ggc_m_S (x);
+}
+
+void
+gt_ggc_mx (unsigned char& x ATTRIBUTE_UNUSED)
+{
+}
+
/* If P is not marked, mark it and return false. Otherwise return true.
P must have been allocated by the GC allocator; it mustn't point to
static objects, stack variables, or memory allocated with malloc. */
@@ -32,9 +32,6 @@ extern const char empty_string[]; /* empty string */
/* Internal functions and data structures used by the GTY
machinery, including the generated gt*.[hc] files. */
-/* The first parameter is a pointer to a pointer, the second a cookie. */
-typedef void (*gt_pointer_operator) (void *, void *);
-
#include "gtype-desc.h"
/* One of these applies its third parameter (with cookie in the fourth
@@ -49,7 +49,7 @@ static const char digit_vector[] = {
struct ht *ident_hash;
-static hashnode alloc_node (hash_table *);
+static hashnode alloc_node (cpp_hash_table *);
static int mark_ident (struct cpp_reader *, hashnode, const void *);
static void *
@@ -70,7 +70,7 @@ init_stringpool (void)
/* Allocate a hash node. */
static hashnode
-alloc_node (hash_table *table ATTRIBUTE_UNUSED)
+alloc_node (cpp_hash_table *table ATTRIBUTE_UNUSED)
{
return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE));
}
@@ -210,6 +210,32 @@ gt_pch_n_S (const void *x)
gt_pch_note_object (CONST_CAST (void *, x), CONST_CAST (void *, x),
>_pch_p_S, gt_types_enum_last);
}
+
+
+/* User-callable entry point for marking string X. */
+
+void
+gt_pch_nx (const char *& x)
+{
+ gt_pch_n_S (x);
+}
+
+void
+gt_pch_nx (unsigned char *& x)
+{
+ gt_pch_n_S (x);
+}
+
+void
+gt_pch_nx (unsigned char& x ATTRIBUTE_UNUSED)
+{
+}
+
+void
+gt_pch_nx (unsigned char *x, gt_pointer_operator op, void *cookie)
+{
+ op (x, cookie);
+}
/* Handle saving and restoring the string pool for PCH. */
@@ -7863,3 +7863,54 @@ struct gimple_opt_pass pass_warn_unused_result =
0, /* todo_flags_finish */
}
};
+
+
+/* Garbage collection support for edge_def. */
+
+extern void gt_ggc_mx (tree&);
+extern void gt_ggc_mx (gimple&);
+extern void gt_ggc_mx (rtx&);
+extern void gt_ggc_mx (basic_block&);
+
+void
+gt_ggc_mx (edge_def *e)
+{
+ gt_ggc_mx (e->src);
+ gt_ggc_mx (e->dest);
+ if (current_ir_type () == IR_GIMPLE)
+ gt_ggc_mx (e->insns.g);
+ else
+ gt_ggc_mx (e->insns.r);
+ gt_ggc_mx (e->goto_block);
+}
+
+/* PCH support for edge_def. */
+
+extern void gt_pch_nx (tree&);
+extern void gt_pch_nx (gimple&);
+extern void gt_pch_nx (rtx&);
+extern void gt_pch_nx (basic_block&);
+
+void
+gt_pch_nx (edge_def *e)
+{
+ gt_pch_nx (e->src);
+ gt_pch_nx (e->dest);
+ if (current_ir_type () == IR_GIMPLE)
+ gt_pch_nx (e->insns.g);
+ else
+ gt_pch_nx (e->insns.r);
+ gt_pch_nx (e->goto_block);
+}
+
+void
+gt_pch_nx (edge_def *e, gt_pointer_operator op, void *cookie)
+{
+ op (&(e->src), cookie);
+ op (&(e->dest), cookie);
+ if (current_ir_type () == IR_GIMPLE)
+ op (&(e->insns.g), cookie);
+ else
+ op (&(e->insns.r), cookie);
+ op (&(e->goto_block), cookie);
+}