On Tue, Feb 12, 2013 at 8:47 PM, Lawrence Crowl <cr...@google.com> wrote: > Add class record_builder to ease construction of records and unions. Use it > in some appropriate places. > > Nathan please review the vxworks changes. > > tree.h > New class record_builder. > > tree.c > Implement record_builder member functions. > > asan.c > Change asan_global_struct to use record_builder. > > coverage.c > Change build_info_type() to use record_builder. It now takes a > record_builder as a parameter and returns the tree representing > the type. > > Change build_fn_info_type() to use record_builder. It now returns > the tree representing the type. > > Modify coverage_obj_init() to call them appropriately. > > tree-mudflap.c > Change mf_make_mf_cache_struct_type() to use record_builder. > > target.def > Replace the emutls var_fields hook with object_type hook. The > essential difference is that the hook is now responsible for full > construction of the type, not just adding fields. > > targhooks.h > Replace default_emutls_var_fields() with default_emutls_object_type(). > > tree-emutls.c > Replace default_emutls_var_fields() with default_emutls_object_type(). > Use record_builder within default_emutls_object_type(). > > Change get_emutls_object_type to use the new target hook. > > doc/tm.texi.in > Replace TARGET_EMUTLS_VAR_FIELDS with TARGET_EMUTLS_OBJECT_TYPE. > > doc/tm.texi > Replace TARGET_EMUTLS_VAR_FIELDS with TARGET_EMUTLS_OBJECT_TYPE. > > config/vxworks.c > Replace vxworks_emutls_var_fields() with vxworks_emutls_object_type(). > Use record_builder within vxworks_emutls_object_type(). > > Tested on x86_64. Tested with config-list.mk on vxworks targets. > > > Index: gcc/tree-emutls.c > =================================================================== > --- gcc/tree-emutls.c (revision 195904) > +++ gcc/tree-emutls.c (working copy) > @@ -103,41 +103,22 @@ get_emutls_object_name (tree name) > return prefix_name (prefix, name); > } > > -/* Create the fields of the type for the control variables. Ordinarily > +/* Create the type for the control variables. Ordinarily > this must match struct __emutls_object defined in emutls.c. However > this is a target hook so that VxWorks can define its own layout. */ > > tree > -default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED) > +default_emutls_object_type (void) > { > - tree word_type_node, field, next_field; > - > - field = build_decl (UNKNOWN_LOCATION, > - FIELD_DECL, get_identifier ("__templ"), ptr_type_node); > - DECL_CONTEXT (field) = type; > - next_field = field; > - > - field = build_decl (UNKNOWN_LOCATION, > - FIELD_DECL, get_identifier ("__offset"), > - ptr_type_node); > - DECL_CONTEXT (field) = type; > - DECL_CHAIN (field) = next_field; > - next_field = field; > - > - word_type_node = lang_hooks.types.type_for_mode (word_mode, 1); > - field = build_decl (UNKNOWN_LOCATION, > - FIELD_DECL, get_identifier ("__align"), > - word_type_node); > - DECL_CONTEXT (field) = type; > - DECL_CHAIN (field) = next_field; > - next_field = field; > - > - field = build_decl (UNKNOWN_LOCATION, > - FIELD_DECL, get_identifier ("__size"), word_type_node); > - DECL_CONTEXT (field) = type; > - DECL_CHAIN (field) = next_field; > - > - return field; > + tree word_type_node = lang_hooks.types.type_for_mode (word_mode, 1); > + record_builder rec; > + rec.add_field ("__size", word_type_node); > + rec.add_field ("__align", word_type_node); > + rec.add_field ("__offset", ptr_type_node); > + rec.add_field ("__templ", ptr_type_node); > + rec.layout ();
That's awkward - you want to hide the fact that layout has to happen and that it has to happen "last". Just make it a side-effect of .as_tree (). Note that add_field want's to return the FIELD_DECL created, people may want to alter it. Note that tag_name does not allow the way C++ uses this (it can be a TYPE_DECL). Overall I'm not sure this is a good abstraction unless you manage to make the frontends use it. Richard. > + rec.decl_name ("__emutls_object"); > + return rec.as_tree (); > } > > /* Initialize emulated tls object TO, which refers to TLS variable DECL and > @@ -182,24 +163,9 @@ default_emutls_var_init (tree to, tree d > static tree > get_emutls_object_type (void) > { > - tree type, type_name, field; > - > - type = emutls_object_type; > - if (type) > - return type; > - > - emutls_object_type = type = lang_hooks.types.make_type (RECORD_TYPE); > - type_name = NULL; > - field = targetm.emutls.var_fields (type, &type_name); > - if (!type_name) > - type_name = get_identifier ("__emutls_object"); > - type_name = build_decl (UNKNOWN_LOCATION, > - TYPE_DECL, type_name, type); > - TYPE_NAME (type) = type_name; > - TYPE_FIELDS (type) = field; > - layout_type (type); > - > - return type; > + if (!emutls_object_type) > + emutls_object_type = targetm.emutls.object_type (); > + return emutls_object_type; > } > > /* Create a read-only variable like DECL, with the same DECL_INITIAL. > Index: gcc/asan.c > =================================================================== > --- gcc/asan.c (revision 195904) > +++ gcc/asan.c (working copy) > @@ -1496,28 +1496,16 @@ transform_statements (void) > static tree > asan_global_struct (void) > { > - static const char *field_names[5] > - = { "__beg", "__size", "__size_with_redzone", > - "__name", "__has_dynamic_init" }; > - tree fields[5], ret; > - int i; > - > - ret = make_node (RECORD_TYPE); > - for (i = 0; i < 5; i++) > - { > - fields[i] > - = build_decl (UNKNOWN_LOCATION, FIELD_DECL, > - get_identifier (field_names[i]), > - (i == 0 || i == 3) ? const_ptr_type_node > - : build_nonstandard_integer_type (POINTER_SIZE, 1)); > - DECL_CONTEXT (fields[i]) = ret; > - if (i) > - DECL_CHAIN (fields[i - 1]) = fields[i]; > - } > - TYPE_FIELDS (ret) = fields[0]; > - TYPE_NAME (ret) = get_identifier ("__asan_global"); > - layout_type (ret); > - return ret; > + tree ptrint_type = build_nonstandard_integer_type (POINTER_SIZE, 1); > + record_builder rec; > + rec.add_field ("__beg", const_ptr_type_node); > + rec.add_field ("__size", ptrint_type); > + rec.add_field ("__size_with_redzone", ptrint_type); > + rec.add_field ("__name", const_ptr_type_node); > + rec.add_field ("__has_dynamic_init", ptrint_type); > + rec.layout (); > + rec.tag_name ("__asan_global"); > + return rec.as_tree (); > } > > /* Append description of a single global DECL into vector V. > Index: gcc/coverage.c > =================================================================== > --- gcc/coverage.c (revision 195904) > +++ gcc/coverage.c (working copy) > @@ -121,8 +121,8 @@ static const char *const ctr_names[GCOV_ > /* Forward declarations. */ > static void read_counts_file (void); > static tree build_var (tree, tree, int); > -static void build_fn_info_type (tree, unsigned, tree); > -static void build_info_type (tree, tree); > +static tree build_fn_info_type (unsigned, tree); > +static tree build_info_type (record_builder &, tree); > static tree build_fn_info (const struct coverage_data *, tree, tree); > static tree build_info (tree, tree); > static bool coverage_obj_init (void); > @@ -693,63 +693,47 @@ build_var (tree fn_decl, tree type, int > return var; > } > > -/* Creates the gcov_fn_info RECORD_TYPE. */ > +/* Creates the gcov_fn_info RECORD_TYPE, given the number of COUNTERS and > + using the GCOV_INFO_TYPE. */ > > -static void > -build_fn_info_type (tree type, unsigned counters, tree gcov_info_type) > +static tree > +build_fn_info_type (unsigned counters, tree gcov_info_type) > { > - tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE); > - tree field, fields; > - tree array_type; > - > gcc_assert (counters); > - > - /* ctr_info::num */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - get_gcov_unsigned_t ()); > - fields = field; > - > - /* ctr_info::values */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - build_pointer_type (get_gcov_type ())); > - DECL_CHAIN (field) = fields; > - fields = field; > - > - finish_builtin_struct (ctr_info, "__gcov_ctr_info", fields, NULL_TREE); > > + record_builder bld_ctr_info; > + tree gcov_type = get_gcov_type (); > + tree gcov_ptr_type = build_pointer_type (gcov_type); > + bld_ctr_info.add_field (NULL_TREE, gcov_type, BUILTINS_LOCATION); > + bld_ctr_info.add_field (NULL_TREE, gcov_ptr_type, BUILTINS_LOCATION); > + bld_ctr_info.layout (); > + bld_ctr_info.decl_name ("__gcov_ctr_info", BUILTINS_LOCATION); > + tree ctr_info = bld_ctr_info.as_tree (); > + > + record_builder bld_fn_info; > /* key */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - build_pointer_type (build_qualified_type > - (gcov_info_type, TYPE_QUAL_CONST))); > - fields = field; > - > + tree pc_gcov_info > + = build_pointer_type (build_qualified_type (gcov_info_type, > + TYPE_QUAL_CONST)); > + bld_fn_info.add_field (NULL_TREE, pc_gcov_info, BUILTINS_LOCATION); > + > /* ident */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - get_gcov_unsigned_t ()); > - DECL_CHAIN (field) = fields; > - fields = field; > - > + bld_fn_info.add_field (NULL_TREE, get_gcov_unsigned_t ()); > + > /* lineno_checksum */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - get_gcov_unsigned_t ()); > - DECL_CHAIN (field) = fields; > - fields = field; > + bld_fn_info.add_field (NULL_TREE, get_gcov_unsigned_t ()); > > /* cfg checksum */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - get_gcov_unsigned_t ()); > - DECL_CHAIN (field) = fields; > - fields = field; > - > - array_type = build_index_type (size_int (counters - 1)); > - array_type = build_array_type (ctr_info, array_type); > + bld_fn_info.add_field (NULL_TREE, get_gcov_unsigned_t ()); > > /* counters */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type); > - DECL_CHAIN (field) = fields; > - fields = field; > + tree index_type = build_index_type (size_int (counters - 1)); > + tree array_type = build_array_type (ctr_info, index_type); > > - finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE); > + bld_fn_info.add_field (NULL_TREE, array_type, BUILTINS_LOCATION); > + bld_fn_info.layout (); > + bld_fn_info.decl_name ("__gcov_fn_info", BUILTINS_LOCATION); > + return bld_fn_info.as_tree (); > } > > /* Returns a CONSTRUCTOR for a gcov_fn_info. DATA is > @@ -819,69 +803,52 @@ build_fn_info (const struct coverage_dat > return build_constructor (type, v1); > } > > -/* Create gcov_info struct. TYPE is the incomplete RECORD_TYPE to be > +/* Return gcov_info struct. BLD_INFO_TYPE is the record_builder to be > completed, and FN_INFO_PTR_TYPE is a pointer to the function info type. > */ > > -static void > -build_info_type (tree type, tree fn_info_ptr_type) > +static tree > +build_info_type (record_builder &bld_info_type, tree fn_info_ptr_type) > { > - tree field, fields = NULL_TREE; > - tree merge_fn_type; > + tree uns_type = get_gcov_unsigned_t (); > > /* Version ident */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - get_gcov_unsigned_t ()); > - DECL_CHAIN (field) = fields; > - fields = field; > + bld_info_type.add_field (NULL_TREE, uns_type, BUILTINS_LOCATION); > > /* next pointer */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - build_pointer_type (build_qualified_type > - (type, TYPE_QUAL_CONST))); > - DECL_CHAIN (field) = fields; > - fields = field; > + tree self_type = bld_info_type.as_tree (); > + tree qual_info = build_qualified_type (self_type, TYPE_QUAL_CONST); > + tree ptr_info = build_pointer_type (qual_info); > + bld_info_type.add_field (NULL_TREE, ptr_info, BUILTINS_LOCATION); > > /* stamp */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - get_gcov_unsigned_t ()); > - DECL_CHAIN (field) = fields; > - fields = field; > + bld_info_type.add_field (NULL_TREE, uns_type, BUILTINS_LOCATION); > > /* Filename */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - build_pointer_type (build_qualified_type > - (char_type_node, TYPE_QUAL_CONST))); > - DECL_CHAIN (field) = fields; > - fields = field; > + tree qual_char = build_qualified_type (char_type_node, TYPE_QUAL_CONST); > + tree ptr_char = build_pointer_type (qual_char); > + bld_info_type.add_field (NULL_TREE, ptr_char, BUILTINS_LOCATION); > > /* merge fn array */ > - merge_fn_type > + tree merge_fn_type > = build_function_type_list (void_type_node, > build_pointer_type (get_gcov_type ()), > - get_gcov_unsigned_t (), NULL_TREE); > - merge_fn_type > + uns_type, NULL_TREE); > + tree array_fn_type > = build_array_type (build_pointer_type (merge_fn_type), > build_index_type (size_int (GCOV_COUNTERS - 1))); > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - merge_fn_type); > - DECL_CHAIN (field) = fields; > - fields = field; > - > + bld_info_type.add_field (NULL_TREE, array_fn_type, BUILTINS_LOCATION); > + > /* n_functions */ > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - get_gcov_unsigned_t ()); > - DECL_CHAIN (field) = fields; > - fields = field; > - > + bld_info_type.add_field (NULL_TREE, uns_type, BUILTINS_LOCATION); > + > /* function_info pointer pointer */ > - fn_info_ptr_type = build_pointer_type > + tree fn_info_ptr_ptr_type = build_pointer_type > (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST)); > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, > - fn_info_ptr_type); > - DECL_CHAIN (field) = fields; > - fields = field; > + bld_info_type.add_field (NULL_TREE, fn_info_ptr_ptr_type, > BUILTINS_LOCATION); > > - finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE); > + bld_info_type.layout (); > + bld_info_type.decl_name ("__gcov_info"); > + return bld_info_type.as_tree (); > } > > /* Returns a CONSTRUCTOR for the gcov_info object. INFO_TYPE is the > @@ -974,7 +941,7 @@ build_info (tree info_type, tree fn_ary) > static bool > coverage_obj_init (void) > { > - tree gcov_info_type, ctor, stmt, init_fn; > + tree ctor, stmt, init_fn; > unsigned n_counters = 0; > unsigned ix; > struct coverage_data *fn; > @@ -1005,12 +972,11 @@ coverage_obj_init (void) > n_counters++; > > /* Build the info and fn_info types. These are mutually recursive. */ > - gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE); > - gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE); > + record_builder bld_info_type; > + gcov_fn_info_type = build_fn_info_type (n_counters, > bld_info_type.as_tree ()); > gcov_fn_info_ptr_type = build_pointer_type > (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST)); > - build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type); > - build_info_type (gcov_info_type, gcov_fn_info_ptr_type); > + tree gcov_info_type = build_info_type (bld_info_type, > gcov_fn_info_ptr_type); > > /* Build the gcov info var, this is referred to in its own > initializer. */ > Index: gcc/tree-mudflap.c > =================================================================== > --- gcc/tree-mudflap.c (revision 195904) > +++ gcc/tree-mudflap.c (working copy) > @@ -317,23 +317,12 @@ mf_make_builtin (enum tree_code category > static inline tree > mf_make_mf_cache_struct_type (tree field_type) > { > - /* There is, abominably, no language-independent way to construct a > - RECORD_TYPE. So we have to call the basic type construction > - primitives by hand. */ > - tree fieldlo = build_decl (UNKNOWN_LOCATION, > - FIELD_DECL, get_identifier ("low"), field_type); > - tree fieldhi = build_decl (UNKNOWN_LOCATION, > - FIELD_DECL, get_identifier ("high"), field_type); > - > - tree struct_type = make_node (RECORD_TYPE); > - DECL_CONTEXT (fieldlo) = struct_type; > - DECL_CONTEXT (fieldhi) = struct_type; > - DECL_CHAIN (fieldlo) = fieldhi; > - TYPE_FIELDS (struct_type) = fieldlo; > - TYPE_NAME (struct_type) = get_identifier ("__mf_cache"); > - layout_type (struct_type); > - > - return struct_type; > + record_builder rec; > + rec.add_field ("low", field_type); > + rec.add_field ("high", field_type); > + rec.layout (); > + rec.tag_name ("__mf_cache"); > + return rec.as_tree (); > } > > /* Initialize the global tree nodes that correspond to mf-runtime.h > Index: gcc/doc/tm.texi > =================================================================== > --- gcc/doc/tm.texi (revision 195904) > +++ gcc/doc/tm.texi (working copy) > @@ -9966,12 +9966,10 @@ Contains the prefix to be prepended to T > default of @code{NULL} uses a target-specific prefix. > @end deftypevr > > -@deftypefn {Target Hook} tree TARGET_EMUTLS_VAR_FIELDS (tree > @var{type}, tree *@var{name}) > -Specifies a function that generates the FIELD_DECLs for a TLS control > -object type. @var{type} is the RECORD_TYPE the fields are for and > -@var{name} should be filled with the structure tag, if the default of > -@code{__emutls_object} is unsuitable. The default creates a type suitable > -for libgcc's emulated TLS function. > +@deftypefn {Target Hook} tree TARGET_EMUTLS_OBJECT_TYPE () > +Specifies a function that generates the RECORD_TYPE for a TLS control > +object type. The default creates a type, with structure tag > +@code{__emutls_object}, suitable for libgcc's emulated TLS function. > @end deftypefn > > @deftypefn {Target Hook} tree TARGET_EMUTLS_VAR_INIT (tree @var{var}, > tree @var{decl}, tree @var{tmpl_addr}) > Index: gcc/doc/tm.texi.in > =================================================================== > --- gcc/doc/tm.texi.in (revision 195904) > +++ gcc/doc/tm.texi.in (working copy) > @@ -9827,12 +9827,10 @@ Contains the prefix to be prepended to T > default of @code{NULL} uses a target-specific prefix. > @end deftypevr > > -@hook TARGET_EMUTLS_VAR_FIELDS > -Specifies a function that generates the FIELD_DECLs for a TLS control > -object type. @var{type} is the RECORD_TYPE the fields are for and > -@var{name} should be filled with the structure tag, if the default of > -@code{__emutls_object} is unsuitable. The default creates a type suitable > -for libgcc's emulated TLS function. > +@hook TARGET_EMUTLS_OBJECT_TYPE > +Specifies a function that generates the RECORD_TYPE for a TLS control > +object type. The default creates a type, with structure tag > +@code{__emutls_object}, suitable for libgcc's emulated TLS function. > @end deftypefn > > @hook TARGET_EMUTLS_VAR_INIT > Index: gcc/targhooks.h > =================================================================== > --- gcc/targhooks.h (revision 195904) > +++ gcc/targhooks.h (working copy) > @@ -141,7 +141,7 @@ extern void default_target_option_overri > extern void hook_void_bitmap (bitmap); > extern int default_reloc_rw_mask (void); > extern tree default_mangle_decl_assembler_name (tree, tree); > -extern tree default_emutls_var_fields (tree, tree *); > +extern tree default_emutls_object_type (); > extern tree default_emutls_var_init (tree, tree, tree); > extern bool default_hard_regno_scratch_ok (unsigned int); > extern bool default_mode_dependent_address_p (const_rtx, addr_space_t); > Index: gcc/config/vxworks.c > =================================================================== > --- gcc/config/vxworks.c (revision 195904) > +++ gcc/config/vxworks.c (working copy) > @@ -56,35 +56,18 @@ vxworks_asm_out_destructor (rtx symbol, > assemble_addr_to_section (symbol, sec); > } > > -/* Return the list of FIELD_DECLs that make up an emulated TLS > - variable's control object. TYPE is the structure these are fields > - of and *NAME will be filled in with the structure tag that should > - be used. */ > +/* Return the type of an emulated TLS variable's control object. */ > > static tree > -vxworks_emutls_var_fields (tree type, tree *name) > +vxworks_emutls_object_type () > { > - tree field, next_field; > - > - *name = get_identifier ("__tls_var"); > - > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, > - get_identifier ("size"), unsigned_type_node); > - DECL_CONTEXT (field) = type; > - next_field = field; > - > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, > - get_identifier ("module_id"), unsigned_type_node); > - DECL_CONTEXT (field) = type; > - DECL_CHAIN (field) = next_field; > - next_field = field; > - > - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, > - get_identifier ("offset"), unsigned_type_node); > - DECL_CONTEXT (field) = type; > - DECL_CHAIN (field) = next_field; > - > - return field; > + record_builder rec; > + rec.add_field ("offset", unsigned_type_node); > + rec.add_field ("module_id", unsigned_type_node); > + rec.add_field ("size", unsigned_type_node); > + rec.layout (); > + rec.decl_name ("__tls_var"); > + return rec.as_tree (); > } > > /* Return the CONSTRUCTOR to initialize an emulated TLS control > @@ -131,7 +114,7 @@ vxworks_override_options (void) > targetm.emutls.tmpl_section = ".tls_data"; > targetm.emutls.var_prefix = "__tls__"; > targetm.emutls.tmpl_prefix = ""; > - targetm.emutls.var_fields = vxworks_emutls_var_fields; > + targetm.emutls.object_type = vxworks_emutls_object_type; > targetm.emutls.var_init = vxworks_emutls_var_init; > targetm.emutls.var_align_fixed = true; > targetm.emutls.debug_form_tls_address = true; > Index: gcc/target.def > =================================================================== > --- gcc/target.def (revision 195904) > +++ gcc/target.def (working copy) > @@ -2741,12 +2741,12 @@ DEFHOOKPOD > "", > const char *, NULL) > > -/* Function to generate field definitions of the proxy variable. */ > +/* Function to generate type of the proxy variable. */ > DEFHOOK > -(var_fields, > +(object_type, > "", > - tree, (tree type, tree *name), > - default_emutls_var_fields) > + tree, (), > + default_emutls_object_type) > > /* Function to initialize a proxy variable. */ > DEFHOOK > Index: gcc/tree.c > =================================================================== > --- gcc/tree.c (revision 195904) > +++ gcc/tree.c (working copy) > @@ -11624,4 +11624,95 @@ warn_deprecated_use (tree node, tree att > } > } > > + > +/* Construct a record builder with the identifier IDENT. > + It is a union if IS_UNION is true, otherwise it is a RECORD_TYPE. > + QUAL_RECORD_TYPE is not supported. */ > + > +record_builder::record_builder (bool is_union) > +: building_ (lang_hooks.types.make_type (is_union ? UNION_TYPE : > RECORD_TYPE)), > + last_field_ (NULL) > +{ > +} > + > + > +/* Add a field with an identifier IDENT and type TYPE to the record. */ > + > +void > +record_builder::add_field (tree ident, tree type, source_location loc) > +{ > + tree this_field = build_decl (loc, FIELD_DECL, ident, type); > + DECL_CONTEXT (this_field) = building_; > + if (last_field_) > + DECL_CHAIN (last_field_) = this_field; > + else > + TYPE_FIELDS (building_) = this_field; > + last_field_ = this_field; > +} > + > +void > +record_builder::add_field (const char *ident, tree type, source_location loc) > +{ > + add_field (get_identifier (ident), type, loc); > +} > + > + > +/* Add a TYPE_NAME to the record. This can be a tag name directly from > IDENT, > + or a TYPE_DECL created with the IDENT. */ > + > +void > +record_builder::tag_name (tree ident) > +{ > + gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE); > + TYPE_NAME (building_) = ident; > +} > + > +void > +record_builder::tag_name (const char *ident) > +{ > + tag_name (get_identifier (ident)); > +} > + > +void > +record_builder::decl_name (tree ident, source_location loc) > +{ > + tree type_decl = build_decl (loc, TYPE_DECL, ident, building_); > + TYPE_NAME (building_) = type_decl; > +} > + > +void > +record_builder::decl_name (const char *ident, source_location loc) > +{ > + decl_name (get_identifier (ident), loc); > +} > + > + > +/* Layout the fields of the record, aligning with ALIGN_TYPE if given. > + Ensure that you call one of these functions after adding all fields. */ > + > +void > +record_builder::layout () > +{ > + layout_type (building_); > +} > + > +void > +record_builder::layout (tree align_type) > +{ > + TYPE_ALIGN (building_) = TYPE_ALIGN (align_type); > + TYPE_USER_ALIGN (building_) = TYPE_USER_ALIGN (align_type); > + layout (); > +} > + > + > +/* Return the record as a tree. You may call this function any time after > + construction of the builder. */ > + > +tree > +record_builder::as_tree () > +{ > + return building_; > +} > + > + > #include "gt-tree.h" > Index: gcc/tree.h > =================================================================== > --- gcc/tree.h (revision 195904) > +++ gcc/tree.h (working copy) > @@ -6529,4 +6529,28 @@ builtin_decl_implicit_p (enum built_in_f > && builtin_info.implicit_p[uns_fncode]); > } > > + > +/* A class for simplifying the construction of RECORD_TYPE and UNION_TYPE. > */ > + > +class record_builder > +{ > +public: > + record_builder (bool is_union = false); > + void add_field (tree ident, tree type, > + source_location loc = UNKNOWN_LOCATION); > + void add_field (const char *ident, tree type, > + source_location loc = UNKNOWN_LOCATION); > + void layout (); > + void layout (tree align_type); > + void tag_name (tree ident); > + void tag_name (const char *ident); > + void decl_name (tree ident, source_location loc = UNKNOWN_LOCATION); > + void decl_name (const char *ident, source_location loc = UNKNOWN_LOCATION); > + tree as_tree (); > +private: > + tree building_; > + tree last_field_; > +}; // class record_builder > + > + > #endif /* GCC_TREE_H */ > > -- > Lawrence Crowl