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