/* Localize comdats.
- Copyright (C) 2014 Free Software Foundation, Inc.
+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
This file is part of GCC.
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "hash-map.h"
-#include "is-a.h"
-#include "plugin-api.h"
-#include "vec.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "hard-reg-set.h"
-#include "input.h"
-#include "function.h"
-#include "ipa-ref.h"
-#include "cgraph.h"
#include "tree-pass.h"
+#include "cgraph.h"
/* Main dataflow loop propagating comdat groups across
the symbol table. All references to SYMBOL are examined
continue;
}
- /* One COMDAT group can not hold both variables and functions at
+ /* One COMDAT group cannot hold both variables and functions at
a same time. For now we just go to BOTTOM, in future we may
invent special comdat groups for this case. */
{
struct symtab_node *symbol2 = edge->caller;
- /* If we see inline clone, its comdat group actually
- corresponds to the comdat group of the function it is inlined
- to. */
-
if (cgraph_node * cn = dyn_cast <cgraph_node *> (symbol2))
{
+ /* Thunks cannot call across section boundary. */
+ if (cn->thunk.thunk_p)
+ newgroup = propagate_comdat_group (symbol2, newgroup, map);
+ /* If we see inline clone, its comdat group actually
+ corresponds to the comdat group of the function it
+ is inlined to. */
if (cn->global.inlined_to)
symbol2 = cn->global.inlined_to;
}
for (i = 0; symbol->iterate_reference (i, ref); i++)
{
symtab_node *node = ref->referred->ultimate_alias_target ();
+
+ /* Always keep thunks in same sections as target function. */
+ if (is_a <cgraph_node *>(node))
+ node = dyn_cast <cgraph_node *> (node)->function_symbol ();
if (!node->aux && node->definition)
{
node->aux = *first;
else
{
symtab_node *node = edge->callee->ultimate_alias_target ();
+
+ /* Always keep thunks in same sections as target function. */
+ if (is_a <cgraph_node *>(node))
+ node = dyn_cast <cgraph_node *> (node)->function_symbol ();
if (!node->aux && node->definition)
{
node->aux = *first;
}
/* Set comdat group of SYMBOL to GROUP.
- Callback for symtab_for_node_and_aliases. */
+ Callback for for_node_and_aliases. */
bool
set_comdat_group (symtab_node *symbol,
symtab_node *head = (symtab_node *)head_p;
gcc_assert (!symbol->get_comdat_group ());
- symbol->set_comdat_group (head->get_comdat_group ());
- symbol->add_to_same_comdat_group (head);
+ if (symbol->real_symbol_p ())
+ {
+ symbol->set_comdat_group (head->get_comdat_group ());
+ symbol->add_to_same_comdat_group (head);
+ }
return false;
}
+/* Set comdat group of SYMBOL to GROUP.
+ Callback for for_node_thunks_and_aliases. */
+
+bool
+set_comdat_group_1 (cgraph_node *symbol,
+ void *head_p)
+{
+ return set_comdat_group (symbol, head_p);
+}
+
/* The actual pass with the main dataflow loop. */
static unsigned int
/* 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
+ /* See symbols that cannot 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
&& (DECL_STATIC_CONSTRUCTOR (symbol->decl)
|| DECL_STATIC_DESTRUCTOR (symbol->decl))))
{
- map.put (symbol->ultimate_alias_target (), error_mark_node);
+ symtab_node *target = symbol->ultimate_alias_target ();
+
+ /* Always keep thunks in same sections as target function. */
+ if (is_a <cgraph_node *>(target))
+ target = dyn_cast <cgraph_node *> (target)->function_symbol ();
+ map.put (target, error_mark_node);
/* Mark the symbol so we won't waste time visiting it for dataflow. */
symbol->aux = (symtab_node *) (void *) 1;
FOR_EACH_DEFINED_SYMBOL (symbol)
{
+ struct cgraph_node *fun;
symbol->aux = NULL;
if (!symbol->get_comdat_group ()
&& !symbol->alias
+ && (!(fun = dyn_cast <cgraph_node *> (symbol))
+ || !fun->thunk.thunk_p)
&& symbol->real_symbol_p ())
{
- tree group = *map.get (symbol);
+ 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;
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);
+ if (is_a <cgraph_node *> (symbol))
+ dyn_cast <cgraph_node *>(symbol)->call_for_symbol_thunks_and_aliases
+ (set_comdat_group_1,
+ *comdat_head_map.get (group),
+ true);
+ else
+ symbol->call_for_symbol_and_aliases
+ (set_comdat_group,
+ *comdat_head_map.get (group),
+ true);
}
}
return 0;
bool
pass_ipa_comdats::gate (function *)
{
- return optimize;
+ return HAVE_COMDAT_GROUP;
}
} // anon namespace