+/* 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 = 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 (FIELD_DECL, get_identifier ("__templ"), ptr_type_node);
+ DECL_CONTEXT (field) = type;
+ next_field = field;
+
+ field = build_decl (FIELD_DECL, get_identifier ("__offset"),
+ ptr_type_node);
+ DECL_CONTEXT (field) = type;
+ TREE_CHAIN (field) = next_field;
+ next_field = field;
+
+ word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
+ field = build_decl (FIELD_DECL, get_identifier ("__align"),
+ word_type_node);
+ DECL_CONTEXT (field) = type;
+ TREE_CHAIN (field) = next_field;
+ next_field = field;
+
+ field = build_decl (FIELD_DECL, get_identifier ("__size"), word_type_node);
+ DECL_CONTEXT (field) = type;
+ TREE_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 (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 (VAR_DECL, name, TREE_TYPE (decl));
+ SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
+ DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED;
+ 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_WEAK (to) = DECL_WEAK (decl);
+ if (DECL_ONE_ONLY (decl))
+ {
+ make_decl_one_only (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_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 = htab_hash_string (IDENTIFIER_POINTER (name));
+ in.base.from = decl;
+ loc = htab_find_slot_with_hash (emutls_htab, &in, in.hash, INSERT);
+ h = *loc;
+ if (h != NULL)
+ to = h->to;
+ else
+ {
+ to = build_decl (VAR_DECL, get_emutls_object_name (name),
+ get_emutls_object_type ());
+
+ h = ggc_alloc (sizeof (struct 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;
+ TREE_READONLY (to) = 0;
+ SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
+ if (DECL_ONE_ONLY (decl))
+ make_decl_one_only (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. */
+
+ 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);
+
+ return to;
+}
+
+static int
+emutls_common_1 (void **loc, void *xstmts)
+{
+ struct tree_map *h = *(struct tree_map **) loc;
+ tree args, 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 = null_pointer_node;
+ args = tree_cons (NULL, x, NULL);
+ x = build_int_cst (word_type_node, DECL_ALIGN_UNIT (h->base.from));
+ args = tree_cons (NULL, x, args);
+ x = fold_convert (word_type_node, DECL_SIZE_UNIT (h->base.from));
+ args = tree_cons (NULL, x, args);
+ x = build_fold_addr_expr (h->to);
+ args = tree_cons (NULL, x, args);
+
+ x = built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON];
+ x = build_function_call_expr (x, args);
+
+ append_to_statement_list (x, pstmts);
+ return 1;
+}
+
+void
+emutls_finish (void)
+{
+ if (!targetm.emutls.register_common)
+ {
+ tree body = NULL_TREE;
+
+ if (emutls_htab == NULL)
+ return;
+
+ htab_traverse_noresize (emutls_htab, emutls_common_1, &body);
+ if (body == NULL_TREE)
+ return;
+
+ cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
+ }
+}
+