File: | build/gcc/symtab-thunks.cc |
Warning: | line 462, column 12 Although the value stored to 'then_bb' is used in the enclosing expression, the value is never actually read from 'then_bb' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Support for thunks in symbol table. |
2 | Copyright (C) 2003-2023 Free Software Foundation, Inc. |
3 | Contributed by Jan Hubicka |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it under |
8 | the terms of the GNU General Public License as published by the Free |
9 | Software Foundation; either version 3, or (at your option) any later |
10 | version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ |
20 | |
21 | #include "config.h" |
22 | #include "system.h" |
23 | #include "coretypes.h" |
24 | #include "backend.h" |
25 | #include "tree.h" |
26 | #include "gimple.h" |
27 | #include "predict.h" |
28 | #include "target.h" |
29 | #include "rtl.h" |
30 | #include "alloc-pool.h" |
31 | #include "cgraph.h" |
32 | #include "symbol-summary.h" |
33 | #include "symtab-thunks.h" |
34 | #include "lto-streamer.h" |
35 | #include "fold-const.h" |
36 | #include "gimple-iterator.h" |
37 | #include "stor-layout.h" |
38 | #include "gimplify-me.h" |
39 | #include "varasm.h" |
40 | #include "output.h" |
41 | #include "cfg.h" |
42 | #include "cfghooks.h" |
43 | #include "gimple-ssa.h" |
44 | #include "gimple-fold.h" |
45 | #include "cfgloop.h" |
46 | #include "tree-into-ssa.h" |
47 | #include "tree-cfg.h" |
48 | #include "cfgcleanup.h" |
49 | #include "tree-pass.h" |
50 | #include "data-streamer.h" |
51 | #include "langhooks.h" |
52 | |
53 | /* Used for vtable lookup in thunk adjusting. */ |
54 | static GTY (()) tree vtable_entry_type; |
55 | struct GTY (()) unprocessed_thunk |
56 | { |
57 | cgraph_node *node; |
58 | thunk_info *info; |
59 | }; |
60 | /* To be PCH safe we store thunks into a vector before end of compilation |
61 | unit. */ |
62 | static GTY (()) vec<unprocessed_thunk, va_gc> *thunks; |
63 | |
64 | namespace { |
65 | |
66 | /* Function summary for thunk_infos. */ |
67 | class GTY((user)) thunk_infos_t: public function_summary <thunk_info *> |
68 | { |
69 | public: |
70 | thunk_infos_t (symbol_table *table, bool ggc): |
71 | function_summary<thunk_info *> (table, ggc) { } |
72 | |
73 | /* Hook that is called by summary when a node is duplicated. */ |
74 | void duplicate (cgraph_node *node, |
75 | cgraph_node *node2, |
76 | thunk_info *data, |
77 | thunk_info *data2) final override; |
78 | }; |
79 | |
80 | /* Duplication hook. */ |
81 | void |
82 | thunk_infos_t::duplicate (cgraph_node *, cgraph_node *, |
83 | thunk_info *src, thunk_info *dst) |
84 | { |
85 | *dst = *src; |
86 | } |
87 | |
88 | } /* anon namespace */ |
89 | |
90 | /* Return thunk_info possibly creating new one. */ |
91 | thunk_info * |
92 | thunk_info::get_create (cgraph_node *node) |
93 | { |
94 | if (!symtab->m_thunks) |
95 | { |
96 | symtab->m_thunks |
97 | = new (ggc_alloc_no_dtor <thunk_infos_t> ()) |
98 | thunk_infos_t (symtab, true); |
99 | symtab->m_thunks->disable_insertion_hook (); |
100 | } |
101 | return symtab->m_thunks->get_create (node); |
102 | } |
103 | |
104 | /* Stream out THIS to OB. */ |
105 | void |
106 | thunk_info::stream_out (lto_simple_output_block *ob) |
107 | { |
108 | streamer_write_uhwi_stream |
109 | (ob->main_stream, |
110 | 1 + (this_adjusting != 0) * 2 |
111 | + (virtual_offset_p != 0) * 4); |
112 | streamer_write_uhwi_stream (ob->main_stream, fixed_offset); |
113 | streamer_write_uhwi_stream (ob->main_stream, virtual_value); |
114 | streamer_write_uhwi_stream (ob->main_stream, indirect_offset); |
115 | } |
116 | |
117 | /* Stream in THIS from IB. */ |
118 | void |
119 | thunk_info::stream_in (class lto_input_block *ib) |
120 | { |
121 | int type = streamer_read_uhwi (ib); |
122 | fixed_offset = streamer_read_uhwi (ib); |
123 | virtual_value = streamer_read_uhwi (ib); |
124 | indirect_offset = streamer_read_uhwi (ib); |
125 | |
126 | this_adjusting = (type & 2); |
127 | virtual_offset_p = (type & 4); |
128 | } |
129 | |
130 | /* Dump THIS to F. */ |
131 | void |
132 | thunk_info::dump (FILE *f) |
133 | { |
134 | if (alias) |
135 | fprintf (f, " of %s (asm:%s)", |
136 | lang_hooks.decl_printable_name (alias, 2), |
137 | IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (alias))((const char *) (tree_check ((decl_assembler_name (alias)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 137, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); |
138 | fprintf (f, " fixed offset %i virtual value %i indirect_offset %i " |
139 | "has virtual offset %i\n", |
140 | (int)fixed_offset, |
141 | (int)virtual_value, |
142 | (int)indirect_offset, |
143 | (int)virtual_offset_p); |
144 | } |
145 | |
146 | /* Hash THIS. */ |
147 | hashval_t |
148 | thunk_info::hash () |
149 | { |
150 | inchash::hash hstate; |
151 | hstate.add_hwi (fixed_offset); |
152 | hstate.add_hwi (virtual_value); |
153 | hstate.add_flag (this_adjusting); |
154 | hstate.add_flag (virtual_offset_p); |
155 | return hstate.end (); |
156 | } |
157 | |
158 | /* Add unprocessed thunk. */ |
159 | void |
160 | thunk_info::register_early (cgraph_node *node) |
161 | { |
162 | unprocessed_thunk entry = {node, new (ggc_alloc <thunk_info> ()) thunk_info}; |
163 | *entry.info = *this; |
164 | vec_safe_push (thunks, entry); |
165 | } |
166 | |
167 | /* Attach recorded thunks to cgraph_nodes. |
168 | All this is done only to avoid need to stream summaries to PCH. */ |
169 | void |
170 | thunk_info::process_early_thunks () |
171 | { |
172 | unprocessed_thunk *e; |
173 | unsigned int i; |
174 | if (!thunks) |
175 | return; |
176 | |
177 | FOR_EACH_VEC_ELT (*thunks, i, e)for (i = 0; (*thunks).iterate ((i), &(e)); ++(i)) |
178 | { |
179 | *thunk_info::get_create (e->node) = *e->info; |
180 | } |
181 | vec_free (thunks); |
182 | thunks = NULLnullptr; |
183 | } |
184 | |
185 | /* Adjust PTR by the constant FIXED_OFFSET, by the vtable offset indicated by |
186 | VIRTUAL_OFFSET, and by the indirect offset indicated by INDIRECT_OFFSET, if |
187 | it is non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and zero |
188 | for a result adjusting thunk. */ |
189 | tree |
190 | thunk_adjust (gimple_stmt_iterator * bsi, |
191 | tree ptr, bool this_adjusting, |
192 | HOST_WIDE_INTlong fixed_offset, tree virtual_offset, |
193 | HOST_WIDE_INTlong indirect_offset) |
194 | { |
195 | gassign *stmt; |
196 | tree ret; |
197 | |
198 | if (this_adjusting |
199 | && fixed_offset != 0) |
200 | { |
201 | stmt = gimple_build_assign |
202 | (ptr, fold_build_pointer_plus_hwi_loc (input_location, |
203 | ptr, |
204 | fixed_offset)); |
205 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
206 | } |
207 | |
208 | if (!vtable_entry_type && (virtual_offset || indirect_offset != 0)) |
209 | { |
210 | tree vfunc_type = make_node (FUNCTION_TYPE); |
211 | TREE_TYPE (vfunc_type)((contains_struct_check ((vfunc_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 211, __FUNCTION__))->typed.type) = integer_type_nodeinteger_types[itk_int]; |
212 | TYPE_ARG_TYPES (vfunc_type)((tree_check2 ((vfunc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 212, __FUNCTION__, (FUNCTION_TYPE), (METHOD_TYPE)))->type_non_common .values) = NULL_TREE(tree) nullptr; |
213 | layout_type (vfunc_type); |
214 | |
215 | vtable_entry_type = build_pointer_type (vfunc_type); |
216 | } |
217 | |
218 | /* If there's a virtual offset, look up that value in the vtable and |
219 | adjust the pointer again. */ |
220 | if (virtual_offset) |
221 | { |
222 | tree vtabletmp; |
223 | tree vtabletmp2; |
224 | tree vtabletmp3; |
225 | |
226 | vtabletmp = create_tmp_reg |
227 | (build_pointer_type |
228 | (build_pointer_type (vtable_entry_type)), "vptr"); |
229 | |
230 | /* The vptr is always at offset zero in the object. */ |
231 | stmt = gimple_build_assign (vtabletmp, |
232 | build1 (NOP_EXPR, TREE_TYPE (vtabletmp)((contains_struct_check ((vtabletmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 232, __FUNCTION__))->typed.type), |
233 | ptr)); |
234 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
235 | |
236 | /* Form the vtable address. */ |
237 | vtabletmp2 = create_tmp_reg (TREE_TYPE (TREE_TYPE (vtabletmp))((contains_struct_check ((((contains_struct_check ((vtabletmp ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 237, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 237, __FUNCTION__))->typed.type), |
238 | "vtableaddr"); |
239 | stmt = gimple_build_assign (vtabletmp2, |
240 | build_simple_mem_ref (vtabletmp)build_simple_mem_ref_loc (((location_t) 0), vtabletmp)); |
241 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
242 | |
243 | /* Find the entry with the vcall offset. */ |
244 | stmt = gimple_build_assign (vtabletmp2, |
245 | fold_build_pointer_plus_loc (input_location, |
246 | vtabletmp2, |
247 | virtual_offset)); |
248 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
249 | |
250 | /* Get the offset itself. */ |
251 | vtabletmp3 = create_tmp_reg (TREE_TYPE (TREE_TYPE (vtabletmp2))((contains_struct_check ((((contains_struct_check ((vtabletmp2 ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 251, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 251, __FUNCTION__))->typed.type), |
252 | "vcalloffset"); |
253 | stmt = gimple_build_assign (vtabletmp3, |
254 | build_simple_mem_ref (vtabletmp2)build_simple_mem_ref_loc (((location_t) 0), vtabletmp2)); |
255 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
256 | |
257 | /* Adjust the `this' pointer. */ |
258 | ptr = fold_build_pointer_plus_loc (input_location, ptr, vtabletmp3); |
259 | ptr = force_gimple_operand_gsi (bsi, ptr, true, NULL_TREE(tree) nullptr, false, |
260 | GSI_CONTINUE_LINKING); |
261 | } |
262 | |
263 | /* Likewise for an offset that is stored in the object that contains the |
264 | vtable. */ |
265 | if (indirect_offset != 0) |
266 | { |
267 | tree offset_ptr, offset_tree; |
268 | |
269 | /* Get the address of the offset. */ |
270 | offset_ptr |
271 | = create_tmp_reg (build_pointer_type |
272 | (build_pointer_type (vtable_entry_type)), |
273 | "offset_ptr"); |
274 | stmt = gimple_build_assign (offset_ptr, |
275 | build1 (NOP_EXPR, TREE_TYPE (offset_ptr)((contains_struct_check ((offset_ptr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 275, __FUNCTION__))->typed.type), |
276 | ptr)); |
277 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
278 | |
279 | stmt = gimple_build_assign |
280 | (offset_ptr, |
281 | fold_build_pointer_plus_hwi_loc (input_location, offset_ptr, |
282 | indirect_offset)); |
283 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
284 | |
285 | /* Get the offset itself. */ |
286 | offset_tree = create_tmp_reg (TREE_TYPE (TREE_TYPE (offset_ptr))((contains_struct_check ((((contains_struct_check ((offset_ptr ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 286, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 286, __FUNCTION__))->typed.type), |
287 | "offset"); |
288 | stmt = gimple_build_assign (offset_tree, |
289 | build_simple_mem_ref (offset_ptr)build_simple_mem_ref_loc (((location_t) 0), offset_ptr)); |
290 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
291 | |
292 | /* Adjust the `this' pointer. */ |
293 | ptr = fold_build_pointer_plus_loc (input_location, ptr, offset_tree); |
294 | ptr = force_gimple_operand_gsi (bsi, ptr, true, NULL_TREE(tree) nullptr, false, |
295 | GSI_CONTINUE_LINKING); |
296 | } |
297 | |
298 | if (!this_adjusting |
299 | && fixed_offset != 0) |
300 | /* Adjust the pointer by the constant. */ |
301 | { |
302 | tree ptrtmp; |
303 | |
304 | if (VAR_P (ptr)(((enum tree_code) (ptr)->base.code) == VAR_DECL)) |
305 | ptrtmp = ptr; |
306 | else |
307 | { |
308 | ptrtmp = create_tmp_reg (TREE_TYPE (ptr)((contains_struct_check ((ptr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 308, __FUNCTION__))->typed.type), "ptr"); |
309 | stmt = gimple_build_assign (ptrtmp, ptr); |
310 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
311 | } |
312 | ptr = fold_build_pointer_plus_hwi_loc (input_location, |
313 | ptrtmp, fixed_offset); |
314 | } |
315 | |
316 | /* Emit the statement and gimplify the adjustment expression. */ |
317 | ret = create_tmp_reg (TREE_TYPE (ptr)((contains_struct_check ((ptr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 317, __FUNCTION__))->typed.type), "adjusted_this"); |
318 | stmt = gimple_build_assign (ret, ptr); |
319 | gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
320 | |
321 | return ret; |
322 | } |
323 | |
324 | /* Expand thunk NODE to gimple if possible. |
325 | When FORCE_GIMPLE_THUNK is true, gimple thunk is created and |
326 | no assembler is produced. |
327 | When OUTPUT_ASM_THUNK is true, also produce assembler for |
328 | thunks that are not lowered. */ |
329 | bool |
330 | expand_thunk (cgraph_node *node, bool output_asm_thunks, |
331 | bool force_gimple_thunk) |
332 | { |
333 | thunk_info *info = thunk_info::get (node); |
334 | bool this_adjusting = info->this_adjusting; |
335 | HOST_WIDE_INTlong fixed_offset = info->fixed_offset; |
336 | HOST_WIDE_INTlong virtual_value = info->virtual_value; |
337 | HOST_WIDE_INTlong indirect_offset = info->indirect_offset; |
338 | tree virtual_offset = NULLnullptr; |
339 | tree alias = node->callees->callee->decl; |
340 | tree thunk_fndecl = node->decl; |
341 | tree a; |
342 | |
343 | if (!force_gimple_thunk |
344 | && this_adjusting |
345 | && indirect_offset == 0 |
346 | && !DECL_EXTERNAL (alias)((contains_struct_check ((alias), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 346, __FUNCTION__))->decl_common.decl_flag_1) |
347 | && !DECL_STATIC_CHAIN (alias)((tree_check ((alias), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 347, __FUNCTION__, (FUNCTION_DECL)))->decl_with_vis.regdecl_flag ) |
348 | && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, |
349 | virtual_value, alias)) |
350 | { |
351 | tree fn_block; |
352 | tree restype = TREE_TYPE (TREE_TYPE (thunk_fndecl))((contains_struct_check ((((contains_struct_check ((thunk_fndecl ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 352, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 352, __FUNCTION__))->typed.type); |
353 | |
354 | if (!output_asm_thunks) |
355 | { |
356 | node->analyzed = true; |
357 | return false; |
358 | } |
359 | |
360 | if (in_lto_pglobal_options.x_in_lto_p) |
361 | node->get_untransformed_body (); |
362 | a = DECL_ARGUMENTS (thunk_fndecl)((tree_check ((thunk_fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 362, __FUNCTION__, (FUNCTION_DECL)))->function_decl.arguments ); |
363 | |
364 | current_function_decl = thunk_fndecl; |
365 | |
366 | /* Ensure thunks are emitted in their correct sections. */ |
367 | resolve_unique_section (thunk_fndecl, 0, |
368 | flag_function_sectionsglobal_options.x_flag_function_sections); |
369 | |
370 | DECL_RESULT (thunk_fndecl)((tree_check ((thunk_fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 370, __FUNCTION__, (FUNCTION_DECL)))->decl_non_common.result ) |
371 | = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl)((contains_struct_check ((thunk_fndecl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 371, __FUNCTION__))->decl_minimal.locus), |
372 | RESULT_DECL, 0, restype); |
373 | DECL_CONTEXT (DECL_RESULT (thunk_fndecl))((contains_struct_check ((((tree_check ((thunk_fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 373, __FUNCTION__, (FUNCTION_DECL)))->decl_non_common.result )), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 373, __FUNCTION__))->decl_minimal.context) = thunk_fndecl; |
374 | |
375 | /* The back end expects DECL_INITIAL to contain a BLOCK, so we |
376 | create one. */ |
377 | fn_block = make_node (BLOCK); |
378 | BLOCK_VARS (fn_block)((tree_check ((fn_block), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 378, __FUNCTION__, (BLOCK)))->block.vars) = a; |
379 | DECL_INITIAL (thunk_fndecl)((contains_struct_check ((thunk_fndecl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 379, __FUNCTION__))->decl_common.initial) = fn_block; |
380 | BLOCK_SUPERCONTEXT (fn_block)((tree_check ((fn_block), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 380, __FUNCTION__, (BLOCK)))->block.supercontext) = thunk_fndecl; |
381 | allocate_struct_function (thunk_fndecl, false); |
382 | init_function_start (thunk_fndecl); |
383 | cfun(cfun + 0)->is_thunk = 1; |
384 | insn_locations_init (); |
385 | set_curr_insn_location (DECL_SOURCE_LOCATION (thunk_fndecl)((contains_struct_check ((thunk_fndecl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 385, __FUNCTION__))->decl_minimal.locus)); |
386 | prologue_location = curr_insn_location (); |
387 | |
388 | targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, |
389 | fixed_offset, virtual_value, alias); |
390 | |
391 | insn_locations_finalize (); |
392 | init_insn_lengths (); |
393 | free_after_compilation (cfun(cfun + 0)); |
394 | TREE_ASM_WRITTEN (thunk_fndecl)((thunk_fndecl)->base.asm_written_flag) = 1; |
395 | node->thunk = false; |
396 | node->analyzed = false; |
397 | } |
398 | else if (stdarg_p (TREE_TYPE (thunk_fndecl)((contains_struct_check ((thunk_fndecl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 398, __FUNCTION__))->typed.type))) |
399 | { |
400 | error ("generic thunk code fails for method %qD which uses %<...%>", |
401 | thunk_fndecl); |
402 | TREE_ASM_WRITTEN (thunk_fndecl)((thunk_fndecl)->base.asm_written_flag) = 1; |
403 | node->analyzed = true; |
404 | return false; |
405 | } |
406 | else |
407 | { |
408 | tree restype; |
409 | basic_block bb, then_bb, else_bb, return_bb; |
410 | gimple_stmt_iterator bsi; |
411 | int nargs = 0; |
412 | tree arg; |
413 | int i; |
414 | tree resdecl; |
415 | tree restmp = NULLnullptr; |
416 | |
417 | gcall *call; |
418 | greturn *ret; |
419 | bool alias_is_noreturn = TREE_THIS_VOLATILE (alias)((alias)->base.volatile_flag); |
420 | |
421 | /* We may be called from expand_thunk that releases body except for |
422 | DECL_ARGUMENTS. In this case force_gimple_thunk is true. */ |
423 | if (in_lto_pglobal_options.x_in_lto_p && !force_gimple_thunk) |
424 | node->get_untransformed_body (); |
425 | |
426 | /* We need to force DECL_IGNORED_P when the thunk is created |
427 | after early debug was run. */ |
428 | if (force_gimple_thunk) |
429 | DECL_IGNORED_P (thunk_fndecl)((contains_struct_check ((thunk_fndecl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 429, __FUNCTION__))->decl_common.ignored_flag) = 1; |
430 | |
431 | a = DECL_ARGUMENTS (thunk_fndecl)((tree_check ((thunk_fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 431, __FUNCTION__, (FUNCTION_DECL)))->function_decl.arguments ); |
432 | |
433 | current_function_decl = thunk_fndecl; |
434 | |
435 | /* Ensure thunks are emitted in their correct sections. */ |
436 | resolve_unique_section (thunk_fndecl, 0, |
437 | flag_function_sectionsglobal_options.x_flag_function_sections); |
438 | |
439 | bitmap_obstack_initialize (NULLnullptr); |
440 | |
441 | if (info->virtual_offset_p) |
442 | virtual_offset = size_int (virtual_value)size_int_kind (virtual_value, stk_sizetype); |
443 | |
444 | /* Build the return declaration for the function. */ |
445 | restype = TREE_TYPE (TREE_TYPE (thunk_fndecl))((contains_struct_check ((((contains_struct_check ((thunk_fndecl ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 445, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 445, __FUNCTION__))->typed.type); |
446 | if (DECL_RESULT (thunk_fndecl)((tree_check ((thunk_fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 446, __FUNCTION__, (FUNCTION_DECL)))->decl_non_common.result ) == NULL_TREE(tree) nullptr) |
447 | { |
448 | resdecl = build_decl (input_location, RESULT_DECL, 0, restype); |
449 | DECL_ARTIFICIAL (resdecl)((contains_struct_check ((resdecl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 449, __FUNCTION__))->decl_common.artificial_flag) = 1; |
450 | DECL_IGNORED_P (resdecl)((contains_struct_check ((resdecl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 450, __FUNCTION__))->decl_common.ignored_flag) = 1; |
451 | DECL_CONTEXT (resdecl)((contains_struct_check ((resdecl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 451, __FUNCTION__))->decl_minimal.context) = thunk_fndecl; |
452 | DECL_RESULT (thunk_fndecl)((tree_check ((thunk_fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 452, __FUNCTION__, (FUNCTION_DECL)))->decl_non_common.result ) = resdecl; |
453 | } |
454 | else |
455 | resdecl = DECL_RESULT (thunk_fndecl)((tree_check ((thunk_fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 455, __FUNCTION__, (FUNCTION_DECL)))->decl_non_common.result ); |
456 | |
457 | profile_count cfg_count = node->count; |
458 | if (!cfg_count.initialized_p ()) |
459 | cfg_count = profile_count::from_gcov_type |
460 | (BB_FREQ_MAX10000).guessed_local (); |
461 | |
462 | bb = then_bb = else_bb = return_bb |
Although the value stored to 'then_bb' is used in the enclosing expression, the value is never actually read from 'then_bb' | |
463 | = init_lowered_empty_function (thunk_fndecl, true, cfg_count); |
464 | |
465 | bsi = gsi_start_bb (bb); |
466 | |
467 | /* Build call to the function being thunked. */ |
468 | if (!VOID_TYPE_P (restype)(((enum tree_code) (restype)->base.code) == VOID_TYPE) |
469 | && (!alias_is_noreturn |
470 | || TREE_ADDRESSABLE (restype)((restype)->base.addressable_flag) |
471 | || TREE_CODE (TYPE_SIZE_UNIT (restype))((enum tree_code) (((tree_class_check ((restype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 471, __FUNCTION__))->type_common.size_unit))->base.code ) != INTEGER_CST)) |
472 | { |
473 | if (DECL_BY_REFERENCE (resdecl)((tree_check3 ((resdecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 473, __FUNCTION__, (VAR_DECL), (PARM_DECL), (RESULT_DECL))) ->decl_common.decl_by_reference_flag)) |
474 | { |
475 | restmp = gimple_fold_indirect_ref (resdecl); |
476 | if (!restmp) |
477 | restmp = build2 (MEM_REF, |
478 | TREE_TYPE (TREE_TYPE (resdecl))((contains_struct_check ((((contains_struct_check ((resdecl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 478, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 478, __FUNCTION__))->typed.type), |
479 | resdecl, |
480 | build_int_cst (TREE_TYPE (resdecl)((contains_struct_check ((resdecl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 480, __FUNCTION__))->typed.type), 0)); |
481 | } |
482 | else if (!is_gimple_reg_type (restype)) |
483 | { |
484 | if (aggregate_value_p (resdecl, TREE_TYPE (thunk_fndecl)((contains_struct_check ((thunk_fndecl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 484, __FUNCTION__))->typed.type))) |
485 | { |
486 | restmp = resdecl; |
487 | |
488 | if (VAR_P (restmp)(((enum tree_code) (restmp)->base.code) == VAR_DECL)) |
489 | { |
490 | add_local_decl (cfun(cfun + 0), restmp); |
491 | BLOCK_VARS (DECL_INITIAL (current_function_decl))((tree_check ((((contains_struct_check ((current_function_decl ), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 491, __FUNCTION__))->decl_common.initial)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 491, __FUNCTION__, (BLOCK)))->block.vars) |
492 | = restmp; |
493 | } |
494 | } |
495 | else |
496 | restmp = create_tmp_var (restype, "retval"); |
497 | } |
498 | else |
499 | restmp = create_tmp_reg (restype, "retval"); |
500 | } |
501 | |
502 | for (arg = a; arg; arg = DECL_CHAIN (arg)(((contains_struct_check (((contains_struct_check ((arg), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 502, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 502, __FUNCTION__))->common.chain))) |
503 | nargs++; |
504 | auto_vec<tree> vargs (nargs); |
505 | i = 0; |
506 | arg = a; |
507 | if (this_adjusting) |
508 | { |
509 | vargs.quick_push (thunk_adjust (&bsi, a, 1, fixed_offset, |
510 | virtual_offset, indirect_offset)); |
511 | arg = DECL_CHAIN (a)(((contains_struct_check (((contains_struct_check ((a), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 511, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 511, __FUNCTION__))->common.chain)); |
512 | i = 1; |
513 | } |
514 | |
515 | if (nargs) |
516 | for (; i < nargs; i++, arg = DECL_CHAIN (arg)(((contains_struct_check (((contains_struct_check ((arg), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 516, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 516, __FUNCTION__))->common.chain))) |
517 | { |
518 | tree tmp = arg; |
519 | DECL_NOT_GIMPLE_REG_P (arg)(contains_struct_check ((arg), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 519, __FUNCTION__))->decl_common.not_gimple_reg_flag = 0; |
520 | if (!is_gimple_val (arg)) |
521 | { |
522 | tmp = create_tmp_reg (TYPE_MAIN_VARIANT((tree_class_check ((((contains_struct_check ((arg), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 523, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 523, __FUNCTION__))->type_common.main_variant) |
523 | (TREE_TYPE (arg))((tree_class_check ((((contains_struct_check ((arg), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 523, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 523, __FUNCTION__))->type_common.main_variant), "arg"); |
524 | gimple *stmt = gimple_build_assign (tmp, arg); |
525 | gsi_insert_after (&bsi, stmt, GSI_NEW_STMT); |
526 | } |
527 | vargs.quick_push (tmp); |
528 | } |
529 | call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs); |
530 | node->callees->call_stmt = call; |
531 | gimple_call_set_from_thunk (call, true); |
532 | if (DECL_STATIC_CHAIN (alias)((tree_check ((alias), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 532, __FUNCTION__, (FUNCTION_DECL)))->decl_with_vis.regdecl_flag )) |
533 | { |
534 | tree p = DECL_STRUCT_FUNCTION (alias)((tree_check ((alias), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 534, __FUNCTION__, (FUNCTION_DECL)))->function_decl.f)->static_chain_decl; |
535 | tree type = TREE_TYPE (p)((contains_struct_check ((p), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 535, __FUNCTION__))->typed.type); |
536 | tree decl = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl)((contains_struct_check ((thunk_fndecl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 536, __FUNCTION__))->decl_minimal.locus), |
537 | PARM_DECL, create_tmp_var_name ("CHAIN"), |
538 | type); |
539 | DECL_ARTIFICIAL (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 539, __FUNCTION__))->decl_common.artificial_flag) = 1; |
540 | DECL_IGNORED_P (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 540, __FUNCTION__))->decl_common.ignored_flag) = 1; |
541 | TREE_USED (decl)((decl)->base.used_flag) = 1; |
542 | DECL_CONTEXT (decl)((contains_struct_check ((decl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 542, __FUNCTION__))->decl_minimal.context) = thunk_fndecl; |
543 | DECL_ARG_TYPE (decl)((tree_check ((decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 543, __FUNCTION__, (PARM_DECL)))->decl_common.initial) = type; |
544 | TREE_READONLY (decl)((non_type_check ((decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 544, __FUNCTION__))->base.readonly_flag) = 1; |
545 | |
546 | struct function *sf = DECL_STRUCT_FUNCTION (thunk_fndecl)((tree_check ((thunk_fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 546, __FUNCTION__, (FUNCTION_DECL)))->function_decl.f); |
547 | sf->static_chain_decl = decl; |
548 | |
549 | gimple_call_set_chain (call, decl); |
550 | } |
551 | |
552 | /* Return slot optimization is always possible and in fact required to |
553 | return values with DECL_BY_REFERENCE. */ |
554 | if (aggregate_value_p (resdecl, TREE_TYPE (thunk_fndecl)((contains_struct_check ((thunk_fndecl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 554, __FUNCTION__))->typed.type)) |
555 | && (!is_gimple_reg_type (TREE_TYPE (resdecl)((contains_struct_check ((resdecl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 555, __FUNCTION__))->typed.type)) |
556 | || DECL_BY_REFERENCE (resdecl)((tree_check3 ((resdecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 556, __FUNCTION__, (VAR_DECL), (PARM_DECL), (RESULT_DECL))) ->decl_common.decl_by_reference_flag))) |
557 | gimple_call_set_return_slot_opt (call, true); |
558 | |
559 | if (restmp) |
560 | { |
561 | gimple_call_set_lhs (call, restmp); |
562 | gcc_assert (useless_type_conversion_p (TREE_TYPE (restmp),((void)(!(useless_type_conversion_p (((contains_struct_check ( (restmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 562, __FUNCTION__))->typed.type), ((contains_struct_check ((((contains_struct_check ((alias), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 563, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 563, __FUNCTION__))->typed.type))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 563, __FUNCTION__), 0 : 0)) |
563 | TREE_TYPE (TREE_TYPE (alias))))((void)(!(useless_type_conversion_p (((contains_struct_check ( (restmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 562, __FUNCTION__))->typed.type), ((contains_struct_check ((((contains_struct_check ((alias), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 563, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 563, __FUNCTION__))->typed.type))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 563, __FUNCTION__), 0 : 0)); |
564 | } |
565 | gsi_insert_after (&bsi, call, GSI_NEW_STMT); |
566 | if (!alias_is_noreturn) |
567 | { |
568 | if (restmp && !this_adjusting |
569 | && (fixed_offset || virtual_offset)) |
570 | { |
571 | tree true_label = NULL_TREE(tree) nullptr; |
572 | |
573 | if (TREE_CODE (TREE_TYPE (restmp))((enum tree_code) (((contains_struct_check ((restmp), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 573, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE) |
574 | { |
575 | gimple *stmt; |
576 | edge e; |
577 | /* If the return type is a pointer, we need to |
578 | protect against NULL. We know there will be an |
579 | adjustment, because that's why we're emitting a |
580 | thunk. */ |
581 | then_bb = create_basic_block (NULLnullptr, bb); |
582 | then_bb->count = cfg_count - cfg_count / 16; |
583 | return_bb = create_basic_block (NULLnullptr, then_bb); |
584 | return_bb->count = cfg_count; |
585 | else_bb = create_basic_block (NULLnullptr, else_bb); |
586 | else_bb->count = cfg_count / 16; |
587 | add_bb_to_loop (then_bb, bb->loop_father); |
588 | add_bb_to_loop (return_bb, bb->loop_father); |
589 | add_bb_to_loop (else_bb, bb->loop_father); |
590 | remove_edge (single_succ_edge (bb)); |
591 | true_label = gimple_block_label (then_bb); |
592 | stmt = gimple_build_cond (NE_EXPR, restmp, |
593 | build_zero_cst (TREE_TYPE (restmp)((contains_struct_check ((restmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 593, __FUNCTION__))->typed.type)), |
594 | NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr); |
595 | gsi_insert_after (&bsi, stmt, GSI_NEW_STMT); |
596 | e = make_edge (bb, then_bb, EDGE_TRUE_VALUE); |
597 | e->probability = profile_probability::guessed_always () / 16; |
598 | e = make_edge (bb, else_bb, EDGE_FALSE_VALUE); |
599 | e->probability = profile_probability::guessed_always () / 16; |
600 | make_single_succ_edge (return_bb, |
601 | EXIT_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_exit_block_ptr), 0); |
602 | make_single_succ_edge (then_bb, return_bb, EDGE_FALLTHRU); |
603 | e = make_edge (else_bb, return_bb, EDGE_FALLTHRU); |
604 | e->probability = profile_probability::always (); |
605 | bsi = gsi_last_bb (then_bb); |
606 | } |
607 | |
608 | restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0, |
609 | fixed_offset, virtual_offset, |
610 | indirect_offset); |
611 | if (true_label) |
612 | { |
613 | gimple *stmt; |
614 | bsi = gsi_last_bb (else_bb); |
615 | stmt = gimple_build_assign (restmp, |
616 | build_zero_cst |
617 | (TREE_TYPE (restmp)((contains_struct_check ((restmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 617, __FUNCTION__))->typed.type))); |
618 | gsi_insert_after (&bsi, stmt, GSI_NEW_STMT); |
619 | bsi = gsi_last_bb (return_bb); |
620 | } |
621 | } |
622 | else |
623 | { |
624 | gimple_call_set_tail (call, true); |
625 | cfun(cfun + 0)->tail_call_marked = true; |
626 | } |
627 | |
628 | /* Build return value. */ |
629 | if (!DECL_BY_REFERENCE (resdecl)((tree_check3 ((resdecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/symtab-thunks.cc" , 629, __FUNCTION__, (VAR_DECL), (PARM_DECL), (RESULT_DECL))) ->decl_common.decl_by_reference_flag)) |
630 | ret = gimple_build_return (restmp); |
631 | else |
632 | ret = gimple_build_return (resdecl); |
633 | |
634 | gsi_insert_after (&bsi, ret, GSI_NEW_STMT); |
635 | } |
636 | else |
637 | { |
638 | gimple_call_set_ctrl_altering (call, true); |
639 | gimple_call_set_tail (call, true); |
640 | cfun(cfun + 0)->tail_call_marked = true; |
641 | remove_edge (single_succ_edge (bb)); |
642 | } |
643 | |
644 | cfun(cfun + 0)->gimple_df->in_ssa_p = true; |
645 | update_max_bb_count (); |
646 | profile_status_for_fn (cfun)(((cfun + 0))->cfg->x_profile_status) |
647 | = cfg_count.initialized_p () && cfg_count.ipa_p () |
648 | ? PROFILE_READ : PROFILE_GUESSED; |
649 | /* FIXME: C++ FE should stop setting TREE_ASM_WRITTEN on thunks. */ |
650 | TREE_ASM_WRITTEN (thunk_fndecl)((thunk_fndecl)->base.asm_written_flag) = false; |
651 | delete_unreachable_blocks (); |
652 | update_ssa (TODO_update_ssa(1 << 11)); |
653 | checking_verify_flow_info (); |
654 | free_dominance_info (CDI_DOMINATORS); |
655 | |
656 | /* Since we want to emit the thunk, we explicitly mark its name as |
657 | referenced. */ |
658 | node->thunk = false; |
659 | node->lowered = true; |
660 | bitmap_obstack_release (NULLnullptr); |
661 | } |
662 | current_function_decl = NULLnullptr; |
663 | set_cfun (NULLnullptr); |
664 | return true; |
665 | } |
666 | |
667 | void |
668 | symtab_thunks_cc_finalize (void) |
669 | { |
670 | vtable_entry_type = NULLnullptr; |
671 | } |
672 | |
673 | #include "gt-symtab-thunks.h" |