From patchwork Tue Feb 12 19:47:30 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lawrence Crowl X-Patchwork-Id: 219944 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B005C2C0085 for ; Wed, 13 Feb 2013 06:47:48 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1361303269; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:In-Reply-To:References:Date:Message-ID: Subject:From:To:Cc:Content-Type:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=CvjmPe/lpZNpUKSLb3Ol3LMQyLE=; b=Q3W0fD6Py1PZMEL AAlXft3prFeArsUzohfkRKXw8SEYTzYFbw4OtHpGjjKEdQoq2bOpro0wRRcrbRJY 3a98mVx5mTppsMN1LoYkWattyHyjZ4fV3Rskq96lIGLroTHdc60d6qBmiHXs/ovD dBVtBTcGAsSWC4f2g2rJvSqsXNkM= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:X-Google-DKIM-Signature:MIME-Version:X-Received:Received:In-Reply-To:References:Date:Message-ID:Subject:From:To:Cc:Content-Type:X-Gm-Message-State:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=DGAov1FcFijlV87qExt4x568nRZsHhCX1xeaKbE9ipZlPKhLgCT4ezuPL/+7zp 4ROliDjmFTPJXnFRCAEkiYD7qqQS1HP/xNuEmbKh1evgFBVxenuesi+3K5sDjYtz KT+DRgCLrAl5psqFfdYd6RlhaDiyZ4y8FlsGo/fSI0eDs=; Received: (qmail 22999 invoked by alias); 12 Feb 2013 19:47:42 -0000 Received: (qmail 22991 invoked by uid 22791); 12 Feb 2013 19:47:41 -0000 X-SWARE-Spam-Status: No, hits=-5.8 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_RCVD_TRUST, KHOP_THREADED, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RP_MATCHES_RCVD, TW_CF X-Spam-Check-By: sourceware.org Received: from mail-ie0-f176.google.com (HELO mail-ie0-f176.google.com) (209.85.223.176) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 12 Feb 2013 19:47:31 +0000 Received: by mail-ie0-f176.google.com with SMTP id k13so637688iea.21 for ; Tue, 12 Feb 2013 11:47:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-received:in-reply-to:references:date:message-id :subject:from:to:cc:content-type:x-gm-message-state; bh=accdmhKdGUeLaOS/UXvOuKS/sFzrDU47Caql4pnnbD8=; b=HeTTsD8OKrPXOnRRfa7bEY90bN5cVJDt2bBDlga5hTXt9hBnc7j871eiKHI0Iepwve mfSnDrqpbPe1tEJp0TdsLpvMkvzO95MlobWeUiK+Mip5GmX9m8m+5EMogrNfY+HY1mwm ndmLJT4TKKvjpzqgBRUId2KcAsgB6PzShvJzxKX1Q1/nQhz029aKWtf8huKgkc0BDBz4 7l/JvyfIaoQlMw7e6WwqKrJWC2g7mdEyIb1ZlqB4jqZ8DWHvs4MZg6deC22M5OO+hx11 WWWDe8XkLA7t5BtEcztRAkg54D3UYqZq2BNLoWg/eaAR7bEo3HbZfLQ1cnv/rQn3PPl7 xNuQ== MIME-Version: 1.0 X-Received: by 10.50.135.8 with SMTP id po8mr5849849igb.23.1360698450661; Tue, 12 Feb 2013 11:47:30 -0800 (PST) Received: by 10.231.247.66 with HTTP; Tue, 12 Feb 2013 11:47:30 -0800 (PST) In-Reply-To: <20130209065835.F0DCF12084A@jade.mtv.corp.google.com> References: <20130209065835.F0DCF12084A@jade.mtv.corp.google.com> Date: Tue, 12 Feb 2013 11:47:30 -0800 Message-ID: Subject: [cxx-conversion] Add Record Builder Class From: Lawrence Crowl To: dnovillo@google.com, nathan@codesourcery.com Cc: gcc-patches List X-Gm-Message-State: ALoCoQmrrmFUfoFSpB/K3w3ldFwgQZXk7WgE8agdgXpKDJDuI7YfHZusgWC3+QCQMxoAm/gmEvbHwFSwS73uDcT/tEaLltaoaoh+m5jw2XqqNtrWkAqQwKB6iAwJIcouXjipa3u0TIiRAfjM2AVVrBzFi52Jw03ovn47eB7IYX71gJy9RAy8OwM6J2tI63pU41COaeLcn9Kq X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 (); + 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 */