Commit 9aa54cc9 by David Malcolm Committed by David Malcolm

gengtype: Support explicit pointers in template arguments

gcc/
2014-05-13  David Malcolm  <dmalcolm@redhat.com>

	* gengtype-parse.c (require3): Eliminate in favor of...
	(require4): New.
	(require_template_declaration): Update to support optional single *
	on a type.

	* gengtype.c (get_ultimate_base_class): Add a non-const overload.
	(create_user_defined_type): Handle a single level of explicit
	pointerness within template arguments.
	(struct write_types_data): Add field "kind".
	(filter_type_name): Handle "*" character.
	(write_user_func_for_structure_ptr): Require a write_types_data
	rather than just a prefix string, so that we can look up the kind
	of the wtd and use it as an index into wrote_user_func_for_ptr,
	ensuring that such functions are written at most once.  Support
	subclasses by invoking the marking function of the ultimate base
	class.
	(write_user_func_for_structure_body): Require a write_types_data
	rather than just a prefix string, so that we can pass this to
	write_user_func_for_structure_ptr.
	(write_func_for_structure): Likewise.
	(ggc_wtd): Add initializer of new "kind" field.
	(pch_wtd): Likewise.

	* gengtype.h (enum write_types_kinds): New.
	(struct type): Add field wrote_user_func_for_ptr to the "s"
	union member.

From-SVN: r210379
parent 5c0f009c
2014-05-13 David Malcolm <dmalcolm@redhat.com>
* gengtype-parse.c (require3): Eliminate in favor of...
(require4): New.
(require_template_declaration): Update to support optional single *
on a type.
* gengtype.c (get_ultimate_base_class): Add a non-const overload.
(create_user_defined_type): Handle a single level of explicit
pointerness within template arguments.
(struct write_types_data): Add field "kind".
(filter_type_name): Handle "*" character.
(write_user_func_for_structure_ptr): Require a write_types_data
rather than just a prefix string, so that we can look up the kind
of the wtd and use it as an index into wrote_user_func_for_ptr,
ensuring that such functions are written at most once. Support
subclasses by invoking the marking function of the ultimate base
class.
(write_user_func_for_structure_body): Require a write_types_data
rather than just a prefix string, so that we can pass this to
write_user_func_for_structure_ptr.
(write_func_for_structure): Likewise.
(ggc_wtd): Add initializer of new "kind" field.
(pch_wtd): Likewise.
* gengtype.h (enum write_types_kinds): New.
(struct type): Add field wrote_user_func_for_ptr to the "s"
union member.
2014-05-13 Richard Sandiford <r.sandiford@uk.ibm.com> 2014-05-13 Richard Sandiford <r.sandiford@uk.ibm.com>
* fold-const.c (optimize_bit_field_compare): Use wi:: operations * fold-const.c (optimize_bit_field_compare): Use wi:: operations
......
...@@ -197,18 +197,19 @@ require2 (int t1, int t2) ...@@ -197,18 +197,19 @@ require2 (int t1, int t2)
return v; return v;
} }
/* If the next token does not have one of the codes T1, T2 or T3, report a /* If the next token does not have one of the codes T1, T2, T3 or T4, report a
parse error; otherwise return the token's value. */ parse error; otherwise return the token's value. */
static const char * static const char *
require3 (int t1, int t2, int t3) require4 (int t1, int t2, int t3, int t4)
{ {
int u = token (); int u = token ();
const char *v = advance (); const char *v = advance ();
if (u != t1 && u != t2 && u != t3) if (u != t1 && u != t2 && u != t3 && u != t4)
{ {
parse_error ("expected %s, %s or %s, have %s", parse_error ("expected %s, %s, %s or %s, have %s",
print_token (t1, 0), print_token (t2, 0), print_token (t1, 0), print_token (t2, 0),
print_token (t3, 0), print_token (u, v)); print_token (t3, 0), print_token (t4, 0),
print_token (u, v));
return 0; return 0;
} }
return v; return v;
...@@ -245,7 +246,9 @@ string_seq (void) ...@@ -245,7 +246,9 @@ string_seq (void)
/* The caller has detected a template declaration that starts /* The caller has detected a template declaration that starts
with TMPL_NAME. Parse up to the closing '>'. This recognizes with TMPL_NAME. Parse up to the closing '>'. This recognizes
simple template declarations of the form ID<ID1,ID2,...,IDn>. simple template declarations of the form ID<ID1,ID2,...,IDn>,
potentially with a single level of indirection e.g.
ID<ID1 *, ID2, ID3 *, ..., IDn>.
It does not try to parse anything more sophisticated than that. It does not try to parse anything more sophisticated than that.
Returns the template declaration string "ID<ID1,ID2,...,IDn>". */ Returns the template declaration string "ID<ID1,ID2,...,IDn>". */
...@@ -254,6 +257,7 @@ static const char * ...@@ -254,6 +257,7 @@ static const char *
require_template_declaration (const char *tmpl_name) require_template_declaration (const char *tmpl_name)
{ {
char *str; char *str;
int num_indirections = 0;
/* Recognize the opening '<'. */ /* Recognize the opening '<'. */
require ('<'); require ('<');
...@@ -294,9 +298,21 @@ require_template_declaration (const char *tmpl_name) ...@@ -294,9 +298,21 @@ require_template_declaration (const char *tmpl_name)
depth -= 1; depth -= 1;
continue; continue;
} }
const char *id = require3 (SCALAR, ID, ','); const char *id = require4 (SCALAR, ID, '*', ',');
if (id == NULL) if (id == NULL)
id = ","; {
if (T.code == '*')
{
id = "*";
if (num_indirections++)
parse_error ("only one level of indirection is supported"
" in template arguments");
}
else
id = ",";
}
else
num_indirections = 0;
str = concat (str, id, (char *) 0); str = concat (str, id, (char *) 0);
} }
return str; return str;
......
...@@ -145,6 +145,14 @@ get_ultimate_base_class (const_type_p s) ...@@ -145,6 +145,14 @@ get_ultimate_base_class (const_type_p s)
s = s->u.s.base_class; s = s->u.s.base_class;
return s; return s;
} }
static type_p
get_ultimate_base_class (type_p s)
{
while (s->u.s.base_class)
s = s->u.s.base_class;
return s;
}
/* Input file handling. */ /* Input file handling. */
...@@ -589,7 +597,7 @@ create_user_defined_type (const char *type_name, struct fileloc *pos) ...@@ -589,7 +597,7 @@ create_user_defined_type (const char *type_name, struct fileloc *pos)
/* We only accept simple template declarations (see /* We only accept simple template declarations (see
require_template_declaration), so we only need to parse a require_template_declaration), so we only need to parse a
comma-separated list of strings, implicitly assumed to comma-separated list of strings, implicitly assumed to
be type names. */ be type names, potentially with "*" characters. */
char *arg = open_bracket + 1; char *arg = open_bracket + 1;
char *type_id = strtok (arg, ",>"); char *type_id = strtok (arg, ",>");
pair_p fields = 0; pair_p fields = 0;
...@@ -597,8 +605,28 @@ create_user_defined_type (const char *type_name, struct fileloc *pos) ...@@ -597,8 +605,28 @@ create_user_defined_type (const char *type_name, struct fileloc *pos)
{ {
/* Create a new field for every type found inside the template /* Create a new field for every type found inside the template
parameter list. */ parameter list. */
const char *field_name = xstrdup (type_id);
type_p arg_type = resolve_typedef (field_name, pos); /* Support a single trailing "*" character. */
const char *star = strchr (type_id, '*');
int is_ptr = (star != NULL);
size_t offset_to_star = star - type_id;
if (is_ptr)
offset_to_star = star - type_id;
char *field_name = xstrdup (type_id);
type_p arg_type;
if (is_ptr)
{
/* Strip off the first '*' character (and any subsequent text). */
*(field_name + offset_to_star) = '\0';
arg_type = find_structure (field_name, TYPE_STRUCT);
arg_type = create_pointer (arg_type);
}
else
arg_type = resolve_typedef (field_name, pos);
fields = create_field_at (fields, arg_type, field_name, 0, pos); fields = create_field_at (fields, arg_type, field_name, 0, pos);
type_id = strtok (0, ",>"); type_id = strtok (0, ",>");
} }
...@@ -2461,6 +2489,7 @@ struct write_types_data ...@@ -2461,6 +2489,7 @@ struct write_types_data
const char *reorder_note_routine; const char *reorder_note_routine;
const char *comment; const char *comment;
int skip_hooks; /* skip hook generation if non zero */ int skip_hooks; /* skip hook generation if non zero */
enum write_types_kinds kind;
}; };
static void output_escaped_param (struct walk_type_data *d, static void output_escaped_param (struct walk_type_data *d,
...@@ -2537,7 +2566,8 @@ filter_type_name (const char *type_name) ...@@ -2537,7 +2566,8 @@ filter_type_name (const char *type_name)
size_t i; size_t i;
char *s = xstrdup (type_name); char *s = xstrdup (type_name);
for (i = 0; i < strlen (s); i++) for (i = 0; i < strlen (s); i++)
if (s[i] == '<' || s[i] == '>' || s[i] == ':' || s[i] == ',') if (s[i] == '<' || s[i] == '>' || s[i] == ':' || s[i] == ','
|| s[i] == '*')
s[i] = '_'; s[i] = '_';
return s; return s;
} }
...@@ -3501,10 +3531,10 @@ write_marker_function_name (outf_p of, type_p s, const char *prefix) ...@@ -3501,10 +3531,10 @@ write_marker_function_name (outf_p of, type_p s, const char *prefix)
/* Write on OF a user-callable routine to act as an entry point for /* 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. the marking routine for S, generated by write_func_for_structure.
PREFIX is the prefix to use to distinguish ggc and pch markers. */ WTD distinguishes between ggc and pch markers. */
static void static void
write_user_func_for_structure_ptr (outf_p of, type_p s, const char *prefix) write_user_func_for_structure_ptr (outf_p of, type_p s, const write_types_data *wtd)
{ {
/* Parameterized structures are not supported in user markers. There /* Parameterized structures are not supported in user markers. There
is no way for the marker function to know which specific type is no way for the marker function to know which specific type
...@@ -3534,13 +3564,23 @@ write_user_func_for_structure_ptr (outf_p of, type_p s, const char *prefix) ...@@ -3534,13 +3564,23 @@ write_user_func_for_structure_ptr (outf_p of, type_p s, const char *prefix)
break; break;
} }
DBGPRINTF ("write_user_func_for_structure_ptr: %s %s", s->u.s.tag,
wtd->prefix);
/* Only write the function once. */
if (s->u.s.wrote_user_func_for_ptr[wtd->kind])
return;
s->u.s.wrote_user_func_for_ptr[wtd->kind] = true;
oprintf (of, "\nvoid\n"); oprintf (of, "\nvoid\n");
oprintf (of, "gt_%sx (", prefix); oprintf (of, "gt_%sx (", wtd->prefix);
write_type_decl (of, s); write_type_decl (of, s);
oprintf (of, " *& x)\n"); oprintf (of, " *& x)\n");
oprintf (of, "{\n"); oprintf (of, "{\n");
oprintf (of, " if (x)\n "); oprintf (of, " if (x)\n ");
write_marker_function_name (of, alias_of ? alias_of : s, prefix); write_marker_function_name (of,
alias_of ? alias_of : get_ultimate_base_class (s),
wtd->prefix);
oprintf (of, " ((void *) x);\n"); oprintf (of, " ((void *) x);\n");
oprintf (of, "}\n"); oprintf (of, "}\n");
} }
...@@ -3578,7 +3618,8 @@ write_user_func_for_structure_body (type_p s, const char *prefix, ...@@ -3578,7 +3618,8 @@ write_user_func_for_structure_body (type_p s, const char *prefix,
which just marks the fields of T. */ which just marks the fields of T. */
static void static void
write_user_marking_functions (type_p s, const char *prefix, write_user_marking_functions (type_p s,
const write_types_data *w,
struct walk_type_data *d) struct walk_type_data *d)
{ {
gcc_assert (s->kind == TYPE_USER_STRUCT); gcc_assert (s->kind == TYPE_USER_STRUCT);
...@@ -3590,10 +3631,10 @@ write_user_marking_functions (type_p s, const char *prefix, ...@@ -3590,10 +3631,10 @@ write_user_marking_functions (type_p s, const char *prefix,
{ {
type_p pointed_to_type = fld_type->u.p; type_p pointed_to_type = fld_type->u.p;
if (union_or_struct_p (pointed_to_type)) if (union_or_struct_p (pointed_to_type))
write_user_func_for_structure_ptr (d->of, pointed_to_type, prefix); write_user_func_for_structure_ptr (d->of, pointed_to_type, w);
} }
else if (union_or_struct_p (fld_type)) else if (union_or_struct_p (fld_type))
write_user_func_for_structure_body (fld_type, prefix, d); write_user_func_for_structure_body (fld_type, w->prefix, d);
} }
} }
...@@ -3791,7 +3832,7 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param, ...@@ -3791,7 +3832,7 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
oprintf (d.of, "}\n"); oprintf (d.of, "}\n");
if (orig_s->kind == TYPE_USER_STRUCT) if (orig_s->kind == TYPE_USER_STRUCT)
write_user_marking_functions (orig_s, wtd->prefix, &d); write_user_marking_functions (orig_s, wtd, &d);
} }
...@@ -3969,14 +4010,14 @@ write_types (outf_p output_header, type_p structures, type_p param_structs, ...@@ -3969,14 +4010,14 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
static const struct write_types_data ggc_wtd = { static const struct write_types_data ggc_wtd = {
"ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL, "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
"GC marker procedures. ", "GC marker procedures. ",
FALSE FALSE, WTK_GGC
}; };
static const struct write_types_data pch_wtd = { static const struct write_types_data pch_wtd = {
"pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object", "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
"gt_pch_note_reorder", "gt_pch_note_reorder",
"PCH type-walking procedures. ", "PCH type-walking procedures. ",
TRUE TRUE, WTK_PCH
}; };
/* Write out the local pointer-walking routines. */ /* Write out the local pointer-walking routines. */
......
...@@ -127,7 +127,15 @@ extern type_p structures; ...@@ -127,7 +127,15 @@ extern type_p structures;
extern type_p param_structs; extern type_p param_structs;
extern pair_p variables; extern pair_p variables;
/* An enum for distinguishing GGC vs PCH. */
enum write_types_kinds
{
WTK_GGC,
WTK_PCH,
NUM_WTK
};
/* Discrimating kind of types we can understand. */ /* Discrimating kind of types we can understand. */
...@@ -302,6 +310,10 @@ struct type { ...@@ -302,6 +310,10 @@ struct type {
type_p first_subclass; type_p first_subclass;
/* The next in that list. */ /* The next in that list. */
type_p next_sibling_class; type_p next_sibling_class;
/* Have we already written ggc/pch user func for ptr to this?
(in write_user_func_for_structure_ptr). */
bool wrote_user_func_for_ptr[NUM_WTK];
} s; } s;
/* when TYPE_SCALAR: */ /* when TYPE_SCALAR: */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment