]>
Commit | Line | Data |
---|---|---|
cffbbb9d | 1 | /* Lower TLS operations to emulation functions. |
711789cc | 2 | Copyright (C) 2006-2013 Free Software Foundation, Inc. |
cffbbb9d | 3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU General Public License as published by the | |
8 | Free Software Foundation; either version 3, or (at your option) any | |
9 | later version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT | |
12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
23 | #include "tree.h" | |
9ed99284 | 24 | #include "stor-layout.h" |
25 | #include "varasm.h" | |
bc61cadb | 26 | #include "basic-block.h" |
27 | #include "tree-ssa-alias.h" | |
28 | #include "internal-fn.h" | |
29 | #include "gimple-expr.h" | |
30 | #include "is-a.h" | |
cffbbb9d | 31 | #include "gimple.h" |
dcf1a1ec | 32 | #include "gimple-iterator.h" |
33 | #include "gimple-walk.h" | |
cffbbb9d | 34 | #include "tree-pass.h" |
073c1fd5 | 35 | #include "gimple-ssa.h" |
cffbbb9d | 36 | #include "cgraph.h" |
073c1fd5 | 37 | #include "tree-phinodes.h" |
38 | #include "ssa-iterators.h" | |
9ed99284 | 39 | #include "stringpool.h" |
073c1fd5 | 40 | #include "tree-ssanames.h" |
cffbbb9d | 41 | #include "langhooks.h" |
42 | #include "target.h" | |
43 | #include "targhooks.h" | |
44 | #include "tree-iterator.h" | |
45 | ||
46 | ||
47 | /* Whenever a target does not support thread-local storage (TLS) natively, | |
48 | we can emulate it with some run-time support in libgcc. This will in | |
49 | turn rely on "keyed storage" a-la pthread_key_create; essentially all | |
50 | thread libraries provide such functionality. | |
51 | ||
52 | In order to coordinate with the libgcc runtime, each TLS variable is | |
53 | described by a "control variable". This control variable records the | |
54 | required size, alignment, and initial value of the TLS variable for | |
55 | instantiation at runtime. It also stores an integer token to be used | |
56 | by the runtime to find the address of the variable within each thread. | |
57 | ||
58 | On the compiler side, this means that we need to replace all instances | |
59 | of "tls_var" in the code with "*__emutls_get_addr(&control_var)". We | |
60 | also need to eliminate "tls_var" from the symbol table and introduce | |
61 | "control_var". | |
62 | ||
63 | We used to perform all of the transformations during conversion to rtl, | |
64 | and the variable substitutions magically within assemble_variable. | |
65 | However, this late fiddling of the symbol table conflicts with LTO and | |
66 | whole-program compilation. Therefore we must now make all the changes | |
67 | to the symbol table early in the GIMPLE optimization path, before we | |
68 | write things out to LTO intermediate files. */ | |
69 | ||
70 | /* These two vectors, once fully populated, are kept in lock-step so that | |
71 | the index of a TLS variable equals the index of its control variable in | |
72 | the other vector. */ | |
73 | static varpool_node_set tls_vars; | |
f1f41a6c | 74 | static vec<varpool_node_ptr> control_vars; |
cffbbb9d | 75 | |
76 | /* For the current basic block, an SSA_NAME that has computed the address | |
77 | of the TLS variable at the corresponding index. */ | |
f1f41a6c | 78 | static vec<tree> access_vars; |
cffbbb9d | 79 | |
80 | /* The type of the control structure, shared with the emutls.c runtime. */ | |
81 | static tree emutls_object_type; | |
82 | ||
83 | #if !defined (NO_DOT_IN_LABEL) | |
84 | # define EMUTLS_SEPARATOR "." | |
85 | #elif !defined (NO_DOLLAR_IN_LABEL) | |
86 | # define EMUTLS_SEPARATOR "$" | |
87 | #else | |
88 | # define EMUTLS_SEPARATOR "_" | |
89 | #endif | |
90 | ||
91 | /* Create an IDENTIFIER_NODE by prefixing PREFIX to the | |
92 | IDENTIFIER_NODE NAME's name. */ | |
93 | ||
94 | static tree | |
95 | prefix_name (const char *prefix, tree name) | |
96 | { | |
97 | unsigned plen = strlen (prefix); | |
98 | unsigned nlen = strlen (IDENTIFIER_POINTER (name)); | |
99 | char *toname = (char *) alloca (plen + nlen + 1); | |
100 | ||
101 | memcpy (toname, prefix, plen); | |
102 | memcpy (toname + plen, IDENTIFIER_POINTER (name), nlen + 1); | |
103 | ||
104 | return get_identifier (toname); | |
105 | } | |
106 | ||
107 | /* Create an identifier for the struct __emutls_object, given an identifier | |
108 | of the DECL_ASSEMBLY_NAME of the original object. */ | |
109 | ||
110 | static tree | |
111 | get_emutls_object_name (tree name) | |
112 | { | |
113 | const char *prefix = (targetm.emutls.var_prefix | |
114 | ? targetm.emutls.var_prefix | |
115 | : "__emutls_v" EMUTLS_SEPARATOR); | |
116 | return prefix_name (prefix, name); | |
117 | } | |
118 | ||
119 | /* Create the fields of the type for the control variables. Ordinarily | |
120 | this must match struct __emutls_object defined in emutls.c. However | |
121 | this is a target hook so that VxWorks can define its own layout. */ | |
122 | ||
123 | tree | |
124 | default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED) | |
125 | { | |
126 | tree word_type_node, field, next_field; | |
127 | ||
128 | field = build_decl (UNKNOWN_LOCATION, | |
129 | FIELD_DECL, get_identifier ("__templ"), ptr_type_node); | |
130 | DECL_CONTEXT (field) = type; | |
131 | next_field = field; | |
132 | ||
133 | field = build_decl (UNKNOWN_LOCATION, | |
134 | FIELD_DECL, get_identifier ("__offset"), | |
135 | ptr_type_node); | |
136 | DECL_CONTEXT (field) = type; | |
137 | DECL_CHAIN (field) = next_field; | |
138 | next_field = field; | |
139 | ||
140 | word_type_node = lang_hooks.types.type_for_mode (word_mode, 1); | |
141 | field = build_decl (UNKNOWN_LOCATION, | |
142 | FIELD_DECL, get_identifier ("__align"), | |
143 | word_type_node); | |
144 | DECL_CONTEXT (field) = type; | |
145 | DECL_CHAIN (field) = next_field; | |
146 | next_field = field; | |
147 | ||
148 | field = build_decl (UNKNOWN_LOCATION, | |
149 | FIELD_DECL, get_identifier ("__size"), word_type_node); | |
150 | DECL_CONTEXT (field) = type; | |
151 | DECL_CHAIN (field) = next_field; | |
152 | ||
153 | return field; | |
154 | } | |
155 | ||
156 | /* Initialize emulated tls object TO, which refers to TLS variable DECL and | |
157 | is initialized by PROXY. As above, this is the default implementation of | |
158 | a target hook overridden by VxWorks. */ | |
159 | ||
160 | tree | |
161 | default_emutls_var_init (tree to, tree decl, tree proxy) | |
162 | { | |
f1f41a6c | 163 | vec<constructor_elt, va_gc> *v; |
164 | vec_alloc (v, 4); | |
e82e4eb5 | 165 | constructor_elt elt; |
cffbbb9d | 166 | tree type = TREE_TYPE (to); |
167 | tree field = TYPE_FIELDS (type); | |
168 | ||
e82e4eb5 | 169 | elt.index = field; |
170 | elt.value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl)); | |
f1f41a6c | 171 | v->quick_push (elt); |
cffbbb9d | 172 | |
cffbbb9d | 173 | field = DECL_CHAIN (field); |
e82e4eb5 | 174 | elt.index = field; |
175 | elt.value = build_int_cst (TREE_TYPE (field), | |
176 | DECL_ALIGN_UNIT (decl)); | |
f1f41a6c | 177 | v->quick_push (elt); |
cffbbb9d | 178 | |
cffbbb9d | 179 | field = DECL_CHAIN (field); |
e82e4eb5 | 180 | elt.index = field; |
181 | elt.value = null_pointer_node; | |
f1f41a6c | 182 | v->quick_push (elt); |
cffbbb9d | 183 | |
cffbbb9d | 184 | field = DECL_CHAIN (field); |
e82e4eb5 | 185 | elt.index = field; |
186 | elt.value = proxy; | |
f1f41a6c | 187 | v->quick_push (elt); |
cffbbb9d | 188 | |
189 | return build_constructor (type, v); | |
190 | } | |
191 | ||
192 | /* Create the structure for struct __emutls_object. This should match the | |
193 | structure at the top of emutls.c, modulo the union there. */ | |
194 | ||
195 | static tree | |
196 | get_emutls_object_type (void) | |
197 | { | |
198 | tree type, type_name, field; | |
199 | ||
200 | type = emutls_object_type; | |
201 | if (type) | |
202 | return type; | |
203 | ||
204 | emutls_object_type = type = lang_hooks.types.make_type (RECORD_TYPE); | |
205 | type_name = NULL; | |
206 | field = targetm.emutls.var_fields (type, &type_name); | |
207 | if (!type_name) | |
208 | type_name = get_identifier ("__emutls_object"); | |
209 | type_name = build_decl (UNKNOWN_LOCATION, | |
210 | TYPE_DECL, type_name, type); | |
211 | TYPE_NAME (type) = type_name; | |
212 | TYPE_FIELDS (type) = field; | |
213 | layout_type (type); | |
214 | ||
215 | return type; | |
216 | } | |
217 | ||
218 | /* Create a read-only variable like DECL, with the same DECL_INITIAL. | |
219 | This will be used for initializing the emulated tls data area. */ | |
220 | ||
221 | static tree | |
222 | get_emutls_init_templ_addr (tree decl) | |
223 | { | |
224 | tree name, to; | |
225 | ||
226 | if (targetm.emutls.register_common && !DECL_INITIAL (decl) | |
227 | && !DECL_SECTION_NAME (decl)) | |
228 | return null_pointer_node; | |
229 | ||
230 | name = DECL_ASSEMBLER_NAME (decl); | |
231 | if (!targetm.emutls.tmpl_prefix || targetm.emutls.tmpl_prefix[0]) | |
232 | { | |
233 | const char *prefix = (targetm.emutls.tmpl_prefix | |
234 | ? targetm.emutls.tmpl_prefix | |
235 | : "__emutls_t" EMUTLS_SEPARATOR); | |
236 | name = prefix_name (prefix, name); | |
237 | } | |
238 | ||
239 | to = build_decl (DECL_SOURCE_LOCATION (decl), | |
240 | VAR_DECL, name, TREE_TYPE (decl)); | |
241 | SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to)); | |
242 | ||
243 | DECL_ARTIFICIAL (to) = 1; | |
244 | TREE_USED (to) = TREE_USED (decl); | |
245 | TREE_READONLY (to) = 1; | |
246 | DECL_IGNORED_P (to) = 1; | |
247 | DECL_CONTEXT (to) = DECL_CONTEXT (decl); | |
248 | DECL_SECTION_NAME (to) = DECL_SECTION_NAME (decl); | |
249 | DECL_PRESERVE_P (to) = DECL_PRESERVE_P (decl); | |
250 | ||
251 | DECL_WEAK (to) = DECL_WEAK (decl); | |
252 | if (DECL_ONE_ONLY (decl)) | |
253 | { | |
254 | make_decl_one_only (to, DECL_ASSEMBLER_NAME (to)); | |
255 | TREE_STATIC (to) = TREE_STATIC (decl); | |
256 | TREE_PUBLIC (to) = TREE_PUBLIC (decl); | |
257 | DECL_VISIBILITY (to) = DECL_VISIBILITY (decl); | |
258 | } | |
259 | else | |
260 | TREE_STATIC (to) = 1; | |
261 | ||
262 | DECL_VISIBILITY_SPECIFIED (to) = DECL_VISIBILITY_SPECIFIED (decl); | |
263 | DECL_INITIAL (to) = DECL_INITIAL (decl); | |
264 | DECL_INITIAL (decl) = NULL; | |
265 | ||
266 | if (targetm.emutls.tmpl_section) | |
267 | { | |
268 | DECL_SECTION_NAME (to) | |
269 | = build_string (strlen (targetm.emutls.tmpl_section), | |
270 | targetm.emutls.tmpl_section); | |
271 | } | |
272 | ||
a5c9e220 | 273 | /* Create varpool node for the new variable and finalize it if it is |
274 | not external one. */ | |
275 | if (DECL_EXTERNAL (to)) | |
2dc9831f | 276 | varpool_node_for_decl (to); |
a5c9e220 | 277 | else |
124f4875 | 278 | varpool_add_new_variable (to); |
cffbbb9d | 279 | return build_fold_addr_expr (to); |
280 | } | |
281 | ||
282 | /* Create and return the control variable for the TLS variable DECL. */ | |
283 | ||
284 | static tree | |
478e80e0 | 285 | new_emutls_decl (tree decl, tree alias_of) |
cffbbb9d | 286 | { |
287 | tree name, to; | |
288 | ||
289 | name = DECL_ASSEMBLER_NAME (decl); | |
290 | to = build_decl (DECL_SOURCE_LOCATION (decl), VAR_DECL, | |
291 | get_emutls_object_name (name), | |
292 | get_emutls_object_type ()); | |
293 | ||
294 | SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to)); | |
295 | ||
296 | DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED; | |
297 | DECL_ARTIFICIAL (to) = 1; | |
298 | DECL_IGNORED_P (to) = 1; | |
299 | TREE_READONLY (to) = 0; | |
300 | TREE_STATIC (to) = 1; | |
301 | ||
302 | DECL_PRESERVE_P (to) = DECL_PRESERVE_P (decl); | |
303 | DECL_CONTEXT (to) = DECL_CONTEXT (decl); | |
304 | TREE_USED (to) = TREE_USED (decl); | |
305 | TREE_PUBLIC (to) = TREE_PUBLIC (decl); | |
306 | DECL_EXTERNAL (to) = DECL_EXTERNAL (decl); | |
307 | DECL_COMMON (to) = DECL_COMMON (decl); | |
308 | DECL_WEAK (to) = DECL_WEAK (decl); | |
309 | DECL_VISIBILITY (to) = DECL_VISIBILITY (decl); | |
310 | DECL_VISIBILITY_SPECIFIED (to) = DECL_VISIBILITY_SPECIFIED (decl); | |
cffbbb9d | 311 | DECL_DLLIMPORT_P (to) = DECL_DLLIMPORT_P (decl); |
312 | ||
313 | DECL_ATTRIBUTES (to) = targetm.merge_decl_attributes (decl, to); | |
314 | ||
315 | if (DECL_ONE_ONLY (decl)) | |
316 | make_decl_one_only (to, DECL_ASSEMBLER_NAME (to)); | |
317 | ||
318 | /* If we're not allowed to change the proxy object's alignment, | |
319 | pretend it has been set by the user. */ | |
320 | if (targetm.emutls.var_align_fixed) | |
321 | DECL_USER_ALIGN (to) = 1; | |
322 | ||
323 | /* If the target wants the control variables grouped, do so. */ | |
324 | if (!DECL_COMMON (to) && targetm.emutls.var_section) | |
325 | { | |
326 | DECL_SECTION_NAME (to) | |
448e3e57 | 327 | = build_string (strlen (targetm.emutls.var_section), |
328 | targetm.emutls.var_section); | |
cffbbb9d | 329 | } |
330 | ||
331 | /* If this variable is defined locally, then we need to initialize the | |
332 | control structure with size and alignment information. Initialization | |
333 | of COMMON block variables happens elsewhere via a constructor. */ | |
334 | if (!DECL_EXTERNAL (to) | |
335 | && (!DECL_COMMON (to) | |
336 | || (DECL_INITIAL (decl) | |
337 | && DECL_INITIAL (decl) != error_mark_node))) | |
338 | { | |
339 | tree tmpl = get_emutls_init_templ_addr (decl); | |
340 | DECL_INITIAL (to) = targetm.emutls.var_init (to, decl, tmpl); | |
341 | record_references_in_initializer (to, false); | |
342 | } | |
343 | ||
a5c9e220 | 344 | /* Create varpool node for the new variable and finalize it if it is |
345 | not external one. */ | |
346 | if (DECL_EXTERNAL (to)) | |
2dc9831f | 347 | varpool_node_for_decl (to); |
478e80e0 | 348 | else if (!alias_of) |
124f4875 | 349 | varpool_add_new_variable (to); |
478e80e0 | 350 | else |
351 | varpool_create_variable_alias (to, | |
352 | varpool_node_for_asm | |
02774f2d | 353 | (DECL_ASSEMBLER_NAME (DECL_VALUE_EXPR (alias_of)))->decl); |
cffbbb9d | 354 | return to; |
355 | } | |
356 | ||
357 | /* Look up the index of the TLS variable DECL. This index can then be | |
358 | used in both the control_vars and access_vars arrays. */ | |
359 | ||
360 | static unsigned int | |
361 | emutls_index (tree decl) | |
362 | { | |
363 | varpool_node_set_iterator i; | |
364 | ||
365 | i = varpool_node_set_find (tls_vars, varpool_get_node (decl)); | |
366 | gcc_assert (i.index != ~0u); | |
367 | ||
368 | return i.index; | |
369 | } | |
370 | ||
371 | /* Look up the control variable for the TLS variable DECL. */ | |
372 | ||
373 | static tree | |
374 | emutls_decl (tree decl) | |
375 | { | |
098f44bc | 376 | varpool_node *var; |
cffbbb9d | 377 | unsigned int i; |
378 | ||
379 | i = emutls_index (decl); | |
f1f41a6c | 380 | var = control_vars[i]; |
02774f2d | 381 | return var->decl; |
cffbbb9d | 382 | } |
383 | ||
384 | /* Generate a call statement to initialize CONTROL_DECL for TLS_DECL. | |
385 | This only needs to happen for TLS COMMON variables; non-COMMON | |
386 | variables can be initialized statically. Insert the generated | |
387 | call statement at the end of PSTMTS. */ | |
388 | ||
389 | static void | |
390 | emutls_common_1 (tree tls_decl, tree control_decl, tree *pstmts) | |
391 | { | |
392 | tree x; | |
393 | tree word_type_node; | |
394 | ||
395 | if (! DECL_COMMON (tls_decl) | |
396 | || (DECL_INITIAL (tls_decl) | |
397 | && DECL_INITIAL (tls_decl) != error_mark_node)) | |
398 | return; | |
399 | ||
400 | word_type_node = lang_hooks.types.type_for_mode (word_mode, 1); | |
401 | ||
b9a16870 | 402 | x = build_call_expr (builtin_decl_explicit (BUILT_IN_EMUTLS_REGISTER_COMMON), |
403 | 4, build_fold_addr_expr (control_decl), | |
cffbbb9d | 404 | fold_convert (word_type_node, |
405 | DECL_SIZE_UNIT (tls_decl)), | |
406 | build_int_cst (word_type_node, | |
407 | DECL_ALIGN_UNIT (tls_decl)), | |
408 | get_emutls_init_templ_addr (tls_decl)); | |
409 | ||
410 | append_to_statement_list (x, pstmts); | |
411 | } | |
412 | ||
413 | struct lower_emutls_data | |
414 | { | |
415 | struct cgraph_node *cfun_node; | |
416 | struct cgraph_node *builtin_node; | |
417 | tree builtin_decl; | |
418 | basic_block bb; | |
419 | int bb_freq; | |
420 | location_t loc; | |
421 | gimple_seq seq; | |
422 | }; | |
423 | ||
424 | /* Given a TLS variable DECL, return an SSA_NAME holding its address. | |
425 | Append any new computation statements required to D->SEQ. */ | |
426 | ||
427 | static tree | |
428 | gen_emutls_addr (tree decl, struct lower_emutls_data *d) | |
429 | { | |
430 | unsigned int index; | |
431 | tree addr; | |
432 | ||
433 | /* Compute the address of the TLS variable with help from runtime. */ | |
434 | index = emutls_index (decl); | |
f1f41a6c | 435 | addr = access_vars[index]; |
cffbbb9d | 436 | if (addr == NULL) |
437 | { | |
098f44bc | 438 | varpool_node *cvar; |
cffbbb9d | 439 | tree cdecl; |
440 | gimple x; | |
441 | ||
f1f41a6c | 442 | cvar = control_vars[index]; |
02774f2d | 443 | cdecl = cvar->decl; |
cffbbb9d | 444 | TREE_ADDRESSABLE (cdecl) = 1; |
445 | ||
446 | addr = create_tmp_var (build_pointer_type (TREE_TYPE (decl)), NULL); | |
447 | x = gimple_build_call (d->builtin_decl, 1, build_fold_addr_expr (cdecl)); | |
448 | gimple_set_location (x, d->loc); | |
449 | ||
450 | addr = make_ssa_name (addr, x); | |
451 | gimple_call_set_lhs (x, addr); | |
452 | ||
453 | gimple_seq_add_stmt (&d->seq, x); | |
454 | ||
455 | cgraph_create_edge (d->cfun_node, d->builtin_node, x, | |
0835ad03 | 456 | d->bb->count, d->bb_freq); |
cffbbb9d | 457 | |
458 | /* We may be adding a new reference to a new variable to the function. | |
459 | This means we have to play with the ipa-reference web. */ | |
02774f2d | 460 | ipa_record_reference (d->cfun_node, cvar, IPA_REF_ADDR, x); |
cffbbb9d | 461 | |
462 | /* Record this ssa_name for possible use later in the basic block. */ | |
f1f41a6c | 463 | access_vars[index] = addr; |
cffbbb9d | 464 | } |
465 | ||
466 | return addr; | |
467 | } | |
468 | ||
469 | /* Callback for walk_gimple_op. D = WI->INFO is a struct lower_emutls_data. | |
470 | Given an operand *PTR within D->STMT, if the operand references a TLS | |
471 | variable, then lower the reference to a call to the runtime. Insert | |
472 | any new statements required into D->SEQ; the caller is responsible for | |
473 | placing those appropriately. */ | |
474 | ||
475 | static tree | |
476 | lower_emutls_1 (tree *ptr, int *walk_subtrees, void *cb_data) | |
477 | { | |
478 | struct walk_stmt_info *wi = (struct walk_stmt_info *) cb_data; | |
479 | struct lower_emutls_data *d = (struct lower_emutls_data *) wi->info; | |
480 | tree t = *ptr; | |
481 | bool is_addr = false; | |
482 | tree addr; | |
483 | ||
484 | *walk_subtrees = 0; | |
485 | ||
486 | switch (TREE_CODE (t)) | |
487 | { | |
488 | case ADDR_EXPR: | |
489 | /* If this is not a straight-forward "&var", but rather something | |
490 | like "&var.a", then we may need special handling. */ | |
491 | if (TREE_CODE (TREE_OPERAND (t, 0)) != VAR_DECL) | |
492 | { | |
493 | bool save_changed; | |
494 | ||
495 | /* If we're allowed more than just is_gimple_val, continue. */ | |
496 | if (!wi->val_only) | |
497 | { | |
498 | *walk_subtrees = 1; | |
499 | return NULL_TREE; | |
500 | } | |
501 | ||
502 | /* See if any substitution would be made. */ | |
503 | save_changed = wi->changed; | |
504 | wi->changed = false; | |
505 | wi->val_only = false; | |
506 | walk_tree (&TREE_OPERAND (t, 0), lower_emutls_1, wi, NULL); | |
507 | wi->val_only = true; | |
508 | ||
509 | /* If so, then extract this entire sub-expression "&p->a" into a | |
510 | new assignment statement, and substitute yet another SSA_NAME. */ | |
511 | if (wi->changed) | |
512 | { | |
513 | gimple x; | |
514 | ||
515 | addr = create_tmp_var (TREE_TYPE (t), NULL); | |
516 | x = gimple_build_assign (addr, t); | |
517 | gimple_set_location (x, d->loc); | |
518 | ||
519 | addr = make_ssa_name (addr, x); | |
520 | gimple_assign_set_lhs (x, addr); | |
521 | ||
522 | gimple_seq_add_stmt (&d->seq, x); | |
523 | ||
524 | *ptr = addr; | |
525 | } | |
526 | else | |
527 | wi->changed = save_changed; | |
528 | ||
529 | return NULL_TREE; | |
530 | } | |
531 | ||
532 | t = TREE_OPERAND (t, 0); | |
533 | is_addr = true; | |
534 | /* FALLTHRU */ | |
535 | ||
536 | case VAR_DECL: | |
537 | if (!DECL_THREAD_LOCAL_P (t)) | |
538 | return NULL_TREE; | |
539 | break; | |
540 | ||
541 | default: | |
542 | /* We're not interested in other decls or types, only subexpressions. */ | |
543 | if (EXPR_P (t)) | |
544 | *walk_subtrees = 1; | |
545 | /* FALLTHRU */ | |
546 | ||
547 | case SSA_NAME: | |
548 | /* Special-case the return of SSA_NAME, since it's so common. */ | |
549 | return NULL_TREE; | |
550 | } | |
551 | ||
552 | addr = gen_emutls_addr (t, d); | |
553 | if (is_addr) | |
554 | { | |
555 | /* Replace "&var" with "addr" in the statement. */ | |
556 | *ptr = addr; | |
557 | } | |
558 | else | |
559 | { | |
560 | /* Replace "var" with "*addr" in the statement. */ | |
561 | t = build2 (MEM_REF, TREE_TYPE (t), addr, | |
562 | build_int_cst (TREE_TYPE (addr), 0)); | |
563 | *ptr = t; | |
564 | } | |
565 | ||
566 | wi->changed = true; | |
567 | return NULL_TREE; | |
568 | } | |
569 | ||
570 | /* Lower all of the operands of STMT. */ | |
571 | ||
572 | static void | |
573 | lower_emutls_stmt (gimple stmt, struct lower_emutls_data *d) | |
574 | { | |
575 | struct walk_stmt_info wi; | |
576 | ||
577 | d->loc = gimple_location (stmt); | |
578 | ||
579 | memset (&wi, 0, sizeof (wi)); | |
580 | wi.info = d; | |
581 | wi.val_only = true; | |
582 | walk_gimple_op (stmt, lower_emutls_1, &wi); | |
583 | ||
584 | if (wi.changed) | |
585 | update_stmt (stmt); | |
586 | } | |
587 | ||
588 | /* Lower the I'th operand of PHI. */ | |
589 | ||
590 | static void | |
591 | lower_emutls_phi_arg (gimple phi, unsigned int i, struct lower_emutls_data *d) | |
592 | { | |
593 | struct walk_stmt_info wi; | |
594 | struct phi_arg_d *pd = gimple_phi_arg (phi, i); | |
595 | ||
596 | /* Early out for a very common case we don't care about. */ | |
597 | if (TREE_CODE (pd->def) == SSA_NAME) | |
598 | return; | |
599 | ||
600 | d->loc = pd->locus; | |
601 | ||
602 | memset (&wi, 0, sizeof (wi)); | |
603 | wi.info = d; | |
604 | wi.val_only = true; | |
605 | walk_tree (&pd->def, lower_emutls_1, &wi, NULL); | |
606 | ||
607 | /* For normal statements, we let update_stmt do its job. But for phi | |
608 | nodes, we have to manipulate the immediate use list by hand. */ | |
609 | if (wi.changed) | |
610 | { | |
611 | gcc_assert (TREE_CODE (pd->def) == SSA_NAME); | |
612 | link_imm_use_stmt (&pd->imm_use, pd->def, phi); | |
613 | } | |
614 | } | |
615 | ||
616 | /* Clear the ACCESS_VARS array, in order to begin a new block. */ | |
617 | ||
618 | static inline void | |
619 | clear_access_vars (void) | |
620 | { | |
f1f41a6c | 621 | memset (access_vars.address (), 0, |
9af5ce0c | 622 | access_vars.length () * sizeof (tree)); |
cffbbb9d | 623 | } |
624 | ||
625 | /* Lower the entire function NODE. */ | |
626 | ||
627 | static void | |
628 | lower_emutls_function_body (struct cgraph_node *node) | |
629 | { | |
630 | struct lower_emutls_data d; | |
631 | bool any_edge_inserts = false; | |
632 | ||
02774f2d | 633 | push_cfun (DECL_STRUCT_FUNCTION (node->decl)); |
cffbbb9d | 634 | |
635 | d.cfun_node = node; | |
b9a16870 | 636 | d.builtin_decl = builtin_decl_explicit (BUILT_IN_EMUTLS_GET_ADDRESS); |
4559c6fc | 637 | /* This is where we introduce the declaration to the IL and so we have to |
638 | create a node for it. */ | |
639 | d.builtin_node = cgraph_get_create_node (d.builtin_decl); | |
cffbbb9d | 640 | |
fc00614f | 641 | FOR_EACH_BB_FN (d.bb, cfun) |
cffbbb9d | 642 | { |
643 | gimple_stmt_iterator gsi; | |
644 | unsigned int i, nedge; | |
645 | ||
646 | /* Lower each of the PHI nodes of the block, as we may have | |
647 | propagated &tlsvar into a PHI argument. These loops are | |
648 | arranged so that we process each edge at once, and each | |
649 | PHI argument for that edge. */ | |
650 | if (!gimple_seq_empty_p (phi_nodes (d.bb))) | |
651 | { | |
652 | /* The calls will be inserted on the edges, and the frequencies | |
653 | will be computed during the commit process. */ | |
654 | d.bb_freq = 0; | |
655 | ||
656 | nedge = EDGE_COUNT (d.bb->preds); | |
657 | for (i = 0; i < nedge; ++i) | |
658 | { | |
659 | edge e = EDGE_PRED (d.bb, i); | |
660 | ||
661 | /* We can re-use any SSA_NAME created on this edge. */ | |
662 | clear_access_vars (); | |
663 | d.seq = NULL; | |
664 | ||
665 | for (gsi = gsi_start_phis (d.bb); | |
666 | !gsi_end_p (gsi); | |
667 | gsi_next (&gsi)) | |
668 | lower_emutls_phi_arg (gsi_stmt (gsi), i, &d); | |
669 | ||
670 | /* Insert all statements generated by all phi nodes for this | |
671 | particular edge all at once. */ | |
672 | if (d.seq) | |
673 | { | |
674 | gsi_insert_seq_on_edge (e, d.seq); | |
675 | any_edge_inserts = true; | |
676 | } | |
677 | } | |
678 | } | |
679 | ||
680 | d.bb_freq = compute_call_stmt_bb_frequency (current_function_decl, d.bb); | |
681 | ||
682 | /* We can re-use any SSA_NAME created during this basic block. */ | |
683 | clear_access_vars (); | |
684 | ||
685 | /* Lower each of the statements of the block. */ | |
686 | for (gsi = gsi_start_bb (d.bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |
687 | { | |
688 | d.seq = NULL; | |
689 | lower_emutls_stmt (gsi_stmt (gsi), &d); | |
690 | ||
691 | /* If any new statements were created, insert them immediately | |
692 | before the first use. This prevents variable lifetimes from | |
693 | becoming unnecessarily long. */ | |
694 | if (d.seq) | |
695 | gsi_insert_seq_before (&gsi, d.seq, GSI_SAME_STMT); | |
696 | } | |
697 | } | |
698 | ||
699 | if (any_edge_inserts) | |
700 | gsi_commit_edge_inserts (); | |
701 | ||
702 | pop_cfun (); | |
cffbbb9d | 703 | } |
704 | ||
478e80e0 | 705 | /* Create emutls variable for VAR, DATA is pointer to static |
706 | ctor body we can add constructors to. | |
707 | Callback for varpool_for_variable_and_aliases. */ | |
708 | ||
709 | static bool | |
098f44bc | 710 | create_emultls_var (varpool_node *var, void *data) |
478e80e0 | 711 | { |
712 | tree cdecl; | |
098f44bc | 713 | varpool_node *cvar; |
478e80e0 | 714 | |
02774f2d | 715 | cdecl = new_emutls_decl (var->decl, |
716 | var->alias && var->analyzed | |
717 | ? varpool_alias_target (var)->decl : NULL); | |
478e80e0 | 718 | |
719 | cvar = varpool_get_node (cdecl); | |
f1f41a6c | 720 | control_vars.quick_push (cvar); |
478e80e0 | 721 | |
02774f2d | 722 | if (!var->alias) |
478e80e0 | 723 | { |
724 | /* Make sure the COMMON block control variable gets initialized. | |
725 | Note that there's no point in doing this for aliases; we only | |
726 | need to do this once for the main variable. */ | |
02774f2d | 727 | emutls_common_1 (var->decl, cdecl, (tree *)data); |
478e80e0 | 728 | } |
02774f2d | 729 | if (var->alias && !var->analyzed) |
730 | cvar->alias = true; | |
478e80e0 | 731 | |
732 | /* Indicate that the value of the TLS variable may be found elsewhere, | |
733 | preventing the variable from re-appearing in the GIMPLE. We cheat | |
734 | and use the control variable here (rather than a full call_expr), | |
735 | which is special-cased inside the DWARF2 output routines. */ | |
02774f2d | 736 | SET_DECL_VALUE_EXPR (var->decl, cdecl); |
737 | DECL_HAS_VALUE_EXPR_P (var->decl) = 1; | |
478e80e0 | 738 | return false; |
739 | } | |
740 | ||
cffbbb9d | 741 | /* Main entry point to the tls lowering pass. */ |
742 | ||
743 | static unsigned int | |
744 | ipa_lower_emutls (void) | |
745 | { | |
098f44bc | 746 | varpool_node *var; |
cffbbb9d | 747 | struct cgraph_node *func; |
748 | bool any_aliases = false; | |
749 | tree ctor_body = NULL; | |
750 | unsigned int i, n_tls; | |
751 | ||
752 | tls_vars = varpool_node_set_new (); | |
753 | ||
754 | /* Examine all global variables for TLS variables. */ | |
7c455d87 | 755 | FOR_EACH_VARIABLE (var) |
02774f2d | 756 | if (DECL_THREAD_LOCAL_P (var->decl)) |
cffbbb9d | 757 | { |
02774f2d | 758 | gcc_checking_assert (TREE_STATIC (var->decl) |
759 | || DECL_EXTERNAL (var->decl)); | |
cffbbb9d | 760 | varpool_node_set_add (tls_vars, var); |
02774f2d | 761 | if (var->alias && var->definition) |
478e80e0 | 762 | varpool_node_set_add (tls_vars, varpool_variable_node (var, NULL)); |
cffbbb9d | 763 | } |
764 | ||
765 | /* If we found no TLS variables, then there is no further work to do. */ | |
f1f41a6c | 766 | if (!tls_vars->nodes.exists ()) |
cffbbb9d | 767 | { |
768 | tls_vars = NULL; | |
769 | if (dump_file) | |
770 | fprintf (dump_file, "No TLS variables found.\n"); | |
771 | return 0; | |
772 | } | |
773 | ||
774 | /* Allocate the on-the-side arrays that share indicies with the TLS vars. */ | |
f1f41a6c | 775 | n_tls = tls_vars->nodes.length (); |
776 | control_vars.create (n_tls); | |
777 | access_vars.create (n_tls); | |
778 | access_vars.safe_grow_cleared (n_tls); | |
cffbbb9d | 779 | |
780 | /* Create the control variables for each TLS variable. */ | |
f1f41a6c | 781 | FOR_EACH_VEC_ELT (tls_vars->nodes, i, var) |
cffbbb9d | 782 | { |
f1f41a6c | 783 | var = tls_vars->nodes[i]; |
cffbbb9d | 784 | |
02774f2d | 785 | if (var->alias && !var->analyzed) |
478e80e0 | 786 | any_aliases = true; |
02774f2d | 787 | else if (!var->alias) |
478e80e0 | 788 | varpool_for_node_and_aliases (var, create_emultls_var, &ctor_body, true); |
cffbbb9d | 789 | } |
790 | ||
791 | /* If there were any aliases, then frob the alias_pairs vector. */ | |
792 | if (any_aliases) | |
793 | { | |
794 | alias_pair *p; | |
f1f41a6c | 795 | FOR_EACH_VEC_SAFE_ELT (alias_pairs, i, p) |
cffbbb9d | 796 | if (DECL_THREAD_LOCAL_P (p->decl)) |
797 | { | |
798 | p->decl = emutls_decl (p->decl); | |
799 | p->target = get_emutls_object_name (p->target); | |
800 | } | |
801 | } | |
802 | ||
803 | /* Adjust all uses of TLS variables within the function bodies. */ | |
7c455d87 | 804 | FOR_EACH_DEFINED_FUNCTION (func) |
da751785 | 805 | if (func->lowered) |
cffbbb9d | 806 | lower_emutls_function_body (func); |
807 | ||
808 | /* Generate the constructor for any COMMON control variables created. */ | |
809 | if (ctor_body) | |
810 | cgraph_build_static_cdtor ('I', ctor_body, DEFAULT_INIT_PRIORITY); | |
811 | ||
f1f41a6c | 812 | control_vars.release (); |
813 | access_vars.release (); | |
19ad01f7 | 814 | free_varpool_node_set (tls_vars); |
cffbbb9d | 815 | |
ef3baff5 | 816 | return TODO_verify_all; |
cffbbb9d | 817 | } |
818 | ||
819 | /* If the target supports TLS natively, we need do nothing here. */ | |
820 | ||
821 | static bool | |
822 | gate_emutls (void) | |
823 | { | |
824 | return !targetm.have_tls; | |
825 | } | |
826 | ||
cbe8bda8 | 827 | namespace { |
828 | ||
829 | const pass_data pass_data_ipa_lower_emutls = | |
cffbbb9d | 830 | { |
cbe8bda8 | 831 | SIMPLE_IPA_PASS, /* type */ |
832 | "emutls", /* name */ | |
833 | OPTGROUP_NONE, /* optinfo_flags */ | |
834 | true, /* has_gate */ | |
835 | true, /* has_execute */ | |
836 | TV_IPA_OPT, /* tv_id */ | |
837 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
838 | 0, /* properties_provided */ | |
839 | 0, /* properties_destroyed */ | |
840 | 0, /* todo_flags_start */ | |
841 | 0, /* todo_flags_finish */ | |
cffbbb9d | 842 | }; |
cbe8bda8 | 843 | |
844 | class pass_ipa_lower_emutls : public simple_ipa_opt_pass | |
845 | { | |
846 | public: | |
9af5ce0c | 847 | pass_ipa_lower_emutls (gcc::context *ctxt) |
848 | : simple_ipa_opt_pass (pass_data_ipa_lower_emutls, ctxt) | |
cbe8bda8 | 849 | {} |
850 | ||
851 | /* opt_pass methods: */ | |
852 | bool gate () { return gate_emutls (); } | |
853 | unsigned int execute () { return ipa_lower_emutls (); } | |
854 | ||
855 | }; // class pass_ipa_lower_emutls | |
856 | ||
857 | } // anon namespace | |
858 | ||
859 | simple_ipa_opt_pass * | |
860 | make_pass_ipa_lower_emutls (gcc::context *ctxt) | |
861 | { | |
862 | return new pass_ipa_lower_emutls (ctxt); | |
863 | } |