static void unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr) { DECL_BUILT_IN_CLASS (expr) = bp_unpack_enum (bp, built_in_class, BUILT_IN_LAST); DECL_STATIC_CONSTRUCTOR (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_STATIC_DESTRUCTOR (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_UNINLINABLE (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_POSSIBLY_INLINED (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_IS_NOVOPS (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_IS_RETURNS_TWICE (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_IS_MALLOC (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_IS_OPERATOR_NEW (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_DECLARED_INLINE_P (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_STATIC_CHAIN (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_NO_INLINE_WARNING_P (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_NO_LIMIT_STACK (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_DISREGARD_INLINE_LIMITS (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_LOOPING_CONST_OR_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1); if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN) { DECL_FUNCTION_CODE (expr) = (enum built_in_function) bp_unpack_value (bp, 12); if (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (expr) >= END_BUILTINS) fatal_error (input_location, "machine independent builtin code out of range"); else if (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_MD) { tree result = targetm.builtin_decl (DECL_FUNCTION_CODE (expr), true); if (!result || result == error_mark_node) fatal_error (input_location, "target specific builtin not available"); } } }
symtab_node symtab_nonoverwritable_alias (symtab_node node) { tree new_decl; symtab_node new_node = NULL; symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1, (void *)&new_node, true); if (new_node) return new_node; new_decl = copy_node (node->symbol.decl); DECL_NAME (new_decl) = clone_function_name (node->symbol.decl, "localalias"); if (TREE_CODE (new_decl) == FUNCTION_DECL) DECL_STRUCT_FUNCTION (new_decl) = NULL; DECL_INITIAL (new_decl) = NULL; SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); SET_DECL_RTL (new_decl, NULL); /* Update the properties. */ DECL_EXTERNAL (new_decl) = 0; if (DECL_ONE_ONLY (node->symbol.decl)) DECL_SECTION_NAME (new_decl) = NULL; DECL_COMDAT_GROUP (new_decl) = 0; TREE_PUBLIC (new_decl) = 0; DECL_COMDAT (new_decl) = 0; DECL_WEAK (new_decl) = 0; DECL_VIRTUAL_P (new_decl) = 0; if (TREE_CODE (new_decl) == FUNCTION_DECL) { DECL_STATIC_CONSTRUCTOR (new_decl) = 0; DECL_STATIC_DESTRUCTOR (new_decl) = 0; new_node = (symtab_node) cgraph_create_function_alias (new_decl, node->symbol.decl); } else new_node = (symtab_node) varpool_create_variable_alias (new_decl, node->symbol.decl); symtab_resolve_alias (new_node, node); return new_node; }
static void pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr) { bp_pack_enum (bp, built_in_class, BUILT_IN_LAST, DECL_BUILT_IN_CLASS (expr)); bp_pack_value (bp, DECL_STATIC_CONSTRUCTOR (expr), 1); bp_pack_value (bp, DECL_STATIC_DESTRUCTOR (expr), 1); bp_pack_value (bp, DECL_UNINLINABLE (expr), 1); bp_pack_value (bp, DECL_POSSIBLY_INLINED (expr), 1); bp_pack_value (bp, DECL_IS_NOVOPS (expr), 1); bp_pack_value (bp, DECL_IS_RETURNS_TWICE (expr), 1); bp_pack_value (bp, DECL_IS_MALLOC (expr), 1); bp_pack_value (bp, DECL_IS_OPERATOR_NEW (expr), 1); bp_pack_value (bp, DECL_DECLARED_INLINE_P (expr), 1); bp_pack_value (bp, DECL_STATIC_CHAIN (expr), 1); bp_pack_value (bp, DECL_NO_INLINE_WARNING_P (expr), 1); bp_pack_value (bp, DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (expr), 1); bp_pack_value (bp, DECL_NO_LIMIT_STACK (expr), 1); bp_pack_value (bp, DECL_DISREGARD_INLINE_LIMITS (expr), 1); bp_pack_value (bp, DECL_PURE_P (expr), 1); bp_pack_value (bp, DECL_LOOPING_CONST_OR_PURE_P (expr), 1); if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN) bp_pack_value (bp, DECL_FUNCTION_CODE (expr), 12); }
static unsigned int ipa_comdats (void) { hash_map<symtab_node *, tree> map (251); hash_map<tree, symtab_node *> comdat_head_map (251); symtab_node *symbol; bool comdat_group_seen = false; symtab_node *first = (symtab_node *) (void *) 1; tree group; /* Start the dataflow by assigning comdat group to symbols that are in comdat groups already. All other externally visible symbols must stay, we use ERROR_MARK_NODE as bottom for the propagation. */ FOR_EACH_DEFINED_SYMBOL (symbol) if (!symbol->real_symbol_p ()) ; else if ((group = symbol->get_comdat_group ()) != NULL) { map.put (symbol, group); comdat_head_map.put (group, symbol); comdat_group_seen = true; /* Mark the symbol so we won't waste time visiting it for dataflow. */ symbol->aux = (symtab_node *) (void *) 1; } /* See symbols that can not be privatized to comdats; that is externally visible symbols or otherwise used ones. We also do not want to mangle user section names. */ else if (symbol->externally_visible || symbol->force_output || symbol->used_from_other_partition || TREE_THIS_VOLATILE (symbol->decl) || symbol->get_section () || (TREE_CODE (symbol->decl) == FUNCTION_DECL && (DECL_STATIC_CONSTRUCTOR (symbol->decl) || DECL_STATIC_DESTRUCTOR (symbol->decl)))) { map.put (symbol->ultimate_alias_target (), error_mark_node); /* Mark the symbol so we won't waste time visiting it for dataflow. */ symbol->aux = (symtab_node *) (void *) 1; } else { /* Enqueue symbol for dataflow. */ symbol->aux = first; first = symbol; } if (!comdat_group_seen) { FOR_EACH_DEFINED_SYMBOL (symbol) symbol->aux = NULL; return 0; } /* The actual dataflow. */ while (first != (void *) 1) { tree group = NULL; tree newgroup, *val; symbol = first; first = (symtab_node *)first->aux; /* Get current lattice value of SYMBOL. */ val = map.get (symbol); if (val) group = *val; /* If it is bottom, there is nothing to do; do not clear AUX so we won't re-queue the symbol. */ if (group == error_mark_node) continue; newgroup = propagate_comdat_group (symbol, group, map); /* If nothing changed, proceed to next symbol. */ if (newgroup == group) { symbol->aux = NULL; continue; } /* Update lattice value and enqueue all references for re-visiting. */ gcc_assert (newgroup); if (val) *val = newgroup; else map.put (symbol, newgroup); enqueue_references (&first, symbol); /* We may need to revisit the symbol unless it is BOTTOM. */ if (newgroup != error_mark_node) symbol->aux = NULL; } /* Finally assign symbols to the sections. */ FOR_EACH_DEFINED_SYMBOL (symbol) { struct cgraph_node *fun; symbol->aux = NULL; if (!symbol->get_comdat_group () && !symbol->alias /* Thunks to external functions do not need to be categorized. */ && (!(fun = dyn_cast <cgraph_node *> (symbol)) || !fun->thunk.thunk_p || fun->function_symbol ()->definition) && symbol->real_symbol_p ()) { tree *val = map.get (symbol); /* A NULL here means that SYMBOL is unreachable in the definition of ipa-comdats. Either ipa-comdats is wrong about this or someone forgot to cleanup and remove unreachable functions earlier. */ gcc_assert (val); tree group = *val; if (group == error_mark_node) continue; if (dump_file) { fprintf (dump_file, "Localizing symbol\n"); symbol->dump (dump_file); fprintf (dump_file, "To group: %s\n", IDENTIFIER_POINTER (group)); } symbol->call_for_symbol_and_aliases (set_comdat_group, *comdat_head_map.get (group), true); } } return 0; }
void dump_symtab_base (FILE *f, symtab_node node) { static const char * const visibility_types[] = { "default", "protected", "hidden", "internal" }; fprintf (f, "%s/%i (%s)", symtab_node_asm_name (node), node->symbol.order, symtab_node_name (node)); dump_addr (f, " @", (void *)node); fprintf (f, "\n Type: %s\n", symtab_type_names[node->symbol.type]); fprintf (f, " Visibility:"); if (node->symbol.in_other_partition) fprintf (f, " in_other_partition"); if (node->symbol.used_from_other_partition) fprintf (f, " used_from_other_partition"); if (node->symbol.force_output) fprintf (f, " force_output"); if (node->symbol.resolution != LDPR_UNKNOWN) fprintf (f, " %s", ld_plugin_symbol_resolution_names[(int)node->symbol.resolution]); if (TREE_ASM_WRITTEN (node->symbol.decl)) fprintf (f, " asm_written"); if (DECL_EXTERNAL (node->symbol.decl)) fprintf (f, " external"); if (TREE_PUBLIC (node->symbol.decl)) fprintf (f, " public"); if (DECL_COMMON (node->symbol.decl)) fprintf (f, " common"); if (DECL_WEAK (node->symbol.decl)) fprintf (f, " weak"); if (DECL_DLLIMPORT_P (node->symbol.decl)) fprintf (f, " dll_import"); if (DECL_COMDAT (node->symbol.decl)) fprintf (f, " comdat"); if (DECL_COMDAT_GROUP (node->symbol.decl)) fprintf (f, " comdat_group:%s", IDENTIFIER_POINTER (DECL_COMDAT_GROUP (node->symbol.decl))); if (DECL_ONE_ONLY (node->symbol.decl)) fprintf (f, " one_only"); if (DECL_SECTION_NAME (node->symbol.decl)) fprintf (f, " section_name:%s", TREE_STRING_POINTER (DECL_SECTION_NAME (node->symbol.decl))); if (DECL_VISIBILITY_SPECIFIED (node->symbol.decl)) fprintf (f, " visibility_specified"); if (DECL_VISIBILITY (node->symbol.decl)) fprintf (f, " visibility:%s", visibility_types [DECL_VISIBILITY (node->symbol.decl)]); if (DECL_VIRTUAL_P (node->symbol.decl)) fprintf (f, " virtual"); if (DECL_ARTIFICIAL (node->symbol.decl)) fprintf (f, " artificial"); if (TREE_CODE (node->symbol.decl) == FUNCTION_DECL) { if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)) fprintf (f, " constructor"); if (DECL_STATIC_DESTRUCTOR (node->symbol.decl)) fprintf (f, " destructor"); } fprintf (f, "\n"); if (node->symbol.same_comdat_group) fprintf (f, " Same comdat group as: %s/%i\n", symtab_node_asm_name (node->symbol.same_comdat_group), node->symbol.same_comdat_group->symbol.order); if (node->symbol.next_sharing_asm_name) fprintf (f, " next sharing asm name: %i\n", node->symbol.next_sharing_asm_name->symbol.order); if (node->symbol.previous_sharing_asm_name) fprintf (f, " previous sharing asm name: %i\n", node->symbol.previous_sharing_asm_name->symbol.order); if (node->symbol.address_taken) fprintf (f, " Address is taken.\n"); if (node->symbol.aux) { fprintf (f, " Aux:"); dump_addr (f, " @", (void *)node->symbol.aux); } fprintf (f, " References: "); ipa_dump_references (f, &node->symbol.ref_list); fprintf (f, " Referring: "); ipa_dump_referring (f, &node->symbol.ref_list); }
void symtab_node::dump_base (FILE *f) { static const char * const visibility_types[] = { "default", "protected", "hidden", "internal" }; fprintf (f, "%s/%i (%s)", asm_name (), order, name ()); dump_addr (f, " @", (void *)this); fprintf (f, "\n Type: %s", symtab_type_names[type]); if (definition) fprintf (f, " definition"); if (analyzed) fprintf (f, " analyzed"); if (alias) fprintf (f, " alias"); if (weakref) fprintf (f, " weakref"); if (cpp_implicit_alias) fprintf (f, " cpp_implicit_alias"); if (alias_target) fprintf (f, " target:%s", DECL_P (alias_target) ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (alias_target)) : IDENTIFIER_POINTER (alias_target)); if (body_removed) fprintf (f, "\n Body removed by symtab_remove_unreachable_nodes"); fprintf (f, "\n Visibility:"); if (in_other_partition) fprintf (f, " in_other_partition"); if (used_from_other_partition) fprintf (f, " used_from_other_partition"); if (force_output) fprintf (f, " force_output"); if (forced_by_abi) fprintf (f, " forced_by_abi"); if (externally_visible) fprintf (f, " externally_visible"); if (resolution != LDPR_UNKNOWN) fprintf (f, " %s", ld_plugin_symbol_resolution_names[(int)resolution]); if (TREE_ASM_WRITTEN (decl)) fprintf (f, " asm_written"); if (DECL_EXTERNAL (decl)) fprintf (f, " external"); if (TREE_PUBLIC (decl)) fprintf (f, " public"); if (DECL_COMMON (decl)) fprintf (f, " common"); if (DECL_WEAK (decl)) fprintf (f, " weak"); if (DECL_DLLIMPORT_P (decl)) fprintf (f, " dll_import"); if (DECL_COMDAT (decl)) fprintf (f, " comdat"); if (get_comdat_group ()) fprintf (f, " comdat_group:%s", IDENTIFIER_POINTER (get_comdat_group_id ())); if (DECL_ONE_ONLY (decl)) fprintf (f, " one_only"); if (get_section ()) fprintf (f, " section:%s", get_section ()); if (implicit_section) fprintf (f," (implicit_section)"); if (DECL_VISIBILITY_SPECIFIED (decl)) fprintf (f, " visibility_specified"); if (DECL_VISIBILITY (decl)) fprintf (f, " visibility:%s", visibility_types [DECL_VISIBILITY (decl)]); if (DECL_VIRTUAL_P (decl)) fprintf (f, " virtual"); if (DECL_ARTIFICIAL (decl)) fprintf (f, " artificial"); if (TREE_CODE (decl) == FUNCTION_DECL) { if (DECL_STATIC_CONSTRUCTOR (decl)) fprintf (f, " constructor"); if (DECL_STATIC_DESTRUCTOR (decl)) fprintf (f, " destructor"); } fprintf (f, "\n"); if (same_comdat_group) fprintf (f, " Same comdat group as: %s/%i\n", same_comdat_group->asm_name (), same_comdat_group->order); if (next_sharing_asm_name) fprintf (f, " next sharing asm name: %i\n", next_sharing_asm_name->order); if (previous_sharing_asm_name) fprintf (f, " previous sharing asm name: %i\n", previous_sharing_asm_name->order); if (address_taken) fprintf (f, " Address is taken.\n"); if (aux) { fprintf (f, " Aux:"); dump_addr (f, " @", (void *)aux); } fprintf (f, " References: "); dump_references (f); fprintf (f, " Referring: "); dump_referring (f); if (lto_file_data) fprintf (f, " Read from file: %s\n", lto_file_data->file_name); }
static unsigned int ipa_comdats (void) { pointer_map<tree> map; pointer_map<symtab_node *> comdat_head_map; symtab_node *symbol; bool comdat_group_seen = false; symtab_node *first = (symtab_node *) (void *) 1; tree group; /* Start the dataflow by assigning comdat group to symbols that are in comdat groups already. All other externally visible symbols must stay, we use ERROR_MARK_NODE as bottom for the propagation. */ FOR_EACH_DEFINED_SYMBOL (symbol) if (!symtab_real_symbol_p (symbol)) ; else if ((group = symbol->get_comdat_group ()) != NULL) { *map.insert (symbol) = group; *comdat_head_map.insert (group) = symbol; comdat_group_seen = true; /* Mark the symbol so we won't waste time visiting it for dataflow. */ symbol->aux = (symtab_node *) (void *) 1; } /* See symbols that can not be privatized to comdats; that is externally visible symbols or otherwise used ones. We also do not want to mangle user section names. */ else if (symbol->externally_visible || symbol->force_output || symbol->used_from_other_partition || TREE_THIS_VOLATILE (symbol->decl) || symbol->get_section () || (TREE_CODE (symbol->decl) == FUNCTION_DECL && (DECL_STATIC_CONSTRUCTOR (symbol->decl) || DECL_STATIC_DESTRUCTOR (symbol->decl)))) { *map.insert (symtab_alias_ultimate_target (symbol, NULL)) = error_mark_node; /* Mark the symbol so we won't waste time visiting it for dataflow. */ symbol->aux = (symtab_node *) (void *) 1; } else { /* Enqueue symbol for dataflow. */ symbol->aux = first; first = symbol; } if (!comdat_group_seen) { FOR_EACH_DEFINED_SYMBOL (symbol) symbol->aux = NULL; return 0; } /* The actual dataflow. */ while (first != (void *) 1) { tree group = NULL; tree newgroup, *val; symbol = first; first = (symtab_node *)first->aux; /* Get current lattice value of SYMBOL. */ val = map.contains (symbol); if (val) group = *val; /* If it is bottom, there is nothing to do; do not clear AUX so we won't re-queue the symbol. */ if (group == error_mark_node) continue; newgroup = propagate_comdat_group (symbol, group, map); /* If nothing changed, proceed to next symbol. */ if (newgroup == group) { symbol->aux = NULL; continue; } /* Update lattice value and enqueue all references for re-visiting. */ gcc_assert (newgroup); if (val) *val = newgroup; else *map.insert (symbol) = newgroup; enqueue_references (&first, symbol); /* We may need to revisit the symbol unless it is BOTTOM. */ if (newgroup != error_mark_node) symbol->aux = NULL; } /* Finally assign symbols to the sections. */ FOR_EACH_DEFINED_SYMBOL (symbol) { symbol->aux = NULL; if (!symbol->get_comdat_group () && !symbol->alias && symtab_real_symbol_p (symbol)) { tree group = *map.contains (symbol); if (group == error_mark_node) continue; if (dump_file) { fprintf (dump_file, "Localizing symbol\n"); dump_symtab_node (dump_file, symbol); fprintf (dump_file, "To group: %s\n", IDENTIFIER_POINTER (group)); } symtab_for_node_and_aliases (symbol, set_comdat_group, *comdat_head_map.contains (group), true); } } return 0; }