xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-emutls.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Lower TLS operations to emulation functions.
2*8feb0f0bSmrg    Copyright (C) 2006-2020 Free Software Foundation, Inc.
31debfc3dSmrg 
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg 
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it
71debfc3dSmrg under the terms of the GNU General Public License as published by the
81debfc3dSmrg Free Software Foundation; either version 3, or (at your option) any
91debfc3dSmrg later version.
101debfc3dSmrg 
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT
121debfc3dSmrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg 
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3.  If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>.  */
191debfc3dSmrg 
201debfc3dSmrg #include "config.h"
211debfc3dSmrg #include "system.h"
221debfc3dSmrg #include "coretypes.h"
231debfc3dSmrg #include "backend.h"
241debfc3dSmrg #include "target.h"
251debfc3dSmrg #include "tree.h"
261debfc3dSmrg #include "gimple.h"
271debfc3dSmrg #include "tree-pass.h"
281debfc3dSmrg #include "ssa.h"
291debfc3dSmrg #include "cgraph.h"
301debfc3dSmrg #include "fold-const.h"
311debfc3dSmrg #include "stor-layout.h"
321debfc3dSmrg #include "varasm.h"
331debfc3dSmrg #include "gimple-iterator.h"
341debfc3dSmrg #include "gimple-walk.h"
351debfc3dSmrg #include "langhooks.h"
361debfc3dSmrg #include "tree-iterator.h"
371debfc3dSmrg #include "gimplify.h"
381debfc3dSmrg 
391debfc3dSmrg /* Whenever a target does not support thread-local storage (TLS) natively,
401debfc3dSmrg    we can emulate it with some run-time support in libgcc.  This will in
411debfc3dSmrg    turn rely on "keyed storage" a-la pthread_key_create; essentially all
421debfc3dSmrg    thread libraries provide such functionality.
431debfc3dSmrg 
441debfc3dSmrg    In order to coordinate with the libgcc runtime, each TLS variable is
451debfc3dSmrg    described by a "control variable".  This control variable records the
461debfc3dSmrg    required size, alignment, and initial value of the TLS variable for
471debfc3dSmrg    instantiation at runtime.  It also stores an integer token to be used
481debfc3dSmrg    by the runtime to find the address of the variable within each thread.
491debfc3dSmrg 
501debfc3dSmrg    On the compiler side, this means that we need to replace all instances
511debfc3dSmrg    of "tls_var" in the code with "*__emutls_get_addr(&control_var)".  We
521debfc3dSmrg    also need to eliminate "tls_var" from the symbol table and introduce
531debfc3dSmrg    "control_var".
541debfc3dSmrg 
551debfc3dSmrg    We used to perform all of the transformations during conversion to rtl,
561debfc3dSmrg    and the variable substitutions magically within assemble_variable.
571debfc3dSmrg    However, this late fiddling of the symbol table conflicts with LTO and
581debfc3dSmrg    whole-program compilation.  Therefore we must now make all the changes
591debfc3dSmrg    to the symbol table early in the GIMPLE optimization path, before we
601debfc3dSmrg    write things out to LTO intermediate files.  */
611debfc3dSmrg 
621debfc3dSmrg /* Value for TLS varpool node where a pointer to control variable and
631debfc3dSmrg    access variable are stored.  */
641debfc3dSmrg struct tls_var_data
651debfc3dSmrg {
661debfc3dSmrg   varpool_node *control_var;
671debfc3dSmrg   tree access;
681debfc3dSmrg };
691debfc3dSmrg 
701debfc3dSmrg /* TLS map accesses mapping between a TLS varpool node and a pair
711debfc3dSmrg    made by control variable and access variable.  */
721debfc3dSmrg static hash_map<varpool_node *, tls_var_data> *tls_map = NULL;
731debfc3dSmrg 
741debfc3dSmrg /* The type of the control structure, shared with the emutls.c runtime.  */
751debfc3dSmrg static tree emutls_object_type;
761debfc3dSmrg 
771debfc3dSmrg #if !defined (NO_DOT_IN_LABEL)
781debfc3dSmrg # define EMUTLS_SEPARATOR	"."
791debfc3dSmrg #elif !defined (NO_DOLLAR_IN_LABEL)
801debfc3dSmrg # define EMUTLS_SEPARATOR	"$"
811debfc3dSmrg #else
821debfc3dSmrg # define EMUTLS_SEPARATOR	"_"
831debfc3dSmrg #endif
841debfc3dSmrg 
851debfc3dSmrg /* Create an IDENTIFIER_NODE by prefixing PREFIX to the
861debfc3dSmrg    IDENTIFIER_NODE NAME's name.  */
871debfc3dSmrg 
881debfc3dSmrg static tree
prefix_name(const char * prefix,tree name)891debfc3dSmrg prefix_name (const char *prefix, tree name)
901debfc3dSmrg {
911debfc3dSmrg   unsigned plen = strlen (prefix);
921debfc3dSmrg   unsigned nlen = strlen (IDENTIFIER_POINTER (name));
931debfc3dSmrg   char *toname = (char *) alloca (plen + nlen + 1);
941debfc3dSmrg 
951debfc3dSmrg   memcpy (toname, prefix, plen);
961debfc3dSmrg   memcpy (toname + plen, IDENTIFIER_POINTER (name), nlen + 1);
971debfc3dSmrg 
981debfc3dSmrg   return get_identifier (toname);
991debfc3dSmrg }
1001debfc3dSmrg 
1011debfc3dSmrg /* Create an identifier for the struct __emutls_object, given an identifier
1021debfc3dSmrg    of the DECL_ASSEMBLY_NAME of the original object.  */
1031debfc3dSmrg 
1041debfc3dSmrg static tree
get_emutls_object_name(tree name)1051debfc3dSmrg get_emutls_object_name (tree name)
1061debfc3dSmrg {
1071debfc3dSmrg   const char *prefix = (targetm.emutls.var_prefix
1081debfc3dSmrg 			? targetm.emutls.var_prefix
1091debfc3dSmrg 			: "__emutls_v" EMUTLS_SEPARATOR);
1101debfc3dSmrg   return prefix_name (prefix, name);
1111debfc3dSmrg }
1121debfc3dSmrg 
1131debfc3dSmrg /* Create the fields of the type for the control variables.  Ordinarily
1141debfc3dSmrg    this must match struct __emutls_object defined in emutls.c.  However
1151debfc3dSmrg    this is a target hook so that VxWorks can define its own layout.  */
1161debfc3dSmrg 
1171debfc3dSmrg tree
default_emutls_var_fields(tree type,tree * name ATTRIBUTE_UNUSED)1181debfc3dSmrg default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED)
1191debfc3dSmrg {
1201debfc3dSmrg   tree word_type_node, field, next_field;
1211debfc3dSmrg 
1221debfc3dSmrg   field = build_decl (UNKNOWN_LOCATION,
1231debfc3dSmrg 		      FIELD_DECL, get_identifier ("__templ"), ptr_type_node);
1241debfc3dSmrg   DECL_CONTEXT (field) = type;
1251debfc3dSmrg   next_field = field;
1261debfc3dSmrg 
1271debfc3dSmrg   field = build_decl (UNKNOWN_LOCATION,
1281debfc3dSmrg 		      FIELD_DECL, get_identifier ("__offset"),
1291debfc3dSmrg 		      ptr_type_node);
1301debfc3dSmrg   DECL_CONTEXT (field) = type;
1311debfc3dSmrg   DECL_CHAIN (field) = next_field;
1321debfc3dSmrg   next_field = field;
1331debfc3dSmrg 
1341debfc3dSmrg   word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
1351debfc3dSmrg   field = build_decl (UNKNOWN_LOCATION,
1361debfc3dSmrg 		      FIELD_DECL, get_identifier ("__align"),
1371debfc3dSmrg 		      word_type_node);
1381debfc3dSmrg   DECL_CONTEXT (field) = type;
1391debfc3dSmrg   DECL_CHAIN (field) = next_field;
1401debfc3dSmrg   next_field = field;
1411debfc3dSmrg 
1421debfc3dSmrg   field = build_decl (UNKNOWN_LOCATION,
1431debfc3dSmrg 		      FIELD_DECL, get_identifier ("__size"), word_type_node);
1441debfc3dSmrg   DECL_CONTEXT (field) = type;
1451debfc3dSmrg   DECL_CHAIN (field) = next_field;
1461debfc3dSmrg 
1471debfc3dSmrg   return field;
1481debfc3dSmrg }
1491debfc3dSmrg 
1501debfc3dSmrg /* Initialize emulated tls object TO, which refers to TLS variable DECL and
1511debfc3dSmrg    is initialized by PROXY.  As above, this is the default implementation of
1521debfc3dSmrg    a target hook overridden by VxWorks.  */
1531debfc3dSmrg 
1541debfc3dSmrg tree
default_emutls_var_init(tree to,tree decl,tree proxy)1551debfc3dSmrg default_emutls_var_init (tree to, tree decl, tree proxy)
1561debfc3dSmrg {
1571debfc3dSmrg   vec<constructor_elt, va_gc> *v;
1581debfc3dSmrg   vec_alloc (v, 4);
1591debfc3dSmrg   constructor_elt elt;
1601debfc3dSmrg   tree type = TREE_TYPE (to);
1611debfc3dSmrg   tree field = TYPE_FIELDS (type);
1621debfc3dSmrg 
1631debfc3dSmrg   elt.index = field;
1641debfc3dSmrg   elt.value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl));
1651debfc3dSmrg   v->quick_push (elt);
1661debfc3dSmrg 
1671debfc3dSmrg   field = DECL_CHAIN (field);
1681debfc3dSmrg   elt.index = field;
1691debfc3dSmrg   elt.value = build_int_cst (TREE_TYPE (field),
1701debfc3dSmrg 			     DECL_ALIGN_UNIT (decl));
1711debfc3dSmrg   v->quick_push (elt);
1721debfc3dSmrg 
1731debfc3dSmrg   field = DECL_CHAIN (field);
1741debfc3dSmrg   elt.index = field;
1751debfc3dSmrg   elt.value = null_pointer_node;
1761debfc3dSmrg   v->quick_push (elt);
1771debfc3dSmrg 
1781debfc3dSmrg   field = DECL_CHAIN (field);
1791debfc3dSmrg   elt.index = field;
1801debfc3dSmrg   elt.value = proxy;
1811debfc3dSmrg   v->quick_push (elt);
1821debfc3dSmrg 
1831debfc3dSmrg   return build_constructor (type, v);
1841debfc3dSmrg }
1851debfc3dSmrg 
1861debfc3dSmrg /* Create the structure for struct __emutls_object.  This should match the
1871debfc3dSmrg    structure at the top of emutls.c, modulo the union there.  */
1881debfc3dSmrg 
1891debfc3dSmrg static tree
get_emutls_object_type(void)1901debfc3dSmrg get_emutls_object_type (void)
1911debfc3dSmrg {
1921debfc3dSmrg   tree type, type_name, field;
1931debfc3dSmrg 
1941debfc3dSmrg   type = emutls_object_type;
1951debfc3dSmrg   if (type)
1961debfc3dSmrg     return type;
1971debfc3dSmrg 
1981debfc3dSmrg   emutls_object_type = type = lang_hooks.types.make_type (RECORD_TYPE);
1991debfc3dSmrg   type_name = NULL;
2001debfc3dSmrg   field = targetm.emutls.var_fields (type, &type_name);
2011debfc3dSmrg   if (!type_name)
2021debfc3dSmrg     type_name = get_identifier ("__emutls_object");
2031debfc3dSmrg   type_name = build_decl (UNKNOWN_LOCATION,
2041debfc3dSmrg 			  TYPE_DECL, type_name, type);
2051debfc3dSmrg   TYPE_NAME (type) = type_name;
2061debfc3dSmrg   TYPE_FIELDS (type) = field;
2071debfc3dSmrg   layout_type (type);
2081debfc3dSmrg 
2091debfc3dSmrg   return type;
2101debfc3dSmrg }
2111debfc3dSmrg 
2121debfc3dSmrg /* Create a read-only variable like DECL, with the same DECL_INITIAL.
2131debfc3dSmrg    This will be used for initializing the emulated tls data area.  */
2141debfc3dSmrg 
2151debfc3dSmrg static tree
get_emutls_init_templ_addr(tree decl)2161debfc3dSmrg get_emutls_init_templ_addr (tree decl)
2171debfc3dSmrg {
2181debfc3dSmrg   tree name, to;
2191debfc3dSmrg 
2201debfc3dSmrg   if (targetm.emutls.register_common && !DECL_INITIAL (decl)
2211debfc3dSmrg       && !DECL_SECTION_NAME (decl))
2221debfc3dSmrg     return null_pointer_node;
2231debfc3dSmrg 
2241debfc3dSmrg   name = DECL_ASSEMBLER_NAME (decl);
2251debfc3dSmrg   if (!targetm.emutls.tmpl_prefix || targetm.emutls.tmpl_prefix[0])
2261debfc3dSmrg     {
2271debfc3dSmrg       const char *prefix = (targetm.emutls.tmpl_prefix
2281debfc3dSmrg 			    ? targetm.emutls.tmpl_prefix
2291debfc3dSmrg 			    : "__emutls_t" EMUTLS_SEPARATOR);
2301debfc3dSmrg       name = prefix_name (prefix, name);
2311debfc3dSmrg     }
2321debfc3dSmrg 
2331debfc3dSmrg   to = build_decl (DECL_SOURCE_LOCATION (decl),
2341debfc3dSmrg 		   VAR_DECL, name, TREE_TYPE (decl));
2351debfc3dSmrg   SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
2361debfc3dSmrg 
2371debfc3dSmrg   DECL_ARTIFICIAL (to) = 1;
2381debfc3dSmrg   TREE_USED (to) = TREE_USED (decl);
2391debfc3dSmrg   TREE_READONLY (to) = 1;
2401debfc3dSmrg   DECL_IGNORED_P (to) = 1;
2411debfc3dSmrg   DECL_CONTEXT (to) = DECL_CONTEXT (decl);
2421debfc3dSmrg   DECL_PRESERVE_P (to) = DECL_PRESERVE_P (decl);
2431debfc3dSmrg 
2441debfc3dSmrg   DECL_WEAK (to) = DECL_WEAK (decl);
245*8feb0f0bSmrg   if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
2461debfc3dSmrg     {
2471debfc3dSmrg       TREE_STATIC (to) = TREE_STATIC (decl);
2481debfc3dSmrg       TREE_PUBLIC (to) = TREE_PUBLIC (decl);
2491debfc3dSmrg       DECL_VISIBILITY (to) = DECL_VISIBILITY (decl);
2501debfc3dSmrg     }
2511debfc3dSmrg   else
2521debfc3dSmrg     TREE_STATIC (to) = 1;
2531debfc3dSmrg 
254*8feb0f0bSmrg   if (DECL_ONE_ONLY (decl))
255*8feb0f0bSmrg     make_decl_one_only (to, DECL_ASSEMBLER_NAME (to));
256*8feb0f0bSmrg 
2571debfc3dSmrg   DECL_VISIBILITY_SPECIFIED (to) = DECL_VISIBILITY_SPECIFIED (decl);
2581debfc3dSmrg   DECL_INITIAL (to) = DECL_INITIAL (decl);
2591debfc3dSmrg   DECL_INITIAL (decl) = NULL;
2601debfc3dSmrg 
2611debfc3dSmrg   if (targetm.emutls.tmpl_section)
2621debfc3dSmrg     set_decl_section_name (to, targetm.emutls.tmpl_section);
2631debfc3dSmrg   else
2641debfc3dSmrg     set_decl_section_name (to, DECL_SECTION_NAME (decl));
2651debfc3dSmrg 
2661debfc3dSmrg   /* Create varpool node for the new variable and finalize it if it is
2671debfc3dSmrg      not external one.  */
2681debfc3dSmrg   if (DECL_EXTERNAL (to))
2691debfc3dSmrg     varpool_node::get_create (to);
2701debfc3dSmrg   else
2711debfc3dSmrg     varpool_node::add (to);
2721debfc3dSmrg   return build_fold_addr_expr (to);
2731debfc3dSmrg }
2741debfc3dSmrg 
2751debfc3dSmrg /* Create and return the control variable for the TLS variable DECL.  */
2761debfc3dSmrg 
2771debfc3dSmrg static tree
new_emutls_decl(tree decl,tree alias_of)2781debfc3dSmrg new_emutls_decl (tree decl, tree alias_of)
2791debfc3dSmrg {
2801debfc3dSmrg   tree name, to;
2811debfc3dSmrg 
2821debfc3dSmrg   name = DECL_ASSEMBLER_NAME (decl);
2831debfc3dSmrg   to = build_decl (DECL_SOURCE_LOCATION (decl), VAR_DECL,
2841debfc3dSmrg                    get_emutls_object_name (name),
2851debfc3dSmrg                    get_emutls_object_type ());
2861debfc3dSmrg 
2871debfc3dSmrg   SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
2881debfc3dSmrg 
2891debfc3dSmrg   DECL_ARTIFICIAL (to) = 1;
2901debfc3dSmrg   DECL_IGNORED_P (to) = 1;
2911debfc3dSmrg   TREE_READONLY (to) = 0;
2921debfc3dSmrg   TREE_STATIC (to) = 1;
2931debfc3dSmrg 
2941debfc3dSmrg   DECL_PRESERVE_P (to) = DECL_PRESERVE_P (decl);
2951debfc3dSmrg   DECL_CONTEXT (to) = DECL_CONTEXT (decl);
2961debfc3dSmrg   TREE_USED (to) = TREE_USED (decl);
2971debfc3dSmrg   TREE_PUBLIC (to) = TREE_PUBLIC (decl);
2981debfc3dSmrg   DECL_EXTERNAL (to) = DECL_EXTERNAL (decl);
2991debfc3dSmrg   DECL_COMMON (to) = DECL_COMMON (decl);
3001debfc3dSmrg   DECL_WEAK (to) = DECL_WEAK (decl);
3011debfc3dSmrg   DECL_VISIBILITY (to) = DECL_VISIBILITY (decl);
3021debfc3dSmrg   DECL_VISIBILITY_SPECIFIED (to) = DECL_VISIBILITY_SPECIFIED (decl);
3031debfc3dSmrg   DECL_DLLIMPORT_P (to) = DECL_DLLIMPORT_P (decl);
3041debfc3dSmrg 
3051debfc3dSmrg   DECL_ATTRIBUTES (to) = targetm.merge_decl_attributes (decl, to);
3061debfc3dSmrg 
3071debfc3dSmrg   if (DECL_ONE_ONLY (decl))
3081debfc3dSmrg     make_decl_one_only (to, DECL_ASSEMBLER_NAME (to));
3091debfc3dSmrg 
3101debfc3dSmrg   set_decl_tls_model (to, TLS_MODEL_EMULATED);
3111debfc3dSmrg 
3121debfc3dSmrg   /* If we're not allowed to change the proxy object's alignment,
3131debfc3dSmrg      pretend it has been set by the user.  */
3141debfc3dSmrg   if (targetm.emutls.var_align_fixed)
3151debfc3dSmrg     DECL_USER_ALIGN (to) = 1;
3161debfc3dSmrg 
3171debfc3dSmrg   /* If the target wants the control variables grouped, do so.  */
3181debfc3dSmrg   if (!DECL_COMMON (to) && targetm.emutls.var_section)
3191debfc3dSmrg     {
3201debfc3dSmrg       set_decl_section_name (to, targetm.emutls.var_section);
3211debfc3dSmrg     }
3221debfc3dSmrg 
3231debfc3dSmrg   /* If this variable is defined locally, then we need to initialize the
3241debfc3dSmrg      control structure with size and alignment information.  Initialization
3251debfc3dSmrg      of COMMON block variables happens elsewhere via a constructor.  */
3261debfc3dSmrg   if (!DECL_EXTERNAL (to)
327*8feb0f0bSmrg       && (!DECL_COMMON (to) || !targetm.emutls.register_common
3281debfc3dSmrg           || (DECL_INITIAL (decl)
3291debfc3dSmrg               && DECL_INITIAL (decl) != error_mark_node)))
3301debfc3dSmrg     {
3311debfc3dSmrg       tree tmpl = get_emutls_init_templ_addr (decl);
3321debfc3dSmrg       DECL_INITIAL (to) = targetm.emutls.var_init (to, decl, tmpl);
3331debfc3dSmrg       record_references_in_initializer (to, false);
3341debfc3dSmrg     }
3351debfc3dSmrg 
3361debfc3dSmrg   /* Create varpool node for the new variable and finalize it if it is
3371debfc3dSmrg      not external one.  */
3381debfc3dSmrg   if (DECL_EXTERNAL (to))
3391debfc3dSmrg     varpool_node::get_create (to);
3401debfc3dSmrg   else if (!alias_of)
3411debfc3dSmrg     varpool_node::add (to);
3421debfc3dSmrg   else
3431debfc3dSmrg     {
3441debfc3dSmrg       varpool_node *n;
3451debfc3dSmrg       varpool_node *t = varpool_node::get_for_asmname
3461debfc3dSmrg 	 (DECL_ASSEMBLER_NAME (DECL_VALUE_EXPR (alias_of)));
3471debfc3dSmrg 
3481debfc3dSmrg       n = varpool_node::create_alias (to, t->decl);
3491debfc3dSmrg       n->resolve_alias (t);
3501debfc3dSmrg     }
3511debfc3dSmrg   return to;
3521debfc3dSmrg }
3531debfc3dSmrg 
3541debfc3dSmrg /* Generate a call statement to initialize CONTROL_DECL for TLS_DECL.
3551debfc3dSmrg    This only needs to happen for TLS COMMON variables; non-COMMON
3561debfc3dSmrg    variables can be initialized statically.  Insert the generated
3571debfc3dSmrg    call statement at the end of PSTMTS.  */
3581debfc3dSmrg 
3591debfc3dSmrg static void
emutls_common_1(tree tls_decl,tree control_decl,tree * pstmts)3601debfc3dSmrg emutls_common_1 (tree tls_decl, tree control_decl, tree *pstmts)
3611debfc3dSmrg {
3621debfc3dSmrg   tree x;
3631debfc3dSmrg   tree word_type_node;
3641debfc3dSmrg 
365*8feb0f0bSmrg   if (!DECL_COMMON (tls_decl) || !targetm.emutls.register_common
3661debfc3dSmrg       || (DECL_INITIAL (tls_decl)
3671debfc3dSmrg 	  && DECL_INITIAL (tls_decl) != error_mark_node))
3681debfc3dSmrg     return;
3691debfc3dSmrg 
3701debfc3dSmrg   word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
3711debfc3dSmrg 
3721debfc3dSmrg   x = build_call_expr (builtin_decl_explicit (BUILT_IN_EMUTLS_REGISTER_COMMON),
3731debfc3dSmrg 		       4, build_fold_addr_expr (control_decl),
3741debfc3dSmrg 		       fold_convert (word_type_node,
3751debfc3dSmrg 				     DECL_SIZE_UNIT (tls_decl)),
3761debfc3dSmrg 		       build_int_cst (word_type_node,
3771debfc3dSmrg 				      DECL_ALIGN_UNIT (tls_decl)),
3781debfc3dSmrg 		       get_emutls_init_templ_addr (tls_decl));
3791debfc3dSmrg 
3801debfc3dSmrg   append_to_statement_list (x, pstmts);
3811debfc3dSmrg }
3821debfc3dSmrg 
3831debfc3dSmrg struct lower_emutls_data
3841debfc3dSmrg {
3851debfc3dSmrg   struct cgraph_node *cfun_node;
3861debfc3dSmrg   struct cgraph_node *builtin_node;
3871debfc3dSmrg   tree builtin_decl;
3881debfc3dSmrg   basic_block bb;
3891debfc3dSmrg   location_t loc;
3901debfc3dSmrg   gimple_seq seq;
3911debfc3dSmrg };
3921debfc3dSmrg 
3931debfc3dSmrg /* Given a TLS variable DECL, return an SSA_NAME holding its address.
3941debfc3dSmrg    Append any new computation statements required to D->SEQ.  */
3951debfc3dSmrg 
3961debfc3dSmrg static tree
gen_emutls_addr(tree decl,struct lower_emutls_data * d)3971debfc3dSmrg gen_emutls_addr (tree decl, struct lower_emutls_data *d)
3981debfc3dSmrg {
3991debfc3dSmrg   /* Compute the address of the TLS variable with help from runtime.  */
4001debfc3dSmrg   tls_var_data *data = tls_map->get (varpool_node::get (decl));
4011debfc3dSmrg   tree addr = data->access;
4021debfc3dSmrg 
4031debfc3dSmrg   if (addr == NULL)
4041debfc3dSmrg     {
4051debfc3dSmrg       varpool_node *cvar;
4061debfc3dSmrg       tree cdecl;
4071debfc3dSmrg       gcall *x;
4081debfc3dSmrg 
4091debfc3dSmrg       cvar = data->control_var;
4101debfc3dSmrg       cdecl = cvar->decl;
4111debfc3dSmrg       TREE_ADDRESSABLE (cdecl) = 1;
4121debfc3dSmrg 
4131debfc3dSmrg       addr = create_tmp_var (build_pointer_type (TREE_TYPE (decl)));
4141debfc3dSmrg       x = gimple_build_call (d->builtin_decl, 1, build_fold_addr_expr (cdecl));
4151debfc3dSmrg       gimple_set_location (x, d->loc);
4161debfc3dSmrg 
4171debfc3dSmrg       addr = make_ssa_name (addr, x);
4181debfc3dSmrg       gimple_call_set_lhs (x, addr);
4191debfc3dSmrg 
4201debfc3dSmrg       gimple_seq_add_stmt (&d->seq, x);
4211debfc3dSmrg 
422a2dc1f3fSmrg       d->cfun_node->create_edge (d->builtin_node, x, d->bb->count);
4231debfc3dSmrg 
4241debfc3dSmrg       /* We may be adding a new reference to a new variable to the function.
4251debfc3dSmrg          This means we have to play with the ipa-reference web.  */
4261debfc3dSmrg       d->cfun_node->create_reference (cvar, IPA_REF_ADDR, x);
4271debfc3dSmrg 
4281debfc3dSmrg       /* Record this ssa_name for possible use later in the basic block.  */
4291debfc3dSmrg       data->access = addr;
4301debfc3dSmrg     }
4311debfc3dSmrg 
4321debfc3dSmrg   return addr;
4331debfc3dSmrg }
4341debfc3dSmrg 
4351debfc3dSmrg /* Callback for lower_emutls_1, return non-NULL if there is any TLS
4361debfc3dSmrg    VAR_DECL in the subexpressions.  */
4371debfc3dSmrg 
4381debfc3dSmrg static tree
lower_emutls_2(tree * ptr,int * walk_subtrees,void *)4391debfc3dSmrg lower_emutls_2 (tree *ptr, int *walk_subtrees, void *)
4401debfc3dSmrg {
4411debfc3dSmrg   tree t = *ptr;
4421debfc3dSmrg   if (TREE_CODE (t) == VAR_DECL)
4431debfc3dSmrg     return DECL_THREAD_LOCAL_P (t) ? t : NULL_TREE;
4441debfc3dSmrg   else if (!EXPR_P (t))
4451debfc3dSmrg     *walk_subtrees = 0;
4461debfc3dSmrg   return NULL_TREE;
4471debfc3dSmrg }
4481debfc3dSmrg 
4491debfc3dSmrg /* Callback for walk_gimple_op.  D = WI->INFO is a struct lower_emutls_data.
4501debfc3dSmrg    Given an operand *PTR within D->STMT, if the operand references a TLS
4511debfc3dSmrg    variable, then lower the reference to a call to the runtime.  Insert
4521debfc3dSmrg    any new statements required into D->SEQ; the caller is responsible for
4531debfc3dSmrg    placing those appropriately.  */
4541debfc3dSmrg 
4551debfc3dSmrg static tree
lower_emutls_1(tree * ptr,int * walk_subtrees,void * cb_data)4561debfc3dSmrg lower_emutls_1 (tree *ptr, int *walk_subtrees, void *cb_data)
4571debfc3dSmrg {
4581debfc3dSmrg   struct walk_stmt_info *wi = (struct walk_stmt_info *) cb_data;
4591debfc3dSmrg   struct lower_emutls_data *d = (struct lower_emutls_data *) wi->info;
4601debfc3dSmrg   tree t = *ptr;
4611debfc3dSmrg   bool is_addr = false;
4621debfc3dSmrg   tree addr;
4631debfc3dSmrg 
4641debfc3dSmrg   *walk_subtrees = 0;
4651debfc3dSmrg 
4661debfc3dSmrg   switch (TREE_CODE (t))
4671debfc3dSmrg     {
4681debfc3dSmrg     case ADDR_EXPR:
4691debfc3dSmrg       /* If this is not a straight-forward "&var", but rather something
4701debfc3dSmrg 	 like "&var.a", then we may need special handling.  */
4711debfc3dSmrg       if (TREE_CODE (TREE_OPERAND (t, 0)) != VAR_DECL)
4721debfc3dSmrg 	{
4731debfc3dSmrg 	  bool save_changed;
4741debfc3dSmrg 
4751debfc3dSmrg 	  /* Gimple invariants are shareable trees, so before changing
4761debfc3dSmrg 	     anything in them if we will need to change anything, unshare
4771debfc3dSmrg 	     them.  */
4781debfc3dSmrg 	  if (is_gimple_min_invariant (t)
4791debfc3dSmrg 	      && walk_tree (&TREE_OPERAND (t, 0), lower_emutls_2, NULL, NULL))
4801debfc3dSmrg 	    *ptr = t = unshare_expr (t);
4811debfc3dSmrg 
4821debfc3dSmrg 	  /* If we're allowed more than just is_gimple_val, continue.  */
4831debfc3dSmrg 	  if (!wi->val_only)
4841debfc3dSmrg 	    {
4851debfc3dSmrg 	      *walk_subtrees = 1;
4861debfc3dSmrg 	      return NULL_TREE;
4871debfc3dSmrg 	    }
4881debfc3dSmrg 
4891debfc3dSmrg 	  /* See if any substitution would be made.  */
4901debfc3dSmrg 	  save_changed = wi->changed;
4911debfc3dSmrg 	  wi->changed = false;
4921debfc3dSmrg 	  wi->val_only = false;
4931debfc3dSmrg 	  walk_tree (&TREE_OPERAND (t, 0), lower_emutls_1, wi, NULL);
4941debfc3dSmrg 	  wi->val_only = true;
4951debfc3dSmrg 
4961debfc3dSmrg 	  /* If so, then extract this entire sub-expression "&p->a" into a
4971debfc3dSmrg 	     new assignment statement, and substitute yet another SSA_NAME.  */
4981debfc3dSmrg 	  if (wi->changed)
4991debfc3dSmrg 	    {
5001debfc3dSmrg 	      gimple *x;
5011debfc3dSmrg 
5021debfc3dSmrg 	      addr = create_tmp_var (TREE_TYPE (t));
5031debfc3dSmrg 	      x = gimple_build_assign (addr, t);
5041debfc3dSmrg 	      gimple_set_location (x, d->loc);
5051debfc3dSmrg 
5061debfc3dSmrg 	      addr = make_ssa_name (addr, x);
5071debfc3dSmrg 	      gimple_assign_set_lhs (x, addr);
5081debfc3dSmrg 
5091debfc3dSmrg 	      gimple_seq_add_stmt (&d->seq, x);
5101debfc3dSmrg 
5111debfc3dSmrg 	      *ptr = addr;
5121debfc3dSmrg 	    }
5131debfc3dSmrg 	  else
5141debfc3dSmrg 	    wi->changed = save_changed;
5151debfc3dSmrg 
5161debfc3dSmrg 	  return NULL_TREE;
5171debfc3dSmrg 	}
5181debfc3dSmrg 
5191debfc3dSmrg       t = TREE_OPERAND (t, 0);
5201debfc3dSmrg       is_addr = true;
5211debfc3dSmrg       /* FALLTHRU */
5221debfc3dSmrg 
5231debfc3dSmrg     case VAR_DECL:
5241debfc3dSmrg       if (!DECL_THREAD_LOCAL_P (t))
5251debfc3dSmrg 	return NULL_TREE;
5261debfc3dSmrg       break;
5271debfc3dSmrg 
5281debfc3dSmrg     default:
5291debfc3dSmrg       /* We're not interested in other decls or types, only subexpressions.  */
5301debfc3dSmrg       if (EXPR_P (t))
5311debfc3dSmrg         *walk_subtrees = 1;
5321debfc3dSmrg       /* FALLTHRU */
5331debfc3dSmrg 
5341debfc3dSmrg     case SSA_NAME:
5351debfc3dSmrg       /* Special-case the return of SSA_NAME, since it's so common.  */
5361debfc3dSmrg       return NULL_TREE;
5371debfc3dSmrg     }
5381debfc3dSmrg 
5391debfc3dSmrg   addr = gen_emutls_addr (t, d);
5401debfc3dSmrg   if (is_addr)
5411debfc3dSmrg     {
5421debfc3dSmrg       /* Replace "&var" with "addr" in the statement.  */
5431debfc3dSmrg       *ptr = addr;
5441debfc3dSmrg     }
5451debfc3dSmrg   else
5461debfc3dSmrg     {
5471debfc3dSmrg       /* Replace "var" with "*addr" in the statement.  */
5481debfc3dSmrg       t = build2 (MEM_REF, TREE_TYPE (t), addr,
5491debfc3dSmrg 	          build_int_cst (TREE_TYPE (addr), 0));
5501debfc3dSmrg       *ptr = t;
5511debfc3dSmrg     }
5521debfc3dSmrg 
5531debfc3dSmrg   wi->changed = true;
5541debfc3dSmrg   return NULL_TREE;
5551debfc3dSmrg }
5561debfc3dSmrg 
5571debfc3dSmrg /* Lower all of the operands of STMT.  */
5581debfc3dSmrg 
5591debfc3dSmrg static void
lower_emutls_stmt(gimple * stmt,struct lower_emutls_data * d)5601debfc3dSmrg lower_emutls_stmt (gimple *stmt, struct lower_emutls_data *d)
5611debfc3dSmrg {
5621debfc3dSmrg   struct walk_stmt_info wi;
5631debfc3dSmrg 
5641debfc3dSmrg   d->loc = gimple_location (stmt);
5651debfc3dSmrg 
5661debfc3dSmrg   memset (&wi, 0, sizeof (wi));
5671debfc3dSmrg   wi.info = d;
5681debfc3dSmrg   wi.val_only = true;
5691debfc3dSmrg   walk_gimple_op (stmt, lower_emutls_1, &wi);
5701debfc3dSmrg 
5711debfc3dSmrg   if (wi.changed)
5721debfc3dSmrg     update_stmt (stmt);
5731debfc3dSmrg }
5741debfc3dSmrg 
5751debfc3dSmrg /* Lower the I'th operand of PHI.  */
5761debfc3dSmrg 
5771debfc3dSmrg static void
lower_emutls_phi_arg(gphi * phi,unsigned int i,struct lower_emutls_data * d)5781debfc3dSmrg lower_emutls_phi_arg (gphi *phi, unsigned int i,
5791debfc3dSmrg 		      struct lower_emutls_data *d)
5801debfc3dSmrg {
5811debfc3dSmrg   struct walk_stmt_info wi;
5821debfc3dSmrg   struct phi_arg_d *pd = gimple_phi_arg (phi, i);
5831debfc3dSmrg 
5841debfc3dSmrg   /* Early out for a very common case we don't care about.  */
5851debfc3dSmrg   if (TREE_CODE (pd->def) == SSA_NAME)
5861debfc3dSmrg     return;
5871debfc3dSmrg 
5881debfc3dSmrg   d->loc = pd->locus;
5891debfc3dSmrg 
5901debfc3dSmrg   memset (&wi, 0, sizeof (wi));
5911debfc3dSmrg   wi.info = d;
5921debfc3dSmrg   wi.val_only = true;
5931debfc3dSmrg   walk_tree (&pd->def, lower_emutls_1, &wi, NULL);
5941debfc3dSmrg 
5951debfc3dSmrg   /* For normal statements, we let update_stmt do its job.  But for phi
5961debfc3dSmrg      nodes, we have to manipulate the immediate use list by hand.  */
5971debfc3dSmrg   if (wi.changed)
5981debfc3dSmrg     {
5991debfc3dSmrg       gcc_assert (TREE_CODE (pd->def) == SSA_NAME);
6001debfc3dSmrg       link_imm_use_stmt (&pd->imm_use, pd->def, phi);
6011debfc3dSmrg     }
6021debfc3dSmrg }
6031debfc3dSmrg 
6041debfc3dSmrg /* Reset access variable for a given TLS variable data DATA.  */
6051debfc3dSmrg 
6061debfc3dSmrg bool
reset_access(varpool_node * const &,tls_var_data * data,void *)6071debfc3dSmrg reset_access (varpool_node * const &, tls_var_data *data, void *)
6081debfc3dSmrg {
6091debfc3dSmrg   data->access = NULL;
6101debfc3dSmrg 
6111debfc3dSmrg   return true;
6121debfc3dSmrg }
6131debfc3dSmrg 
6141debfc3dSmrg /* Clear the access variables, in order to begin a new block.  */
6151debfc3dSmrg 
6161debfc3dSmrg static inline void
clear_access_vars(void)6171debfc3dSmrg clear_access_vars (void)
6181debfc3dSmrg {
6191debfc3dSmrg   tls_map->traverse<void *, reset_access> (NULL);
6201debfc3dSmrg }
6211debfc3dSmrg 
6221debfc3dSmrg /* Lower the entire function NODE.  */
6231debfc3dSmrg 
6241debfc3dSmrg static void
lower_emutls_function_body(struct cgraph_node * node)6251debfc3dSmrg lower_emutls_function_body (struct cgraph_node *node)
6261debfc3dSmrg {
6271debfc3dSmrg   struct lower_emutls_data d;
6281debfc3dSmrg   bool any_edge_inserts = false;
6291debfc3dSmrg 
6301debfc3dSmrg   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
6311debfc3dSmrg 
6321debfc3dSmrg   d.cfun_node = node;
6331debfc3dSmrg   d.builtin_decl = builtin_decl_explicit (BUILT_IN_EMUTLS_GET_ADDRESS);
6341debfc3dSmrg   /* This is where we introduce the declaration to the IL and so we have to
6351debfc3dSmrg      create a node for it.  */
6361debfc3dSmrg   d.builtin_node = cgraph_node::get_create (d.builtin_decl);
6371debfc3dSmrg 
6381debfc3dSmrg   FOR_EACH_BB_FN (d.bb, cfun)
6391debfc3dSmrg     {
6401debfc3dSmrg       unsigned int i, nedge;
6411debfc3dSmrg 
6421debfc3dSmrg       /* Lower each of the PHI nodes of the block, as we may have
6431debfc3dSmrg 	 propagated &tlsvar into a PHI argument.  These loops are
6441debfc3dSmrg 	 arranged so that we process each edge at once, and each
6451debfc3dSmrg 	 PHI argument for that edge.  */
6461debfc3dSmrg       if (!gimple_seq_empty_p (phi_nodes (d.bb)))
6471debfc3dSmrg 	{
6481debfc3dSmrg 	  nedge = EDGE_COUNT (d.bb->preds);
6491debfc3dSmrg 	  for (i = 0; i < nedge; ++i)
6501debfc3dSmrg 	    {
6511debfc3dSmrg 	      edge e = EDGE_PRED (d.bb, i);
6521debfc3dSmrg 
6531debfc3dSmrg 	      /* We can re-use any SSA_NAME created on this edge.  */
6541debfc3dSmrg 	      clear_access_vars ();
6551debfc3dSmrg 	      d.seq = NULL;
6561debfc3dSmrg 
6571debfc3dSmrg 	      for (gphi_iterator gsi = gsi_start_phis (d.bb);
6581debfc3dSmrg 		   !gsi_end_p (gsi);
6591debfc3dSmrg 		   gsi_next (&gsi))
6601debfc3dSmrg 		lower_emutls_phi_arg (gsi.phi (), i, &d);
6611debfc3dSmrg 
6621debfc3dSmrg 	      /* Insert all statements generated by all phi nodes for this
6631debfc3dSmrg 		 particular edge all at once.  */
6641debfc3dSmrg 	      if (d.seq)
6651debfc3dSmrg 		{
6661debfc3dSmrg 		  gsi_insert_seq_on_edge (e, d.seq);
6671debfc3dSmrg 		  any_edge_inserts = true;
6681debfc3dSmrg 		}
6691debfc3dSmrg 	    }
6701debfc3dSmrg 	}
6711debfc3dSmrg 
6721debfc3dSmrg       /* We can re-use any SSA_NAME created during this basic block.  */
6731debfc3dSmrg       clear_access_vars ();
6741debfc3dSmrg 
6751debfc3dSmrg       /* Lower each of the statements of the block.  */
6761debfc3dSmrg       for (gimple_stmt_iterator gsi = gsi_start_bb (d.bb); !gsi_end_p (gsi);
6771debfc3dSmrg 	   gsi_next (&gsi))
6781debfc3dSmrg 	{
6791debfc3dSmrg           d.seq = NULL;
6801debfc3dSmrg 	  lower_emutls_stmt (gsi_stmt (gsi), &d);
6811debfc3dSmrg 
6821debfc3dSmrg 	  /* If any new statements were created, insert them immediately
6831debfc3dSmrg 	     before the first use.  This prevents variable lifetimes from
6841debfc3dSmrg 	     becoming unnecessarily long.  */
6851debfc3dSmrg 	  if (d.seq)
6861debfc3dSmrg 	    gsi_insert_seq_before (&gsi, d.seq, GSI_SAME_STMT);
6871debfc3dSmrg 	}
6881debfc3dSmrg     }
6891debfc3dSmrg 
6901debfc3dSmrg   if (any_edge_inserts)
6911debfc3dSmrg     gsi_commit_edge_inserts ();
6921debfc3dSmrg 
6931debfc3dSmrg   pop_cfun ();
6941debfc3dSmrg }
6951debfc3dSmrg 
6961debfc3dSmrg /* Create emutls variable for VAR, DATA is pointer to static
6971debfc3dSmrg    ctor body we can add constructors to.
6981debfc3dSmrg    Callback for varpool_for_variable_and_aliases.  */
6991debfc3dSmrg 
7001debfc3dSmrg static bool
create_emultls_var(varpool_node * var,void * data)7011debfc3dSmrg create_emultls_var (varpool_node *var, void *data)
7021debfc3dSmrg {
7031debfc3dSmrg   tree cdecl;
7041debfc3dSmrg   tls_var_data value;
7051debfc3dSmrg 
7061debfc3dSmrg   cdecl = new_emutls_decl (var->decl,
7071debfc3dSmrg 			   var->alias && var->analyzed
7081debfc3dSmrg 			   ? var->get_alias_target ()->decl : NULL);
7091debfc3dSmrg 
7101debfc3dSmrg   varpool_node *cvar = varpool_node::get (cdecl);
7111debfc3dSmrg 
7121debfc3dSmrg   if (!var->alias)
7131debfc3dSmrg     {
7141debfc3dSmrg       /* Make sure the COMMON block control variable gets initialized.
7151debfc3dSmrg 	 Note that there's no point in doing this for aliases; we only
7161debfc3dSmrg 	 need to do this once for the main variable.  */
7171debfc3dSmrg       emutls_common_1 (var->decl, cdecl, (tree *)data);
7181debfc3dSmrg     }
7191debfc3dSmrg   if (var->alias && !var->analyzed)
7201debfc3dSmrg     cvar->alias = true;
7211debfc3dSmrg 
7221debfc3dSmrg   /* Indicate that the value of the TLS variable may be found elsewhere,
7231debfc3dSmrg      preventing the variable from re-appearing in the GIMPLE.  We cheat
7241debfc3dSmrg      and use the control variable here (rather than a full call_expr),
7251debfc3dSmrg      which is special-cased inside the DWARF2 output routines.  */
7261debfc3dSmrg   SET_DECL_VALUE_EXPR (var->decl, cdecl);
7271debfc3dSmrg   DECL_HAS_VALUE_EXPR_P (var->decl) = 1;
7281debfc3dSmrg 
7291debfc3dSmrg   value.control_var = cvar;
7301debfc3dSmrg   tls_map->put (var, value);
7311debfc3dSmrg 
7321debfc3dSmrg   return false;
7331debfc3dSmrg }
7341debfc3dSmrg 
7351debfc3dSmrg /* Main entry point to the tls lowering pass.  */
7361debfc3dSmrg 
7371debfc3dSmrg static unsigned int
ipa_lower_emutls(void)7381debfc3dSmrg ipa_lower_emutls (void)
7391debfc3dSmrg {
7401debfc3dSmrg   varpool_node *var;
7411debfc3dSmrg   cgraph_node *func;
7421debfc3dSmrg   bool any_aliases = false;
7431debfc3dSmrg   tree ctor_body = NULL;
7441debfc3dSmrg   hash_set <varpool_node *> visited;
7451debfc3dSmrg   auto_vec <varpool_node *> tls_vars;
7461debfc3dSmrg 
7471debfc3dSmrg   /* Examine all global variables for TLS variables.  */
7481debfc3dSmrg   FOR_EACH_VARIABLE (var)
7491debfc3dSmrg     if (DECL_THREAD_LOCAL_P (var->decl)
7501debfc3dSmrg 	&& !visited.add (var))
7511debfc3dSmrg       {
7521debfc3dSmrg 	gcc_checking_assert (TREE_STATIC (var->decl)
7531debfc3dSmrg 			     || DECL_EXTERNAL (var->decl));
7541debfc3dSmrg 	tls_vars.safe_push (var);
7551debfc3dSmrg 	if (var->alias && var->definition
7561debfc3dSmrg 	    && !visited.add (var->ultimate_alias_target ()))
7571debfc3dSmrg 	  tls_vars.safe_push (var->ultimate_alias_target ());
7581debfc3dSmrg       }
7591debfc3dSmrg 
7601debfc3dSmrg   /* If we found no TLS variables, then there is no further work to do.  */
7611debfc3dSmrg   if (tls_vars.is_empty ())
7621debfc3dSmrg     {
7631debfc3dSmrg       if (dump_file)
7641debfc3dSmrg 	fprintf (dump_file, "No TLS variables found.\n");
7651debfc3dSmrg       return 0;
7661debfc3dSmrg     }
7671debfc3dSmrg 
7681debfc3dSmrg   tls_map = new hash_map <varpool_node *, tls_var_data> ();
7691debfc3dSmrg 
7701debfc3dSmrg   /* Create the control variables for each TLS variable.  */
7711debfc3dSmrg   for (unsigned i = 0; i < tls_vars.length (); i++)
7721debfc3dSmrg     {
7731debfc3dSmrg       var = tls_vars[i];
7741debfc3dSmrg 
7751debfc3dSmrg       if (var->alias && !var->analyzed)
7761debfc3dSmrg 	any_aliases = true;
7771debfc3dSmrg       else if (!var->alias)
7781debfc3dSmrg 	var->call_for_symbol_and_aliases (create_emultls_var, &ctor_body, true);
7791debfc3dSmrg     }
7801debfc3dSmrg 
7811debfc3dSmrg   /* If there were any aliases, then frob the alias_pairs vector.  */
7821debfc3dSmrg   if (any_aliases)
7831debfc3dSmrg     {
7841debfc3dSmrg       alias_pair *p;
7851debfc3dSmrg       unsigned int i;
7861debfc3dSmrg       FOR_EACH_VEC_SAFE_ELT (alias_pairs, i, p)
7871debfc3dSmrg 	if (DECL_THREAD_LOCAL_P (p->decl))
7881debfc3dSmrg 	  {
7891debfc3dSmrg 	    p->decl = tls_map->get
7901debfc3dSmrg 	      (varpool_node::get (p->decl))->control_var->decl;
7911debfc3dSmrg 	    p->target = get_emutls_object_name (p->target);
7921debfc3dSmrg 	  }
7931debfc3dSmrg     }
7941debfc3dSmrg 
7951debfc3dSmrg   /* Adjust all uses of TLS variables within the function bodies.  */
7961debfc3dSmrg   FOR_EACH_DEFINED_FUNCTION (func)
7971debfc3dSmrg     if (func->lowered)
7981debfc3dSmrg       lower_emutls_function_body (func);
7991debfc3dSmrg 
8001debfc3dSmrg   /* Generate the constructor for any COMMON control variables created.  */
8011debfc3dSmrg   if (ctor_body)
8021debfc3dSmrg     cgraph_build_static_cdtor ('I', ctor_body, DEFAULT_INIT_PRIORITY);
8031debfc3dSmrg 
8041debfc3dSmrg   delete tls_map;
8051debfc3dSmrg 
8061debfc3dSmrg   return 0;
8071debfc3dSmrg }
8081debfc3dSmrg 
8091debfc3dSmrg namespace {
8101debfc3dSmrg 
8111debfc3dSmrg const pass_data pass_data_ipa_lower_emutls =
8121debfc3dSmrg {
8131debfc3dSmrg   SIMPLE_IPA_PASS, /* type */
8141debfc3dSmrg   "emutls", /* name */
8151debfc3dSmrg   OPTGROUP_NONE, /* optinfo_flags */
8161debfc3dSmrg   TV_IPA_OPT, /* tv_id */
8171debfc3dSmrg   ( PROP_cfg | PROP_ssa ), /* properties_required */
8181debfc3dSmrg   0, /* properties_provided */
8191debfc3dSmrg   0, /* properties_destroyed */
8201debfc3dSmrg   0, /* todo_flags_start */
8211debfc3dSmrg   0, /* todo_flags_finish */
8221debfc3dSmrg };
8231debfc3dSmrg 
8241debfc3dSmrg class pass_ipa_lower_emutls : public simple_ipa_opt_pass
8251debfc3dSmrg {
8261debfc3dSmrg public:
pass_ipa_lower_emutls(gcc::context * ctxt)8271debfc3dSmrg   pass_ipa_lower_emutls (gcc::context *ctxt)
8281debfc3dSmrg     : simple_ipa_opt_pass (pass_data_ipa_lower_emutls, ctxt)
8291debfc3dSmrg   {}
8301debfc3dSmrg 
8311debfc3dSmrg   /* opt_pass methods: */
gate(function *)8321debfc3dSmrg   virtual bool gate (function *)
8331debfc3dSmrg     {
8341debfc3dSmrg       /* If the target supports TLS natively, we need do nothing here.  */
8351debfc3dSmrg       return !targetm.have_tls;
8361debfc3dSmrg     }
8371debfc3dSmrg 
execute(function *)8381debfc3dSmrg   virtual unsigned int execute (function *) { return ipa_lower_emutls (); }
8391debfc3dSmrg 
8401debfc3dSmrg }; // class pass_ipa_lower_emutls
8411debfc3dSmrg 
8421debfc3dSmrg } // anon namespace
8431debfc3dSmrg 
8441debfc3dSmrg simple_ipa_opt_pass *
make_pass_ipa_lower_emutls(gcc::context * ctxt)8451debfc3dSmrg make_pass_ipa_lower_emutls (gcc::context *ctxt)
8461debfc3dSmrg {
8471debfc3dSmrg   return new pass_ipa_lower_emutls (ctxt);
8481debfc3dSmrg }
849