/* Interprocedural Identical Code Folding pass
- Copyright (C) 2014-2017 Free Software Foundation, Inc.
+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
#include "tree-cfg.h"
#include "symbol-summary.h"
#include "ipa-prop.h"
-#include "ipa-inline.h"
+#include "ipa-fnsummary.h"
#include "except.h"
#include "attribs.h"
#include "print-tree.h"
#include "ipa-icf.h"
#include "stor-layout.h"
#include "dbgcnt.h"
+#include "tree-vector-builder.h"
using namespace ipa_icf_gimple;
{
if (dump_file)
{
- fprintf (dump_file, "[%s] %s (%u) (tree:%p)\n", type == FUNC ? "func" : "var",
- node->name(), node->order, (void *) node->decl);
+ fprintf (dump_file, "[%s] %s (tree:%p)\n", type == FUNC ? "func" : "var",
+ node->dump_name (), (void *) node->decl);
fprintf (dump_file, " hash: %u\n", get_hash ());
fprintf (dump_file, " references: ");
m_hash_set = true;
}
+hash_map<const_tree, hashval_t> sem_item::m_type_hash_cache;
+
/* Semantic function constructor that uses STACK as bitmap memory stack. */
sem_function::sem_function (bitmap_obstack *stack)
/* Add common features of declaration itself. */
if (DECL_FUNCTION_SPECIFIC_TARGET (decl))
- hstate.add_wide_int
+ hstate.add_hwi
(cl_target_option_hash
(TREE_TARGET_OPTION (DECL_FUNCTION_SPECIFIC_TARGET (decl))));
if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))
- hstate.add_wide_int
+ hstate.add_hwi
(cl_optimization_hash
(TREE_OPTIMIZATION (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))));
hstate.add_flag (DECL_CXX_CONSTRUCTOR_P (decl));
return m_hash;
}
-/* Return ture if A1 and A2 represent equivalent function attribute lists.
- Based on comp_type_attributes. */
-
-bool
-sem_item::compare_attributes (const_tree a1, const_tree a2)
-{
- const_tree a;
- if (a1 == a2)
- return true;
- for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a))
- {
- const struct attribute_spec *as;
- const_tree attr;
-
- as = lookup_attribute_spec (get_attribute_name (a));
- /* TODO: We can introduce as->affects_decl_identity
- and as->affects_decl_reference_identity if attribute mismatch
- gets a common reason to give up on merging. It may not be worth
- the effort.
- For example returns_nonnull affects only references, while
- optimize attribute can be ignored because it is already lowered
- into flags representation and compared separately. */
- if (!as)
- continue;
-
- attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
- if (!attr || !attribute_value_equal (a, attr))
- break;
- }
- if (!a)
- {
- for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
- {
- const struct attribute_spec *as;
-
- as = lookup_attribute_spec (get_attribute_name (a));
- if (!as)
- continue;
-
- if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
- break;
- /* We don't need to compare trees again, as we did this
- already in first loop. */
- }
- if (!a)
- return true;
- }
- /* TODO: As in comp_type_attributes we may want to introduce target hook. */
- return false;
-}
-
/* Compare properties of symbols N1 and N2 that does not affect semantics of
symbol itself but affects semantics of its references from USED_BY (which
may be NULL if it is unknown). If comparsion is false, symbols
variables just compare attributes for references - the codegen
for constructors is affected only by those attributes that we lower
to explicit representation (such as DECL_ALIGN or DECL_SECTION). */
- if (!compare_attributes (DECL_ATTRIBUTES (n1->decl),
- DECL_ATTRIBUTES (n2->decl)))
+ if (!attribute_list_equal (DECL_ATTRIBUTES (n1->decl),
+ DECL_ATTRIBUTES (n2->decl)))
return return_false_with_msg ("different var decl attributes");
if (comp_type_attributes (TREE_TYPE (n1->decl),
TREE_TYPE (n2->decl)) != 1)
struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ());
- if (parms_info->descriptors.is_empty ()
- || parms_info->descriptors.length () <= i)
- return true;
+ if (vec_safe_length (parms_info->descriptors) <= i)
+ return true;
return ipa_is_param_used (IPA_NODE_REF (get_node ()), i);
}
return return_false_with_msg ("thunk fixed_offset mismatch");
if (cnode->thunk.virtual_value != cnode2->thunk.virtual_value)
return return_false_with_msg ("thunk virtual_value mismatch");
+ if (cnode->thunk.indirect_offset != cnode2->thunk.indirect_offset)
+ return return_false_with_msg ("thunk indirect_offset mismatch");
if (cnode->thunk.this_adjusting != cnode2->thunk.this_adjusting)
return return_false_with_msg ("thunk this_adjusting mismatch");
if (cnode->thunk.virtual_offset_p != cnode2->thunk.virtual_offset_p)
cl_optimization *opt1 = opts_for_fn (decl);
cl_optimization *opt2 = opts_for_fn (item->decl);
- if (opt1 != opt2 && memcmp (opt1, opt2, sizeof(cl_optimization)))
+ if (opt1 != opt2 && !cl_optimization_option_eq (opt1, opt2))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
if (comp_type_attributes (TREE_TYPE (decl),
TREE_TYPE (item->decl)) != 1)
return return_false_with_msg ("different type attributes");
- if (!compare_attributes (DECL_ATTRIBUTES (decl),
- DECL_ATTRIBUTES (item->decl)))
+ if (!attribute_list_equal (DECL_ATTRIBUTES (decl),
+ DECL_ATTRIBUTES (item->decl)))
return return_false_with_msg ("different decl attributes");
/* The type of THIS pointer type memory location for
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
- "Equals called for:%s:%s (%u:%u) (%s:%s) with result: %s\n\n",
- xstrdup_for_dump (node->name()),
- xstrdup_for_dump (item->node->name ()),
- node->order,
- item->node->order,
- xstrdup_for_dump (node->asm_name ()),
- xstrdup_for_dump (item->node->asm_name ()),
+ "Equals called for: %s:%s with result: %s\n\n",
+ node->dump_name (),
+ item->node->dump_name (),
eq ? "true" : "false");
return eq;
return false;
}
+ if (!original->in_same_comdat_group_p (alias)
+ || original->comdat_local_p ())
+ {
+ if (dump_file)
+ fprintf (dump_file,
+ "Not unifying; alias nor wrapper cannot be created; "
+ "across comdat group boundary\n\n");
+
+ return false;
+ }
+
/* See if original is in a section that can be discarded if the main
symbol is not used. */
fprintf (dump_file,
"can not create wrapper of stdarg function.\n");
}
- else if (inline_summaries
- && inline_summaries->get (alias)->self_size <= 2)
+ else if (ipa_fn_summaries
+ && ipa_fn_summaries->get (alias) != NULL
+ && ipa_fn_summaries->get (alias)->self_size <= 2)
{
if (dump_file)
fprintf (dump_file, "Wrapper creation is not "
are not interposable. */
redirect_callers
= alias->get_availability () > AVAIL_INTERPOSABLE
- && original->get_availability () > AVAIL_INTERPOSABLE
- && !alias->instrumented_version;
+ && original->get_availability () > AVAIL_INTERPOSABLE;
/* TODO: We can redirect, but we need to produce alias of ORIGINAL
with proper properties. */
if (!sem_item::compare_referenced_symbol_properties (NULL, original, alias,
alias->icf_merged = true;
local_original->icf_merged = true;
- ipa_merge_profiles (local_original, alias, true);
+ /* FIXME update local_original counts. */
+ ipa_merge_profiles (original, alias, true);
alias->create_wrapper (local_original);
if (dump_file)
}
}
+ hstate.commit_flag ();
gcode_hash = hstate.end ();
bb_sizes.safe_push (nondbg_stmt_count);
{
cfg_checksum = 0;
inchash::hash hstate;
- hstate.add_wide_int (cnode->thunk.fixed_offset);
- hstate.add_wide_int (cnode->thunk.virtual_value);
+ hstate.add_hwi (cnode->thunk.fixed_offset);
+ hstate.add_hwi (cnode->thunk.virtual_value);
hstate.add_flag (cnode->thunk.this_adjusting);
hstate.add_flag (cnode->thunk.virtual_offset_p);
hstate.add_flag (cnode->thunk.add_pointer_bounds_args);
unsigned HOST_WIDE_INT idx;
tree value;
- hstate.add_wide_int (int_size_in_bytes (TREE_TYPE (exp)));
+ hstate.add_hwi (int_size_in_bytes (TREE_TYPE (exp)));
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
if (value)
case VAR_DECL:
case CONST_DECL:
case PARM_DECL:
- hstate.add_wide_int (int_size_in_bytes (TREE_TYPE (exp)));
+ hstate.add_hwi (int_size_in_bytes (TREE_TYPE (exp)));
break;
case MEM_REF:
case POINTER_PLUS_EXPR:
}
break;
CASE_CONVERT:
- hstate.add_wide_int (int_size_in_bytes (TREE_TYPE (exp)));
+ hstate.add_hwi (int_size_in_bytes (TREE_TYPE (exp)));
return add_expr (TREE_OPERAND (exp, 0), hstate);
default:
break;
}
else if (RECORD_OR_UNION_TYPE_P (type))
{
- gcc_checking_assert (COMPLETE_TYPE_P (type));
- hashval_t *val = optimizer->m_type_hash_cache.get (type);
+ /* Incomplete types must be skipped here. */
+ if (!COMPLETE_TYPE_P (type))
+ {
+ hstate.add_int (RECORD_TYPE);
+ return;
+ }
+
+ hashval_t *val = m_type_hash_cache.get (type);
if (!val)
{
hashval_t hash;
hstate2.add_int (RECORD_TYPE);
- gcc_assert (COMPLETE_TYPE_P (type));
-
for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
if (TREE_CODE (f) == FIELD_DECL)
{
hstate2.add_int (nf);
hash = hstate2.end ();
- hstate.add_wide_int (hash);
- optimizer->m_type_hash_cache.put (type, hash);
+ hstate.add_hwi (hash);
+ m_type_hash_cache.put (type, hash);
}
else
- hstate.add_wide_int (*val);
+ hstate.add_hwi (*val);
}
}
if (gimple_op (stmt, i))
add_type (TREE_TYPE (gimple_op (stmt, i)), hstate);
}
+ /* Consider nocf_check attribute in hash as it affects code
+ generation. */
+ if (code == GIMPLE_CALL
+ && flag_cf_protection & CF_BRANCH)
+ hstate.add_flag (gimple_call_nocf_check_p (as_a <gcall *> (stmt)));
default:
break;
}
DECL_INITIAL (item->node->decl));
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
- "Equals called for vars:%s:%s (%u:%u) (%s:%s) with result: %s\n\n",
- xstrdup_for_dump (node->name()),
- xstrdup_for_dump (item->node->name ()),
- node->order, item->node->order,
- xstrdup_for_dump (node->asm_name ()),
- xstrdup_for_dump (item->node->asm_name ()), ret ? "true" : "false");
+ "Equals called for vars: %s:%s with result: %s\n\n",
+ node->dump_name (), item->node->dump_name (),
+ ret ? "true" : "false");
return ret;
}
/* Type of the offset on MEM_REF does not matter. */
return return_with_debug (sem_variable::equals (x1, x2)
- && wi::to_offset (y1)
- == wi::to_offset (y2));
+ && known_eq (wi::to_poly_offset (y1),
+ wi::to_poly_offset (y2)));
}
case ADDR_EXPR:
case FDESC_EXPR:
&TREE_REAL_CST (t2)));
case VECTOR_CST:
{
- unsigned i;
+ if (maybe_ne (VECTOR_CST_NELTS (t1), VECTOR_CST_NELTS (t2)))
+ return return_false_with_msg ("VECTOR_CST nelts mismatch");
- if (VECTOR_CST_NELTS (t1) != VECTOR_CST_NELTS (t2))
- return return_false_with_msg ("VECTOR_CST nelts mismatch");
+ unsigned int count
+ = tree_vector_builder::binary_encoded_nelts (t1, t2);
+ for (unsigned int i = 0; i < count; ++i)
+ if (!sem_variable::equals (VECTOR_CST_ENCODED_ELT (t1, i),
+ VECTOR_CST_ENCODED_ELT (t2, i)))
+ return false;
- for (i = 0; i < VECTOR_CST_NELTS (t1); ++i)
- if (!sem_variable::equals (VECTOR_CST_ELT (t1, i),
- VECTOR_CST_ELT (t2, i)))
- return 0;
-
- return 1;
+ return true;
}
case ARRAY_REF:
case ARRAY_RANGE_REF:
hstate.add_int (456346417);
if (DECL_SIZE (decl) && tree_fits_shwi_p (DECL_SIZE (decl)))
- hstate.add_wide_int (tree_to_shwi (DECL_SIZE (decl)));
+ hstate.add_hwi (tree_to_shwi (DECL_SIZE (decl)));
add_expr (ctor, hstate);
set_hash (hstate.end ());
return m_hash;
}
-/* Set all points-to UIDs of aliases pointing to node N as UID. */
-
-static void
-set_alias_uids (symtab_node *n, int uid)
-{
- ipa_ref *ref;
- FOR_EACH_ALIAS (n, ref)
- {
- if (dump_file)
- fprintf (dump_file, " Setting points-to UID of [%s] as %d\n",
- xstrdup_for_dump (ref->referring->asm_name ()), uid);
-
- SET_DECL_PT_UID (ref->referring->decl, uid);
- set_alias_uids (ref->referring, uid);
- }
-}
-
/* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
be applied. */
if (dump_file)
fprintf (dump_file, "Unified; Variable alias has been created.\n");
- set_alias_uids (original, DECL_UID (original->decl));
return true;
}
}
sem_item_optimizer::sem_item_optimizer ()
: worklist (0), m_classes (0), m_classes_count (0), m_cgraph_node_hooks (NULL),
- m_varpool_node_hooks (NULL)
+ m_varpool_node_hooks (NULL), m_merged_variables ()
{
m_items.create (0);
bitmap_obstack_initialize (&m_bmstack);
m_items.release ();
bitmap_obstack_release (&m_bmstack);
+ m_merged_variables.release ();
}
/* Write IPA ICF summary for symbols. */
gcc_assert (node->definition);
if (dump_file)
- fprintf (dump_file, "Symbol added:%s (tree: %p, uid:%u)\n",
- node->asm_name (), (void *) node->decl, node->order);
+ fprintf (dump_file, "Symbol added: %s (tree: %p)\n",
+ node->dump_asm_name (), (void *) node->decl);
if (is_a<cgraph_node *> (node))
{
bool merged_p = merge_classes (prev_class_count);
if (dump_file && (dump_flags & TDF_DETAILS))
- symtab_node::dump_table (dump_file);
+ symtab->dump (dump_file);
return merged_p;
}
if (TYPE_NAME (class_type)
&& DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (class_type)))
- hstate.add_wide_int
+ hstate.add_hwi
(IDENTIFIER_HASH_VALUE
(DECL_ASSEMBLER_NAME (TYPE_NAME (class_type))));
return true;
}
+/* Compare function for sorting pairs in do_congruence_step_f. */
+
+int
+sem_item_optimizer::sort_congruence_split (const void *a_, const void *b_)
+{
+ const std::pair<congruence_class *, bitmap> *a
+ = (const std::pair<congruence_class *, bitmap> *)a_;
+ const std::pair<congruence_class *, bitmap> *b
+ = (const std::pair<congruence_class *, bitmap> *)b_;
+ if (a->first->id < b->first->id)
+ return -1;
+ else if (a->first->id > b->first->id)
+ return 1;
+ return 0;
+}
+
/* Tests if a class CLS used as INDEXth splits any congruence classes.
Bitmap stack BMSTACK is used for bitmap allocation. */
}
}
+ auto_vec<std::pair<congruence_class *, bitmap> > to_split;
+ to_split.reserve_exact (split_map.elements ());
+ for (hash_map <congruence_class *, bitmap>::iterator i = split_map.begin ();
+ i != split_map.end (); ++i)
+ to_split.safe_push (*i);
+ to_split.qsort (sort_congruence_split);
+
traverse_split_pair pair;
pair.optimizer = this;
pair.cls = cls;
splitter_class_removed = false;
- split_map.traverse <traverse_split_pair *,
- sem_item_optimizer::traverse_congruence_split> (&pair);
+ for (unsigned i = 0; i < to_split.length (); ++i)
+ traverse_congruence_split (to_split[i].first, to_split[i].second, &pair);
/* Bitmap clean-up. */
split_map.traverse <traverse_split_pair *,
free (histogram);
}
+/* Sort pair of sem_items A and B by DECL_UID. */
+
+static int
+sort_sem_items_by_decl_uid (const void *a, const void *b)
+{
+ const sem_item *i1 = *(const sem_item * const *)a;
+ const sem_item *i2 = *(const sem_item * const *)b;
+
+ int uid1 = DECL_UID (i1->decl);
+ int uid2 = DECL_UID (i2->decl);
+
+ if (uid1 < uid2)
+ return -1;
+ else if (uid1 > uid2)
+ return 1;
+ else
+ return 0;
+}
+
+/* Sort pair of congruence_classes A and B by DECL_UID of the first member. */
+
+static int
+sort_congruence_classes_by_decl_uid (const void *a, const void *b)
+{
+ const congruence_class *c1 = *(const congruence_class * const *)a;
+ const congruence_class *c2 = *(const congruence_class * const *)b;
+
+ int uid1 = DECL_UID (c1->members[0]->decl);
+ int uid2 = DECL_UID (c2->members[0]->decl);
+
+ if (uid1 < uid2)
+ return -1;
+ else if (uid1 > uid2)
+ return 1;
+ else
+ return 0;
+}
+
+/* Sort pair of congruence_class_groups A and B by
+ DECL_UID of the first member of a first group. */
+
+static int
+sort_congruence_class_groups_by_decl_uid (const void *a, const void *b)
+{
+ const congruence_class_group *g1
+ = *(const congruence_class_group * const *)a;
+ const congruence_class_group *g2
+ = *(const congruence_class_group * const *)b;
+
+ int uid1 = DECL_UID (g1->classes[0]->members[0]->decl);
+ int uid2 = DECL_UID (g2->classes[0]->members[0]->decl);
+
+ if (uid1 < uid2)
+ return -1;
+ else if (uid1 > uid2)
+ return 1;
+ else
+ return 0;
+}
+
/* After reduction is done, we can declare all items in a group
to be equal. PREV_CLASS_COUNT is start number of classes
before reduction. True is returned if there's a merge operation
bool merged_p = false;
+ /* PR lto/78211
+ Sort functions in congruence classes by DECL_UID and do the same
+ for the classes to not to break -fcompare-debug. */
+
+ for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
+ it != m_classes.end (); ++it)
+ {
+ for (unsigned int i = 0; i < (*it)->classes.length (); i++)
+ {
+ congruence_class *c = (*it)->classes[i];
+ c->members.qsort (sort_sem_items_by_decl_uid);
+ }
+
+ (*it)->classes.qsort (sort_congruence_classes_by_decl_uid);
+ }
+
for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
it != m_classes.end (); ++it)
for (unsigned int i = 0; i < (*it)->classes.length (); i++)
}
}
+ auto_vec <congruence_class_group *> classes (m_classes.elements ());
+ for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
+ it != m_classes.end (); ++it)
+ classes.quick_push (*it);
+
+ classes.qsort (sort_congruence_class_groups_by_decl_uid);
+
if (dump_file)
{
fprintf (dump_file, "\nItem count: %u\n", item_count);
item_count ? 100.0f * equal_items / item_count : 0.0f);
}
- for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
- it != m_classes.end (); ++it)
- for (unsigned int i = 0; i < (*it)->classes.length (); i++)
+ unsigned int l;
+ congruence_class_group *it;
+ FOR_EACH_VEC_ELT (classes, l, it)
+ for (unsigned int i = 0; i < it->classes.length (); i++)
{
- congruence_class *c = (*it)->classes[i];
+ congruence_class *c = it->classes[i];
if (c->members.length () == 1)
continue;
}
if (dbg_cnt (merged_ipa_icf))
- merged_p |= source->merge (alias);
+ {
+ bool merged = source->merge (alias);
+ merged_p |= merged;
+
+ if (merged && alias->type == VAR)
+ {
+ symtab_pair p = symtab_pair (source->node, alias->node);
+ m_merged_variables.safe_push (p);
+ }
+ }
}
}
+ if (!m_merged_variables.is_empty ())
+ fixup_points_to_sets ();
+
return merged_p;
}
+/* Fixup points to set PT. */
+
+void
+sem_item_optimizer::fixup_pt_set (struct pt_solution *pt)
+{
+ if (pt->vars == NULL)
+ return;
+
+ unsigned i;
+ symtab_pair *item;
+ FOR_EACH_VEC_ELT (m_merged_variables, i, item)
+ if (bitmap_bit_p (pt->vars, DECL_UID (item->second->decl)))
+ bitmap_set_bit (pt->vars, DECL_UID (item->first->decl));
+}
+
+/* Set all points-to UIDs of aliases pointing to node N as UID. */
+
+static void
+set_alias_uids (symtab_node *n, int uid)
+{
+ ipa_ref *ref;
+ FOR_EACH_ALIAS (n, ref)
+ {
+ if (dump_file)
+ fprintf (dump_file, " Setting points-to UID of [%s] as %d\n",
+ xstrdup_for_dump (ref->referring->asm_name ()), uid);
+
+ SET_DECL_PT_UID (ref->referring->decl, uid);
+ set_alias_uids (ref->referring, uid);
+ }
+}
+
+/* Fixup points to analysis info. */
+
+void
+sem_item_optimizer::fixup_points_to_sets (void)
+{
+ /* TODO: remove in GCC 9 and trigger PTA re-creation after IPA passes. */
+ cgraph_node *cnode;
+
+ FOR_EACH_DEFINED_FUNCTION (cnode)
+ {
+ tree name;
+ unsigned i;
+ function *fn = DECL_STRUCT_FUNCTION (cnode->decl);
+ if (!gimple_in_ssa_p (fn))
+ continue;
+
+ FOR_EACH_SSA_NAME (i, name, fn)
+ if (POINTER_TYPE_P (TREE_TYPE (name))
+ && SSA_NAME_PTR_INFO (name))
+ fixup_pt_set (&SSA_NAME_PTR_INFO (name)->pt);
+ fixup_pt_set (&fn->gimple_df->escaped);
+
+ /* The above get's us to 99% I guess, at least catching the
+ address compares. Below also gets us aliasing correct
+ but as said we're giving leeway to the situation with
+ readonly vars anyway, so ... */
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, fn)
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gcall *call = dyn_cast<gcall *> (gsi_stmt (gsi));
+ if (call)
+ {
+ fixup_pt_set (gimple_call_use_set (call));
+ fixup_pt_set (gimple_call_clobber_set (call));
+ }
+ }
+ }
+
+ unsigned i;
+ symtab_pair *item;
+ FOR_EACH_VEC_ELT (m_merged_variables, i, item)
+ set_alias_uids (item->first, DECL_UID (item->first->decl));
+}
+
/* Dump function prints all class members to a FILE with an INDENT. */
void
FPUTS_SPACES (file, indent + 2, "");
for (unsigned i = 0; i < members.length (); i++)
- fprintf (file, "%s(%p/%u) ", members[i]->node->asm_name (),
- (void *) members[i]->decl,
- members[i]->node->order);
+ fprintf (file, "%s ", members[i]->node->dump_asm_name ());
fprintf (file, "\n");
}