[cxx-conversion] Add Record Builder Class

Richard Biener richard.guenther@gmail.com
Thu Feb 14 09:26:00 GMT 2013


On Tue, Feb 12, 2013 at 8:47 PM, Lawrence Crowl <crowl@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



More information about the Gcc-patches mailing list