GCC Wikia
Advertisement

このページを編集する際は,編集に関する方針に従ってください.[]

概要[]

338 /* For functions-as-trees languages, this performs all optimization and
339    compilation for FNDECL.  */


引数[]

  • tree fndecl
    • 関数を表している木構造

実装[]

341 void
342 tree_rest_of_compilation (tree fndecl)
343 {
344   location_t saved_loc;
345   struct cgraph_node *saved_node = NULL, *node;
346 
347   timevar_push (TV_EXPAND);
348 
349   gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
350 
351   /* Initialize the RTL code for the function.  */
352   current_function_decl = fndecl;
353   saved_loc = input_location;
354   input_location = DECL_SOURCE_LOCATION (fndecl);
355   init_function_start (fndecl);
356 
357   /* Even though we're inside a function body, we still don't want to
358      call expand_expr to calculate the size of a variable-sized array.
359      We haven't necessarily assigned RTL to all variables yet, so it's
360      not safe to try to expand expressions involving them.  */
361   cfun->x_dont_save_pending_sizes_p = 1;
362   cfun->after_inlining = true;
363 
364   node = cgraph_node (fndecl);
365 
 366   /* We might need the body of this function so that we can expand
 367      it inline somewhere else.  This means not lowering some constructs
 368      such as exception handling.  */
369   if (cgraph_preserve_function_body_p (fndecl))
370     {
371       if (!flag_unit_at_a_time)
372         {
373           struct cgraph_edge *e;
374 
375           saved_node = cgraph_clone_node (node, node->count, 1, false);
376           for (e = saved_node->callees; e; e = e->next_callee)
377             if (!e->inline_failed)
378               cgraph_clone_inlined_nodes (e, true, false);
379         }
380       cfun->saved_static_chain_decl = cfun->static_chain_decl;
381       save_body (fndecl, &cfun->saved_args, &cfun->saved_static_chain_decl);
382     }
383 
384   if (flag_inline_trees)
385     {
386       struct cgraph_edge *e;
387       for (e = node->callees; e; e = e->next_callee)
388         if (!e->inline_failed || warn_inline)
389           break;
390       if (e)
391         {
392           timevar_push (TV_INTEGRATION);
393           optimize_inline_calls (fndecl);
394           timevar_pop (TV_INTEGRATION);
395         }
396     }
 397   /* We are not going to maintain the cgraph edges up to date.
 398      Kill it so it won't confuse us.  */
399   while (node->callees)
400     {
 401       /* In non-unit-at-a-time we must mark all referenced functions as needed.
 402          */
403       if (node->callees->callee->analyzed && !flag_unit_at_a_time)
404         cgraph_mark_needed_node (node->callees->callee);
405       cgraph_remove_edge (node->callees);
406     }
407 
 408   /* We are not going to maintain the cgraph edges up to date.
 409      Kill it so it won't confuse us.  */
410   cgraph_node_remove_callees (node);
411 
412 
 413   /* Initialize the default bitmap obstack.  */
414   bitmap_obstack_initialize (NULL);
415   bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
416   
417   tree_register_cfg_hooks ();
 418   /* Perform all tree transforms and optimizations.  */
419   execute_pass_list (all_passes);
420   
421   bitmap_obstack_release (&reg_obstack);
422 
 423   /* Release the default bitmap obstack.  */
424   bitmap_obstack_release (NULL);
425   
 426   /* Restore original body if still needed.  */
427   if (cfun->saved_cfg)
428     {
429       DECL_ARGUMENTS (fndecl) = cfun->saved_args;
430       cfun->cfg = cfun->saved_cfg;
431       cfun->eh = cfun->saved_eh;
432       DECL_INITIAL (fndecl) = cfun->saved_blocks;
433       cfun->unexpanded_var_list = cfun->saved_unexpanded_var_list;
434       cfun->saved_cfg = NULL;
435       cfun->saved_eh = NULL;
436       cfun->saved_args = NULL_TREE;
437       cfun->saved_blocks = NULL_TREE;
438       cfun->saved_unexpanded_var_list = NULL_TREE;
439       cfun->static_chain_decl = cfun->saved_static_chain_decl;
440       cfun->saved_static_chain_decl = NULL;
 441       /* When not in unit-at-a-time mode, we must preserve out of line copy
 442          representing node before inlining.  Restore original outgoing edges
 443          using clone we created earlier.  */
444       if (!flag_unit_at_a_time)
445         {
446           struct cgraph_edge *e;
447 
448           node = cgraph_node (current_function_decl);
449           cgraph_node_remove_callees (node);
450           node->callees = saved_node->callees;
451           saved_node->callees = NULL;
452           update_inlined_to_pointers (node, node);
453           for (e = node->callees; e; e = e->next_callee)
454             e->caller = node;
455           cgraph_remove_node (saved_node);
456         }
457     }
458   else
459     DECL_SAVED_TREE (fndecl) = NULL;
460   cfun = 0;
461 
 462   /* If requested, warn about function definitions where the function will
 463      return a value (usually of some struct or union type) which itself will
 464      take up a lot of stack space.  */
465   if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
466     {
467       tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
468 
469       if (ret_type && TYPE_SIZE_UNIT (ret_type)
470           && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == [[INTEGER_CST>enum tree_code]]
471           && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
472                                    larger_than_size))
473         {
474           unsigned int size_as_int
475             = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
476 
477           if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
478             warning (0, "size of return value of %q+D is %u bytes",
479                      fndecl, size_as_int);
480           else
481             warning (0, "size of return value of %q+D is larger than %wd bytes",
482                      fndecl, larger_than_size);
483         }
484     }
485 
486   if (!flag_inline_trees)
487     {
488       DECL_SAVED_TREE (fndecl) = NULL;
489       if (DECL_STRUCT_FUNCTION (fndecl) == 0
490           && !cgraph_node (fndecl)->origin)
491         {
 492           /* Stop pointing to the local nodes about to be freed.
 493              But DECL_INITIAL must remain nonzero so we know this
 494              was an actual function definition.
 495              For a nested function, this is done in c_pop_function_context.
 496              If rest_of_compilation set this to 0, leave it 0.  */
497           if (DECL_INITIAL (fndecl) != 0)
498             DECL_INITIAL (fndecl) = error_mark_node;
499         }
500     }
501 
502   input_location = saved_loc;
503 
504   ggc_collect ();
505   timevar_pop (TV_EXPAND);
506 }


リンク元

Advertisement