Mercurial > hg > CbC > CbC_gcc
diff gcc/cgraphunit.c @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/cgraphunit.c Thu Oct 25 08:08:40 2018 +0900 +++ b/gcc/cgraphunit.c Thu Oct 25 10:21:07 2018 +0900 @@ -1,5 +1,5 @@ /* Driver of optimization process - Copyright (C) 2003-2017 Free Software Foundation, Inc. + Copyright (C) 2003-2018 Free Software Foundation, Inc. Contributed by Jan Hubicka This file is part of GCC. @@ -202,7 +202,6 @@ #include "pass_manager.h" #include "tree-nested.h" #include "dbgcnt.h" -#include "tree-chkp.h" #include "lto-section-names.h" #include "stringpool.h" #include "attribs.h" @@ -620,24 +619,22 @@ { cgraph_node *t = cgraph_node::get (thunk.alias); - create_edge (t, NULL, t->count, CGRAPH_FREQ_BASE); + create_edge (t, NULL, t->count); callees->can_throw_external = !TREE_NOTHROW (t->decl); /* Target code in expand_thunk may need the thunk's target to be analyzed, so recurse here. */ - if (!t->analyzed) + if (!t->analyzed && t->definition) t->analyze (); if (t->alias) { t = t->get_alias_target (); - if (!t->analyzed) + if (!t->analyzed && t->definition) t->analyze (); } - if (!expand_thunk (false, false)) - { - thunk.alias = NULL; - return; - } + bool ret = expand_thunk (false, false); thunk.alias = NULL; + if (!ret) + return; } if (alias) resolve_alias (cgraph_node::get (alias_target), transparent_alias); @@ -787,6 +784,12 @@ DECL_ATTRIBUTES (decl) = remove_attribute ("weakref", DECL_ATTRIBUTES (decl)); } + else if (lookup_attribute ("alias", DECL_ATTRIBUTES (decl)) + && node->definition + && !node->alias) + warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes, + "%<alias%> attribute ignored" + " because function is defined"); if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl)) && !DECL_DECLARED_INLINE_P (decl) @@ -865,9 +868,6 @@ || (node->no_reorder && symtab->state == EXPANSION)) node->assemble_decl (); - - if (DECL_INITIAL (decl)) - chkp_register_var_initializer (decl); } /* EDGE is an polymorphic call. Mark all possible targets as reachable @@ -932,8 +932,7 @@ } if (dump_enabled_p ()) { - location_t locus = gimple_location_safe (edge->call_stmt); - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus, + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, edge->call_stmt, "devirtualizing call in %s to %s\n", edge->caller->name (), target->name ()); } @@ -941,10 +940,6 @@ edge->make_direct (target); edge->redirect_call_stmt_to_callee (); - /* Call to __builtin_unreachable shouldn't be instrumented. */ - if (!targets.length ()) - gimple_call_set_with_bounds (edge->call_stmt, false); - if (symtab->dump_file) { fprintf (symtab->dump_file, @@ -1307,7 +1302,7 @@ tree altype = TREE_TYPE (alias); tree targtype = TREE_TYPE (target); - bool ifunc = lookup_attribute ("ifunc", DECL_ATTRIBUTES (alias)); + bool ifunc = cgraph_node::get (alias)->ifunc_resolver; tree funcptr = altype; if (ifunc) @@ -1367,6 +1362,7 @@ { funcptr = build_pointer_type (funcptr); + auto_diagnostic_group d; if (warning_at (DECL_SOURCE_LOCATION (target), OPT_Wattribute_alias, "%<ifunc%> resolver for %qD should return %qT", @@ -1374,12 +1370,16 @@ inform (DECL_SOURCE_LOCATION (alias), "resolver indirect function declared here"); } - else if (warning_at (DECL_SOURCE_LOCATION (alias), - OPT_Wattribute_alias, - "%qD alias between functions of incompatible " - "types %qT and %qT", alias, altype, targtype)) - inform (DECL_SOURCE_LOCATION (target), - "aliased declaration here"); + else + { + auto_diagnostic_group d; + if (warning_at (DECL_SOURCE_LOCATION (alias), + OPT_Wattribute_alias, + "%qD alias between functions of incompatible " + "types %qT and %qT", alias, altype, targtype)) + inform (DECL_SOURCE_LOCATION (target), + "aliased declaration here"); + } } } @@ -1601,12 +1601,9 @@ /* Create BB for body of the function and connect it properly. */ ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = count; - ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency = BB_FREQ_MAX; EXIT_BLOCK_PTR_FOR_FN (cfun)->count = count; - EXIT_BLOCK_PTR_FOR_FN (cfun)->frequency = BB_FREQ_MAX; bb = create_basic_block (NULL, ENTRY_BLOCK_PTR_FOR_FN (cfun)); bb->count = count; - bb->frequency = BB_FREQ_MAX; e = make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, EDGE_FALLTHRU); e->probability = profile_probability::always (); e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0); @@ -1616,15 +1613,16 @@ return bb; } -/* Adjust PTR by the constant FIXED_OFFSET, and by the vtable - offset indicated by VIRTUAL_OFFSET, if that is - non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and - zero for a result adjusting thunk. */ +/* Adjust PTR by the constant FIXED_OFFSET, by the vtable offset indicated by + VIRTUAL_OFFSET, and by the indirect offset indicated by INDIRECT_OFFSET, if + it is non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and zero + for a result adjusting thunk. */ tree thunk_adjust (gimple_stmt_iterator * bsi, tree ptr, bool this_adjusting, - HOST_WIDE_INT fixed_offset, tree virtual_offset) + HOST_WIDE_INT fixed_offset, tree virtual_offset, + HOST_WIDE_INT indirect_offset) { gassign *stmt; tree ret; @@ -1639,6 +1637,16 @@ gsi_insert_after (bsi, stmt, GSI_NEW_STMT); } + if (!vtable_entry_type && (virtual_offset || indirect_offset != 0)) + { + tree vfunc_type = make_node (FUNCTION_TYPE); + TREE_TYPE (vfunc_type) = integer_type_node; + TYPE_ARG_TYPES (vfunc_type) = NULL_TREE; + layout_type (vfunc_type); + + vtable_entry_type = build_pointer_type (vfunc_type); + } + /* If there's a virtual offset, look up that value in the vtable and adjust the pointer again. */ if (virtual_offset) @@ -1647,16 +1655,6 @@ tree vtabletmp2; tree vtabletmp3; - if (!vtable_entry_type) - { - tree vfunc_type = make_node (FUNCTION_TYPE); - TREE_TYPE (vfunc_type) = integer_type_node; - TYPE_ARG_TYPES (vfunc_type) = NULL_TREE; - layout_type (vfunc_type); - - vtable_entry_type = build_pointer_type (vfunc_type); - } - vtabletmp = create_tmp_reg (build_pointer_type (build_pointer_type (vtable_entry_type)), "vptr"); @@ -1694,6 +1692,41 @@ GSI_CONTINUE_LINKING); } + /* Likewise for an offset that is stored in the object that contains the + vtable. */ + if (indirect_offset != 0) + { + tree offset_ptr, offset_tree; + + /* Get the address of the offset. */ + offset_ptr + = create_tmp_reg (build_pointer_type + (build_pointer_type (vtable_entry_type)), + "offset_ptr"); + stmt = gimple_build_assign (offset_ptr, + build1 (NOP_EXPR, TREE_TYPE (offset_ptr), + ptr)); + gsi_insert_after (bsi, stmt, GSI_NEW_STMT); + + stmt = gimple_build_assign + (offset_ptr, + fold_build_pointer_plus_hwi_loc (input_location, offset_ptr, + indirect_offset)); + gsi_insert_after (bsi, stmt, GSI_NEW_STMT); + + /* Get the offset itself. */ + offset_tree = create_tmp_reg (TREE_TYPE (TREE_TYPE (offset_ptr)), + "offset"); + stmt = gimple_build_assign (offset_tree, + build_simple_mem_ref (offset_ptr)); + gsi_insert_after (bsi, stmt, GSI_NEW_STMT); + + /* Adjust the `this' pointer. */ + ptr = fold_build_pointer_plus_loc (input_location, ptr, offset_tree); + ptr = force_gimple_operand_gsi (bsi, ptr, true, NULL_TREE, false, + GSI_CONTINUE_LINKING); + } + if (!this_adjusting && fixed_offset != 0) /* Adjust the pointer by the constant. */ @@ -1732,6 +1765,7 @@ bool this_adjusting = thunk.this_adjusting; HOST_WIDE_INT fixed_offset = thunk.fixed_offset; HOST_WIDE_INT virtual_value = thunk.virtual_value; + HOST_WIDE_INT indirect_offset = thunk.indirect_offset; tree virtual_offset = NULL; tree alias = callees->callee->decl; tree thunk_fndecl = decl; @@ -1742,7 +1776,11 @@ if (thunk.add_pointer_bounds_args) return false; - if (!force_gimple_thunk && this_adjusting + if (!force_gimple_thunk + && this_adjusting + && indirect_offset == 0 + && !DECL_EXTERNAL (alias) + && !DECL_STATIC_CHAIN (alias) && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, virtual_value, alias)) { @@ -1815,7 +1853,6 @@ int i; tree resdecl; tree restmp = NULL; - tree resbnd = NULL; gcall *call; greturn *ret; @@ -1825,6 +1862,12 @@ DECL_ARGUMENTS. In this case force_gimple_thunk is true. */ if (in_lto_p && !force_gimple_thunk) get_untransformed_body (); + + /* We need to force DECL_IGNORED_P when the thunk is created + after early debug was run. */ + if (force_gimple_thunk) + DECL_IGNORED_P (thunk_fndecl) = 1; + a = DECL_ARGUMENTS (thunk_fndecl); current_function_decl = thunk_fndecl; @@ -1833,7 +1876,6 @@ resolve_unique_section (thunk_fndecl, 0, flag_function_sections); - DECL_IGNORED_P (thunk_fndecl) = 1; bitmap_obstack_initialize (NULL); if (thunk.virtual_offset_p) @@ -1846,14 +1888,18 @@ resdecl = build_decl (input_location, RESULT_DECL, 0, restype); DECL_ARTIFICIAL (resdecl) = 1; DECL_IGNORED_P (resdecl) = 1; + DECL_CONTEXT (resdecl) = thunk_fndecl; DECL_RESULT (thunk_fndecl) = resdecl; - DECL_CONTEXT (DECL_RESULT (thunk_fndecl)) = thunk_fndecl; } else resdecl = DECL_RESULT (thunk_fndecl); + profile_count cfg_count = count; + if (!cfg_count.initialized_p ()) + cfg_count = profile_count::from_gcov_type (BB_FREQ_MAX).guessed_local (); + bb = then_bb = else_bb = return_bb - = init_lowered_empty_function (thunk_fndecl, true, count); + = init_lowered_empty_function (thunk_fndecl, true, cfg_count); bsi = gsi_start_bb (bb); @@ -1880,8 +1926,11 @@ restmp = resdecl; if (VAR_P (restmp)) - add_local_decl (cfun, restmp); - BLOCK_VARS (DECL_INITIAL (current_function_decl)) = restmp; + { + add_local_decl (cfun, restmp); + BLOCK_VARS (DECL_INITIAL (current_function_decl)) + = restmp; + } } else restmp = create_tmp_var (restype, "retval"); @@ -1898,7 +1947,7 @@ if (this_adjusting) { vargs.quick_push (thunk_adjust (&bsi, a, 1, fixed_offset, - virtual_offset)); + virtual_offset, indirect_offset)); arg = DECL_CHAIN (a); i = 1; } @@ -1923,7 +1972,25 @@ call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs); callees->call_stmt = call; gimple_call_set_from_thunk (call, true); - gimple_call_set_with_bounds (call, instrumentation_clone); + if (DECL_STATIC_CHAIN (alias)) + { + tree p = DECL_STRUCT_FUNCTION (alias)->static_chain_decl; + tree type = TREE_TYPE (p); + tree decl = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl), + PARM_DECL, create_tmp_var_name ("CHAIN"), + type); + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_USED (decl) = 1; + DECL_CONTEXT (decl) = thunk_fndecl; + DECL_ARG_TYPE (decl) = type; + TREE_READONLY (decl) = 1; + + struct function *sf = DECL_STRUCT_FUNCTION (thunk_fndecl); + sf->static_chain_decl = decl; + + gimple_call_set_chain (call, decl); + } /* Return slot optimization is always possible and in fact requred to return values with DECL_BY_REFERENCE. */ @@ -1941,17 +2008,6 @@ gsi_insert_after (&bsi, call, GSI_NEW_STMT); if (!alias_is_noreturn) { - if (instrumentation_clone - && !DECL_BY_REFERENCE (resdecl) - && restmp - && BOUNDED_P (restmp)) - { - resbnd = chkp_insert_retbnd_call (NULL, restmp, &bsi); - create_edge (get_create (gimple_call_fndecl (gsi_stmt (bsi))), - as_a <gcall *> (gsi_stmt (bsi)), - callees->count, callees->frequency); - } - if (restmp && !this_adjusting && (fixed_offset || virtual_offset)) { @@ -1966,14 +2022,11 @@ adjustment, because that's why we're emitting a thunk. */ then_bb = create_basic_block (NULL, bb); - then_bb->count = count - count.apply_scale (1, 16); - then_bb->frequency = BB_FREQ_MAX - BB_FREQ_MAX / 16; + then_bb->count = cfg_count - cfg_count.apply_scale (1, 16); return_bb = create_basic_block (NULL, then_bb); - return_bb->count = count; - return_bb->frequency = BB_FREQ_MAX; + return_bb->count = cfg_count; else_bb = create_basic_block (NULL, else_bb); - then_bb->count = count.apply_scale (1, 16); - then_bb->frequency = BB_FREQ_MAX / 16; + else_bb->count = cfg_count.apply_scale (1, 16); add_bb_to_loop (then_bb, bb->loop_father); add_bb_to_loop (return_bb, bb->loop_father); add_bb_to_loop (else_bb, bb->loop_father); @@ -1998,7 +2051,8 @@ } restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0, - fixed_offset, virtual_offset); + fixed_offset, virtual_offset, + indirect_offset); if (true_label) { gimple *stmt; @@ -2017,7 +2071,6 @@ ret = gimple_build_return (restmp); else ret = gimple_build_return (resdecl); - gimple_return_set_retbnd (ret, resbnd); gsi_insert_after (&bsi, ret, GSI_NEW_STMT); } @@ -2028,8 +2081,10 @@ } cfun->gimple_df->in_ssa_p = true; + update_max_bb_count (); profile_status_for_fn (cfun) - = count.initialized_p () ? PROFILE_READ : PROFILE_GUESSED; + = cfg_count.initialized_p () && cfg_count.ipa_p () + ? PROFILE_READ : PROFILE_GUESSED; /* FIXME: C++ FE should stop setting TREE_ASM_WRITTEN on thunks. */ TREE_ASM_WRITTEN (thunk_fndecl) = false; delete_unreachable_blocks (); @@ -2149,24 +2204,26 @@ /* If requested, warn about function definitions where the function will return a value (usually of some struct or union type) which itself will take up a lot of stack space. */ - if (warn_larger_than && !DECL_EXTERNAL (decl) && TREE_TYPE (decl)) + if (!DECL_EXTERNAL (decl) && TREE_TYPE (decl)) { tree ret_type = TREE_TYPE (TREE_TYPE (decl)); if (ret_type && TYPE_SIZE_UNIT (ret_type) && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST - && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type), - larger_than_size)) + && compare_tree_int (TYPE_SIZE_UNIT (ret_type), + warn_larger_than_size) > 0) { unsigned int size_as_int = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type)); if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0) - warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes", + warning (OPT_Wlarger_than_, + "size of return value of %q+D is %u bytes", decl, size_as_int); else - warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes", - decl, larger_than_size); + warning (OPT_Wlarger_than_, + "size of return value of %q+D is larger than %wu bytes", + decl, warn_larger_than_size); } } @@ -2452,8 +2509,11 @@ if (flag_generate_lto || flag_generate_offload) targetm.asm_out.lto_start (); - if (!in_lto_p) + if (!in_lto_p + || flag_incremental_link == INCREMENTAL_LINK_LTO) { + if (!quiet_flag) + fprintf (stderr, "Streaming LTO\n"); if (g->have_offload) { section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX; @@ -2472,7 +2532,9 @@ if (flag_generate_lto || flag_generate_offload) targetm.asm_out.lto_end (); - if (!flag_ltrans && (in_lto_p || !flag_lto || flag_fat_lto_objects)) + if (!flag_ltrans + && ((in_lto_p && flag_incremental_link != INCREMENTAL_LINK_LTO) + || !flag_lto || flag_fat_lto_objects)) execute_ipa_pass_list (passes->all_regular_ipa_passes); invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL); @@ -2498,13 +2560,9 @@ symbol_table::output_weakrefs (void) { symtab_node *node; - cgraph_node *cnode; FOR_EACH_SYMBOL (node) if (node->alias && !TREE_ASM_WRITTEN (node->decl) - && (!(cnode = dyn_cast <cgraph_node *> (node)) - || !cnode->instrumented_version - || !TREE_ASM_WRITTEN (cnode->instrumented_version->decl)) && node->weakref) { tree target; @@ -2559,7 +2617,8 @@ /* Do nothing else if any IPA pass found errors or if we are just streaming LTO. */ if (seen_error () - || (!in_lto_p && flag_lto && !flag_fat_lto_objects)) + || ((!in_lto_p || flag_incremental_link == INCREMENTAL_LINK_LTO) + && flag_lto && !flag_fat_lto_objects)) { timevar_pop (TV_CGRAPHOPT); return; @@ -2579,6 +2638,7 @@ timevar_pop (TV_CGRAPHOPT); /* Output everything. */ + switch_to_section (text_section); (*debug_hooks->assembly_start) (); if (!quiet_flag) fprintf (stderr, "Assembling functions:\n"); @@ -2654,6 +2714,89 @@ } } +/* Earlydebug dump file, flags, and number. */ + +static int debuginfo_early_dump_nr; +static FILE *debuginfo_early_dump_file; +static dump_flags_t debuginfo_early_dump_flags; + +/* Debug dump file, flags, and number. */ + +static int debuginfo_dump_nr; +static FILE *debuginfo_dump_file; +static dump_flags_t debuginfo_dump_flags; + +/* Register the debug and earlydebug dump files. */ + +void +debuginfo_early_init (void) +{ + gcc::dump_manager *dumps = g->get_dumps (); + debuginfo_early_dump_nr = dumps->dump_register (".earlydebug", "earlydebug", + "earlydebug", DK_tree, + OPTGROUP_NONE, + false); + debuginfo_dump_nr = dumps->dump_register (".debug", "debug", + "debug", DK_tree, + OPTGROUP_NONE, + false); +} + +/* Initialize the debug and earlydebug dump files. */ + +void +debuginfo_init (void) +{ + gcc::dump_manager *dumps = g->get_dumps (); + debuginfo_dump_file = dump_begin (debuginfo_dump_nr, NULL); + debuginfo_dump_flags = dumps->get_dump_file_info (debuginfo_dump_nr)->pflags; + debuginfo_early_dump_file = dump_begin (debuginfo_early_dump_nr, NULL); + debuginfo_early_dump_flags + = dumps->get_dump_file_info (debuginfo_early_dump_nr)->pflags; +} + +/* Finalize the debug and earlydebug dump files. */ + +void +debuginfo_fini (void) +{ + if (debuginfo_dump_file) + dump_end (debuginfo_dump_nr, debuginfo_dump_file); + if (debuginfo_early_dump_file) + dump_end (debuginfo_early_dump_nr, debuginfo_early_dump_file); +} + +/* Set dump_file to the debug dump file. */ + +void +debuginfo_start (void) +{ + set_dump_file (debuginfo_dump_file); +} + +/* Undo setting dump_file to the debug dump file. */ + +void +debuginfo_stop (void) +{ + set_dump_file (NULL); +} + +/* Set dump_file to the earlydebug dump file. */ + +void +debuginfo_early_start (void) +{ + set_dump_file (debuginfo_early_dump_file); +} + +/* Undo setting dump_file to the earlydebug dump file. */ + +void +debuginfo_early_stop (void) +{ + set_dump_file (NULL); +} /* Analyze the whole compilation unit once it is parsed completely. */ @@ -2709,7 +2852,9 @@ /* Clean up anything that needs cleaning up after initial debug generation. */ + debuginfo_early_start (); (*debug_hooks->early_finish) (main_input_filename); + debuginfo_early_stop (); } /* Finally drive the pass manager. */ @@ -2759,7 +2904,7 @@ memset (&thunk, 0, sizeof (cgraph_thunk_info)); thunk.thunk_p = true; - create_edge (target, NULL, count, CGRAPH_FREQ_BASE); + create_edge (target, NULL, count); callees->can_throw_external = !TREE_NOTHROW (target->decl); tree arguments = DECL_ARGUMENTS (decl);