Add support for discarding unused virtual functions.
* search.c (dfs_search, binfo_for_vtable, dfs_bfv_helper): New fns. * decl2.c (output_vtable_inherit): Call binfo_for_vtable. * lang-options.h: Add -fvtable-gc. * cp-tree.h: Add flag_vtable_gc. * decl2.c (output_vtable_inherit): New fn. (finish_vtable_vardecl): Call it. * class.c (build_vtable_entry_ref): New fn. (build_vtbl_ref): Call it. From-SVN: r22061
This commit is contained in:
parent
079e1098ab
commit
a1dd0d36f4
6 changed files with 150 additions and 1 deletions
|
@ -1,3 +1,18 @@
|
|||
1998-08-28 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* search.c (dfs_search, binfo_for_vtable, dfs_bfv_helper): New fns.
|
||||
* decl2.c (output_vtable_inherit): Call binfo_for_vtable.
|
||||
|
||||
1998-08-28 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
Add support for discarding unused virtual functions.
|
||||
* lang-options.h: Add -fvtable-gc.
|
||||
* cp-tree.h: Add flag_vtable_gc.
|
||||
* decl2.c (output_vtable_inherit): New fn.
|
||||
(finish_vtable_vardecl): Call it.
|
||||
* class.c (build_vtable_entry_ref): New fn.
|
||||
(build_vtbl_ref): Call it.
|
||||
|
||||
1998-08-28 Mark Mitchell <mark@markmitchell.com>
|
||||
|
||||
* cp-tree.h (build_enumerator): Take the enumeration type as a
|
||||
|
|
|
@ -429,6 +429,36 @@ build_vtable_entry (delta, pfn)
|
|||
}
|
||||
}
|
||||
|
||||
/* We want to give the assembler the vtable identifier as well as
|
||||
the offset to the function pointer. So we generate
|
||||
|
||||
__asm__ __volatile__ (".vtable_entry %0, %1"
|
||||
: : "s"(&class_vtable),
|
||||
"i"((long)&vtbl[idx].pfn - (long)&vtbl[0])); */
|
||||
|
||||
static void
|
||||
build_vtable_entry_ref (basetype, vtbl, idx)
|
||||
tree basetype, vtbl, idx;
|
||||
{
|
||||
static char asm_stmt[] = ".vtable_entry %0, %1";
|
||||
tree s, i, i2;
|
||||
|
||||
s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0);
|
||||
s = build_tree_list (build_string (1, "s"), s);
|
||||
|
||||
i = build_array_ref (vtbl, idx);
|
||||
if (!flag_vtable_thunks)
|
||||
i = build_component_ref (i, pfn_identifier, vtable_entry_type, 0);
|
||||
i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0));
|
||||
i2 = build_array_ref (vtbl, build_int_2(0,0));
|
||||
i2 = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i2, 0));
|
||||
i = build_binary_op (MINUS_EXPR, i, i2, 0);
|
||||
i = build_tree_list (build_string (1, "i"), i);
|
||||
|
||||
expand_asm_operands (build_string (sizeof(asm_stmt)-1, asm_stmt),
|
||||
NULL_TREE, chainon (s, i), NULL_TREE, 1, NULL, 0);
|
||||
}
|
||||
|
||||
/* Given an object INSTANCE, return an expression which yields the
|
||||
virtual function vtable element corresponding to INDEX. There are
|
||||
many special cases for INSTANCE which we take care of here, mainly
|
||||
|
@ -489,7 +519,12 @@ build_vtbl_ref (instance, idx)
|
|||
vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
|
||||
NULL_PTR);
|
||||
}
|
||||
|
||||
assemble_external (vtbl);
|
||||
|
||||
if (flag_vtable_gc)
|
||||
build_vtable_entry_ref (basetype, vtbl, idx);
|
||||
|
||||
aref = build_array_ref (vtbl, idx);
|
||||
|
||||
return aref;
|
||||
|
|
|
@ -476,6 +476,9 @@ extern int flag_do_squangling;
|
|||
/* Nonzero if we want to issue diagnostics that the standard says are not
|
||||
required. */
|
||||
extern int flag_optional_diags;
|
||||
|
||||
/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
|
||||
extern int flag_vtable_gc;
|
||||
|
||||
/* C++ language-specific tree codes. */
|
||||
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
|
||||
|
|
|
@ -454,6 +454,9 @@ int flag_guiding_decls;
|
|||
and class qualifiers. */
|
||||
int flag_do_squangling;
|
||||
|
||||
/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
|
||||
|
||||
int flag_vtable_gc;
|
||||
|
||||
/* Table of language-dependent -f options.
|
||||
STRING is the option name. VARIABLE is the address of the variable.
|
||||
|
@ -496,6 +499,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
|
|||
{"init-priority", &flag_init_priority, 1},
|
||||
{"huge-objects", &flag_huge_objects, 1},
|
||||
{"conserve-space", &flag_conserve_space, 1},
|
||||
{"vtable-gc", &flag_vtable_gc, 1},
|
||||
{"vtable-thunks", &flag_vtable_thunks, 1},
|
||||
{"access-control", &flag_access_control, 1},
|
||||
{"nonansi-builtins", &flag_no_nonansi_builtin, 0},
|
||||
|
@ -2672,7 +2676,35 @@ finish_prevtable_vardecl (prev, vars)
|
|||
import_export_vtable (vars, ctype, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* We need to describe to the assembler the relationship between
|
||||
a vtable and the vtable of the parent class. It is not
|
||||
straightforward how to get this during multiple inheritance. */
|
||||
|
||||
static void
|
||||
output_vtable_inherit (vars)
|
||||
tree vars;
|
||||
{
|
||||
tree parent;
|
||||
rtx op[2];
|
||||
|
||||
op[0] = XEXP (DECL_RTL (vars), 0); /* strip the mem ref */
|
||||
|
||||
parent = binfo_for_vtable (vars);
|
||||
|
||||
if (parent == TYPE_BINFO (DECL_CONTEXT (vars)))
|
||||
op[1] = const0_rtx;
|
||||
else if (parent)
|
||||
{
|
||||
parent = TYPE_BINFO_VTABLE (BINFO_TYPE (parent));
|
||||
op[1] = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */
|
||||
}
|
||||
else
|
||||
my_friendly_abort (980826);
|
||||
|
||||
output_asm_insn (".vtable_inherit %0, %1", op);
|
||||
}
|
||||
|
||||
static int
|
||||
finish_vtable_vardecl (prev, vars)
|
||||
tree prev, vars;
|
||||
|
@ -2716,6 +2748,10 @@ finish_vtable_vardecl (prev, vars)
|
|||
}
|
||||
|
||||
rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
|
||||
|
||||
if (flag_vtable_gc)
|
||||
output_vtable_inherit (vars);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)))
|
||||
|
|
|
@ -93,6 +93,8 @@ DEFINE_LANG_NAME ("C++")
|
|||
{ "-ftemplate-depth-", "Specify maximum template instantiation depth"},
|
||||
{ "-fthis-is-variable", "Make 'this' not be type '* const'" },
|
||||
{ "-fno-this-is-variable", "" },
|
||||
{ "-fvtable-gc", "Discard unused virtual functions" },
|
||||
{ "-fno-vtable-gc", "" },
|
||||
{ "-fvtable-thunks", "Implement vtables using thunks" },
|
||||
{ "-fno-vtable-thunks", "" },
|
||||
{ "-fweak", "Emit common-like symbols as weak symbols" },
|
||||
|
|
|
@ -2147,6 +2147,41 @@ dfs_walk (binfo, fn, qfn)
|
|||
fn (binfo);
|
||||
}
|
||||
|
||||
/* Like dfs_walk, but only walk until fn returns something, and return
|
||||
that. We also use the real vbase binfos instead of the placeholders
|
||||
in the normal binfo hierarchy. START is the most-derived type for this
|
||||
hierarchy, so that we can find the vbase binfos. */
|
||||
|
||||
static tree
|
||||
dfs_search (binfo, fn, start)
|
||||
tree binfo, start;
|
||||
tree (*fn) PROTO((tree));
|
||||
{
|
||||
tree binfos = BINFO_BASETYPES (binfo);
|
||||
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
|
||||
tree retval;
|
||||
|
||||
for (i = 0; i < n_baselinks; i++)
|
||||
{
|
||||
tree base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
|
||||
if (TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TYPE_PARM
|
||||
|| TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TEMPLATE_PARM)
|
||||
/* Pass */;
|
||||
else
|
||||
{
|
||||
if (TREE_VIA_VIRTUAL (base_binfo) && start)
|
||||
base_binfo = binfo_member (BINFO_TYPE (base_binfo),
|
||||
CLASSTYPE_VBASECLASSES (start));
|
||||
retval = dfs_search (base_binfo, fn, start);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
return fn (binfo);
|
||||
}
|
||||
|
||||
static int markedp (binfo) tree binfo;
|
||||
{ return BINFO_MARKED (binfo); }
|
||||
static int unmarkedp (binfo) tree binfo;
|
||||
|
@ -3370,3 +3405,26 @@ types_overlap_p (empty_type, next_type)
|
|||
return found_overlap;
|
||||
}
|
||||
|
||||
/* Passed to dfs_search by binfo_for_vtable; determine if bvtable comes
|
||||
from BINFO. */
|
||||
|
||||
static tree bvtable;
|
||||
static tree
|
||||
dfs_bfv_helper (binfo)
|
||||
tree binfo;
|
||||
{
|
||||
if (BINFO_VTABLE (binfo) == bvtable)
|
||||
return binfo;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Given a vtable VARS, determine which binfo it comes from. */
|
||||
|
||||
tree
|
||||
binfo_for_vtable (vars)
|
||||
tree vars;
|
||||
{
|
||||
bvtable = vars;
|
||||
return dfs_search (TYPE_BINFO (DECL_CONTEXT (vars)), dfs_bfv_helper,
|
||||
DECL_CONTEXT (vars));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue