Message ID | 50252386.8000505@google.com |
---|---|
State | New |
Headers | show |
On 2012-08-10 08:06, Diego Novillo wrote: > The end point should be that the only thing we really need to tell > gengtype about are the variable roots. Everything else would rely on > user-provided markings. I suppose we could still keep the automatic > option for really simple stuff, though. Yes please. Markup may be awkward, but I think can be less awkward than generating those three cookie-cutter functions. r~
On 12-08-10 16:14 , Richard Henderson wrote: > On 2012-08-10 08:06, Diego Novillo wrote: >> The end point should be that the only thing we really need to tell >> gengtype about are the variable roots. Everything else would rely on >> user-provided markings. I suppose we could still keep the automatic >> option for really simple stuff, though. > > Yes please. Markup may be awkward, but I think can be less awkward > than generating those three cookie-cutter functions. Yeah. Another thing I suppose we want to keep is the whole 'prev' and 'next' markings. These generate harness that would be cumbersome to implement from user code. Diego.
On 8/10/12, Diego Novillo <dnovillo@google.com> wrote: > On 12-08-10 16:14 , Richard Henderson wrote: > > On 2012-08-10 08:06, Diego Novillo wrote: > > > The end point should be that the only thing we really need to > > > tell gengtype about are the variable roots. Everything else > > > would rely on user-provided markings. I suppose we could still > > > keep the automatic option for really simple stuff, though. > > > > Yes please. Markup may be awkward, but I think can be less > > awkward than generating those three cookie-cutter functions. > > Yeah. Another thing I suppose we want to keep is the whole > 'prev' and 'next' markings. These generate harness that would be > cumbersome to implement from user code. Diego and I talked about this issue. What follows is sort of a brain dump. Corrections welcome. There are several principles we can apply to the work. Data types that change frequently should be handled automatically. Otherwise, the purpose of precise garbage collection is somewhat defeated. If we get to that situation, we should simply figure out how to convert the collector to something else. GTY markings that change frequently, or are hard to understand and get right, are a burden as well. The complexity of gengtype's implementation can be substantially reduced if it does not try to solve all problems. We are compiler engineers, and we can do complex manual work when appropriate. Not everything needs to be automatic. Applying those principles, we can reach some conclusions about approach. We can rely on GTY((user)) for template class types. By and large these types implement general data structures, like hash tables. The won't change much once built, and so maintenance of the manual marking routines will not be a large burden. Taking this approach means that gengtype will not have to understand templates. We really do not want gengtype trying to understand templates. Diego has already implemented this part. Some types generic via void* and use param_is/use_param. As we migrate to templates, much of these uses can go away. Perhaps, eventually, we might be able to remove that complexity from gengtype. As this possibility is closer to wishful thinking, it has really low priority. We cannot rely on GTY((user)) for class hierarchies that hold program structures. For example, cgraph and tree nodes are too volatile to rely on manually synchronizing the marker function with the data fields. So, we need to get gengtype to work with class hierarchies. We probably do not need to handle multiple inheritance. First, existing structures do not use it. Second, it probably would not be used much anyway. Polymorphic class hierarchies may require the user to add a couple of method declarations for gengtype. Gengtype would then provide the method definitions. We do not have any polymorphic classes yet, so this issue has a low priority. We will likely borrow the descriminator/tag structure of unions for the marking of non-polymorphic class hierarchies. Gengtype will split the marking of fields and the identification of the dynamic type into separate functions. We have several non-polymorphic class hierarchies now, though represented with unions and embedding, so this issue has a high priority. Some current classes with nested unions, e.g. tree_type_symtab within tree_type_common within tree_node, might be convertable to a class hierarchy that eliminates all unions. If so, they will likely need more than one descriminator. Given that such structures can persist with nested unions for some time, this issue has low priority. Given all that, it seems that the highest priority for gengtype modifications is direct support for non-polymorphic single-inheritance class hierarchies that are discriminated by tags.
diff --git a/gcc/basic-block.h b/gcc/basic-block.h index bf18bae..23cec6b 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -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 { diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l index 537acf6..5788a6a 100644 --- a/gcc/gengtype-lex.l +++ b/gcc/gengtype-lex.l @@ -108,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); diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c index b213585..03ee781 100644 --- a/gcc/gengtype-parse.c +++ b/gcc/gengtype-parse.c @@ -499,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 (); @@ -733,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: @@ -805,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; @@ -812,9 +829,20 @@ 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 ('}'); + 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); } } diff --git a/gcc/gengtype.h b/gcc/gengtype.h index 2ca0e4e..4a178ec 100644 --- a/gcc/gengtype.h +++ b/gcc/gengtype.h @@ -463,6 +463,7 @@ enum ELLIPSIS, PTR_ALIAS, NESTED_PTR, + USER_GTY, PARAM_IS, NUM, SCALAR, diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index e4cf076..b734781 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -7836,3 +7836,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); +}