diff options
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r-- | gcc/varasm.c | 435 |
1 files changed, 11 insertions, 424 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c index f43f206..4742304 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -186,317 +186,6 @@ static GTY(()) int anchor_labelno; /* A pool of constants that can be shared between functions. */ static GTY(()) struct rtx_constant_pool *shared_constant_pool; -/* TLS emulation. */ - -static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) - htab_t emutls_htab; -static GTY (()) tree emutls_object_type; -/* Emulated TLS objects have the TLS model TLS_MODEL_EMULATED. This - macro can be used on them to distinguish the control variable from - the initialization template. */ -#define DECL_EMUTLS_VAR_P(D) (TREE_TYPE (D) == emutls_object_type) - -#if !defined (NO_DOT_IN_LABEL) -# define EMUTLS_SEPARATOR "." -#elif !defined (NO_DOLLAR_IN_LABEL) -# define EMUTLS_SEPARATOR "$" -#else -# define EMUTLS_SEPARATOR "_" -#endif - -/* Create an IDENTIFIER_NODE by prefixing PREFIX to the - IDENTIFIER_NODE NAME's name. */ - -static tree -prefix_name (const char *prefix, tree name) -{ - unsigned plen = strlen (prefix); - unsigned nlen = strlen (IDENTIFIER_POINTER (name)); - char *toname = (char *) alloca (plen + nlen + 1); - - memcpy (toname, prefix, plen); - memcpy (toname + plen, IDENTIFIER_POINTER (name), nlen + 1); - - return get_identifier (toname); -} - -/* Create an identifier for the struct __emutls_object, given an identifier - of the DECL_ASSEMBLY_NAME of the original object. */ - -static tree -get_emutls_object_name (tree name) -{ - const char *prefix = (targetm.emutls.var_prefix - ? targetm.emutls.var_prefix - : "__emutls_v" EMUTLS_SEPARATOR); - return prefix_name (prefix, name); -} - -tree -default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED) -{ - 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; -} - -/* Create the structure for struct __emutls_object. This should match the - structure at the top of emutls.c, modulo the union there. */ - -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; -} - -/* Create a read-only variable like DECL, with the same DECL_INITIAL. - This will be used for initializing the emulated tls data area. */ - -static tree -get_emutls_init_templ_addr (tree decl) -{ - tree name, to; - - if (targetm.emutls.register_common && !DECL_INITIAL (decl) - && !DECL_SECTION_NAME (decl)) - return null_pointer_node; - - name = DECL_ASSEMBLER_NAME (decl); - if (!targetm.emutls.tmpl_prefix || targetm.emutls.tmpl_prefix[0]) - { - const char *prefix = (targetm.emutls.tmpl_prefix - ? targetm.emutls.tmpl_prefix - : "__emutls_t" EMUTLS_SEPARATOR); - name = prefix_name (prefix, name); - } - - to = build_decl (DECL_SOURCE_LOCATION (decl), - VAR_DECL, name, TREE_TYPE (decl)); - SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to)); - - DECL_ARTIFICIAL (to) = 1; - TREE_USED (to) = TREE_USED (decl); - TREE_READONLY (to) = 1; - DECL_IGNORED_P (to) = 1; - DECL_CONTEXT (to) = DECL_CONTEXT (decl); - DECL_SECTION_NAME (to) = DECL_SECTION_NAME (decl); - DECL_PRESERVE_P (to) = DECL_PRESERVE_P (decl); - - DECL_WEAK (to) = DECL_WEAK (decl); - if (DECL_ONE_ONLY (decl)) - { - make_decl_one_only (to, DECL_ASSEMBLER_NAME (to)); - TREE_STATIC (to) = TREE_STATIC (decl); - TREE_PUBLIC (to) = TREE_PUBLIC (decl); - DECL_VISIBILITY (to) = DECL_VISIBILITY (decl); - } - else - TREE_STATIC (to) = 1; - - DECL_VISIBILITY_SPECIFIED (to) = DECL_VISIBILITY_SPECIFIED (decl); - DECL_INITIAL (to) = DECL_INITIAL (decl); - DECL_INITIAL (decl) = NULL; - - varpool_finalize_decl (to); - return build_fold_addr_expr (to); -} - -/* When emulating tls, we use a control structure for use by the runtime. - Create and return this structure. */ - -tree -emutls_decl (tree decl) -{ - tree name, to; - struct tree_map *h, in; - void **loc; - - if (targetm.have_tls || decl == NULL || decl == error_mark_node - || TREE_CODE (decl) != VAR_DECL || ! DECL_THREAD_LOCAL_P (decl)) - return decl; - - /* Look up the object in the hash; return the control structure if - it has already been created. */ - if (! emutls_htab) - emutls_htab = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0); - - name = DECL_ASSEMBLER_NAME (decl); - - /* Note that we use the hash of the decl's name, rather than a hash - of the decl's pointer. In emutls_finish we iterate through the - hash table, and we want this traversal to be predictable. */ - in.hash = IDENTIFIER_HASH_VALUE (name); - in.base.from = decl; - loc = htab_find_slot_with_hash (emutls_htab, &in, in.hash, INSERT); - h = (struct tree_map *) *loc; - if (h != NULL) - to = h->to; - else - { - to = build_decl (DECL_SOURCE_LOCATION (decl), - VAR_DECL, get_emutls_object_name (name), - get_emutls_object_type ()); - - h = ggc_alloc_tree_map (); - h->hash = in.hash; - h->base.from = decl; - h->to = to; - *(struct tree_map **) loc = h; - - DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED; - DECL_ARTIFICIAL (to) = 1; - DECL_IGNORED_P (to) = 1; - /* FIXME: work around PR44132. */ - DECL_PRESERVE_P (to) = 1; - TREE_READONLY (to) = 0; - SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to)); - if (DECL_ONE_ONLY (decl)) - make_decl_one_only (to, DECL_ASSEMBLER_NAME (to)); - DECL_CONTEXT (to) = DECL_CONTEXT (decl); - if (targetm.emutls.var_align_fixed) - /* If we're not allowed to change the proxy object's - alignment, pretend it's been set by the user. */ - DECL_USER_ALIGN (to) = 1; - } - - /* Note that these fields may need to be updated from time to time from - the original decl. Consider: - extern __thread int i; - int foo() { return i; } - __thread int i = 1; - in which I goes from external to locally defined and initialized. */ - DECL_DLLIMPORT_P (to) = DECL_DLLIMPORT_P (decl); - DECL_ATTRIBUTES (to) = targetm.merge_decl_attributes (decl, to); - - TREE_STATIC (to) = TREE_STATIC (decl); - TREE_USED (to) = TREE_USED (decl); - TREE_PUBLIC (to) = TREE_PUBLIC (decl); - DECL_EXTERNAL (to) = DECL_EXTERNAL (decl); - DECL_COMMON (to) = DECL_COMMON (decl); - DECL_WEAK (to) = DECL_WEAK (decl); - DECL_VISIBILITY (to) = DECL_VISIBILITY (decl); - DECL_VISIBILITY_SPECIFIED (to) = DECL_VISIBILITY_SPECIFIED (decl); - - /* Fortran might pass this to us. */ - DECL_RESTRICTED_P (to) = DECL_RESTRICTED_P (decl); - - return to; -} - -static int -emutls_common_1 (void **loc, void *xstmts) -{ - struct tree_map *h = *(struct tree_map **) loc; - tree x, *pstmts = (tree *) xstmts; - tree word_type_node; - - if (! DECL_COMMON (h->base.from) - || (DECL_INITIAL (h->base.from) - && DECL_INITIAL (h->base.from) != error_mark_node)) - return 1; - - word_type_node = lang_hooks.types.type_for_mode (word_mode, 1); - - /* The idea was to call get_emutls_init_templ_addr here, but if we - do this and there is an initializer, -fanchor_section loses, - because it would be too late to ensure the template is - output. */ - x = built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON]; - x = build_call_expr (x, 4, - build_fold_addr_expr (h->to), - fold_convert (word_type_node, - DECL_SIZE_UNIT (h->base.from)), - build_int_cst (word_type_node, - DECL_ALIGN_UNIT (h->base.from)), - null_pointer_node); - - append_to_statement_list (x, pstmts); - return 1; -} - -/* Callback to finalize one emutls control variable. */ - -static int -emutls_finalize_control_var (void **loc, - void *unused ATTRIBUTE_UNUSED) -{ - struct tree_map *h = *(struct tree_map **) loc; - if (h != NULL) - { - struct varpool_node *node = varpool_node (h->to); - /* Because varpool_finalize_decl () has side-effects, - only apply to un-finalized vars. */ - if (node && !node->finalized) - varpool_finalize_decl (h->to); - } - return 1; -} - -/* Finalize emutls control vars and add a static constructor if - required. */ - -void -emutls_finish (void) -{ - if (emutls_htab == NULL) - return; - htab_traverse_noresize (emutls_htab, - emutls_finalize_control_var, NULL); - - if (targetm.emutls.register_common) - { - tree body = NULL_TREE; - - htab_traverse_noresize (emutls_htab, emutls_common_1, &body); - if (body == NULL_TREE) - return; - - cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY); - } -} - /* Helper routines for maintaining section_htab. */ static int @@ -1210,11 +899,6 @@ get_variable_section (tree decl, bool prefer_noswitch_p) && ADDR_SPACE_GENERIC_P (as)); if (DECL_THREAD_LOCAL_P (decl)) return tls_comm_section; - /* This cannot be common bss for an emulated TLS object without - a register_common hook. */ - else if (DECL_TLS_MODEL (decl) == TLS_MODEL_EMULATED - && !targetm.emutls.register_common) - ; else if (TREE_PUBLIC (decl) && bss_initializer_p (decl)) return comm_section; } @@ -2098,40 +1782,6 @@ assemble_variable_contents (tree decl, const char *name, } } -/* Initialize emulated tls object TO, which refers to TLS variable - DECL and is initialized by PROXY. */ - -tree -default_emutls_var_init (tree to, tree decl, tree proxy) -{ - VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 4); - constructor_elt *elt; - tree type = TREE_TYPE (to); - tree field = TYPE_FIELDS (type); - - elt = VEC_quick_push (constructor_elt, v, NULL); - elt->index = field; - elt->value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl)); - - elt = VEC_quick_push (constructor_elt, v, NULL); - field = DECL_CHAIN (field); - elt->index = field; - elt->value = build_int_cst (TREE_TYPE (field), - DECL_ALIGN_UNIT (decl)); - - elt = VEC_quick_push (constructor_elt, v, NULL); - field = DECL_CHAIN (field); - elt->index = field; - elt->value = null_pointer_node; - - elt = VEC_quick_push (constructor_elt, v, NULL); - field = DECL_CHAIN (field); - elt->index = field; - elt->value = proxy; - - return build_constructor (type, v); -} - /* Assemble everything that is needed for a variable or function declaration. Not used for automatic variables, and not used for function definitions. Should not be called for variables of incomplete structure type. @@ -2153,35 +1803,9 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, /* This function is supposed to handle VARIABLES. Ensure we have one. */ gcc_assert (TREE_CODE (decl) == VAR_DECL); - if (! targetm.have_tls - && TREE_CODE (decl) == VAR_DECL - && DECL_THREAD_LOCAL_P (decl)) - { - tree to = emutls_decl (decl); - - /* If this variable is defined locally, then we need to initialize the - control structure with size and alignment information. We do this - at the last moment because tentative definitions can take a locally - defined but uninitialized variable and initialize it later, which - would result in incorrect contents. */ - if (! DECL_EXTERNAL (to) - && (! DECL_COMMON (to) - || (DECL_INITIAL (decl) - && DECL_INITIAL (decl) != error_mark_node))) - { - DECL_INITIAL (to) = targetm.emutls.var_init - (to, decl, get_emutls_init_templ_addr (decl)); - - /* Make sure the template is marked as needed early enough. - Without this, if the variable is placed in a - section-anchored block, the template will only be marked - when it's too late. */ - record_references_in_initializer (to, false); - } - - decl = to; - } - + /* Emulated TLS had better not get this far. */ + gcc_checking_assert (targetm.have_tls || !DECL_THREAD_LOCAL_P (decl)); + last_assemble_variable_decl = 0; /* Normally no need to say anything here for external references, @@ -5685,6 +5309,11 @@ find_decl_and_mark_needed (tree decl, tree target) static void do_assemble_alias (tree decl, tree target) { + /* Emulated TLS had better not get this var. */ + gcc_assert(!(!targetm.have_tls + && TREE_CODE (decl) == VAR_DECL + && DECL_THREAD_LOCAL_P (decl))); + if (TREE_ASM_WRITTEN (decl)) return; @@ -5699,14 +5328,6 @@ do_assemble_alias (tree decl, tree target) { ultimate_transparent_alias_target (&target); - if (!targetm.have_tls - && TREE_CODE (decl) == VAR_DECL - && DECL_THREAD_LOCAL_P (decl)) - { - decl = emutls_decl (decl); - target = get_emutls_object_name (target); - } - if (!TREE_SYMBOL_REFERENCED (target)) weakref_targets = tree_cons (decl, target, weakref_targets); @@ -5725,14 +5346,6 @@ do_assemble_alias (tree decl, tree target) return; } - if (!targetm.have_tls - && TREE_CODE (decl) == VAR_DECL - && DECL_THREAD_LOCAL_P (decl)) - { - decl = emutls_decl (decl); - target = get_emutls_object_name (target); - } - #ifdef ASM_OUTPUT_DEF /* Make name accessible from other files, if appropriate. */ @@ -6400,24 +6013,11 @@ categorize_decl_for_section (const_tree decl, int reloc) ret = SECCAT_RODATA; /* There are no read-only thread-local sections. */ - if (TREE_CODE (decl) == VAR_DECL && DECL_TLS_MODEL (decl)) + if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl)) { - if (DECL_TLS_MODEL (decl) == TLS_MODEL_EMULATED) - { - if (DECL_EMUTLS_VAR_P (decl)) - { - if (targetm.emutls.var_section) - ret = SECCAT_EMUTLS_VAR; - } - else - { - if (targetm.emutls.tmpl_prefix) - ret = SECCAT_EMUTLS_TMPL; - } - } /* Note that this would be *just* SECCAT_BSS, except that there's no concept of a read-only thread-local-data section. */ - else if (ret == SECCAT_BSS + if (ret == SECCAT_BSS || (flag_zero_initialized_in_bss && initializer_zerop (DECL_INITIAL (decl)))) ret = SECCAT_TBSS; @@ -6511,12 +6111,6 @@ default_elf_select_section (tree decl, int reloc, case SECCAT_TBSS: sname = ".tbss"; break; - case SECCAT_EMUTLS_VAR: - sname = targetm.emutls.var_section; - break; - case SECCAT_EMUTLS_TMPL: - sname = targetm.emutls.tmpl_section; - break; default: gcc_unreachable (); } @@ -6581,12 +6175,6 @@ default_unique_section (tree decl, int reloc) case SECCAT_TBSS: prefix = one_only ? ".tb" : ".tbss"; break; - case SECCAT_EMUTLS_VAR: - prefix = targetm.emutls.var_section; - break; - case SECCAT_EMUTLS_TMPL: - prefix = targetm.emutls.tmpl_section; - break; default: gcc_unreachable (); } @@ -6697,8 +6285,7 @@ default_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED) flags |= SYMBOL_FLAG_FUNCTION; if (targetm.binds_local_p (decl)) flags |= SYMBOL_FLAG_LOCAL; - if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl) - && DECL_TLS_MODEL (decl) != TLS_MODEL_EMULATED) + if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl)) flags |= DECL_TLS_MODEL (decl) << SYMBOL_FLAG_TLS_SHIFT; else if (targetm.in_small_data_p (decl)) flags |= SYMBOL_FLAG_SMALL; |