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