Hello all,
I am currently working on an ARM embedded project with very significant size
constraints. When disassembling an executable I noticed a non-insignificant
amount of space is wasted by vtables.
I am currently cross compiling with arm-none-eabi-g++ version 14.2.0 and using
the following flags (among others): -fno-exceptions -fno-rtti.
This is a random vtable i got from a .class file:
Vtable for std::bad_alloc
std::bad_alloc::_ZTVSt9bad_alloc: 5 entries
0 (int (*)(...))0
4 (int (*)(...))0
8 (int (*)(...))std::bad_alloc::~bad_alloc
12 (int (*)(...))std::bad_alloc::~bad_alloc
16 (int (*)(...))std::bad_alloc::wha
Even though RTTI is disabled, and therefore dynamic_cast is disabled, the vtable
still has both a pointer to base and a pointer to typeinfo. Even though
they are both null.
As far as I understand it both the pointer to base and typeinfo are necessary
to enable dynamic_cast, since this is disabled it should be possible to get rid
of these two pointers? Am I correct?
Even so the typeinfo pointer is completely redundant.
Getting rid of these two entries in all vtables would be very good, as doing so
would lead to about a ~1.5% code size decrease in my 64k project.
I have tried to make a quick and dirty patch by modifying the following
in class.cc:
static void
build_rtti_vtbl_entries(tree binfo, vtbl_init_data *vid)
{
tree b;
tree t;
tree offset;
tree decl;
tree init;
t = BINFO_TYPE(vid->rtti_binfo);
/* To find the complete object, we will first convert to our most
primary base, and then add the offset in the vtbl to that value. */
b = most_primary_binfo(binfo);
offset = size_diffop_loc(input_location,
BINFO_OFFSET(vid->rtti_binfo), BINFO_OFFSET(b));
/* The second entry is the address of the typeinfo object. */
/* MODIFIED - only add the entry if rtti is enabled */
if (flag_rtti)
{
decl = build_address(get_tinfo_decl(t));
/* Convert the declaration to a type that can be stored in the
vtable. */
init = build_nop(vfunc_ptr_type_node, decl);
CONSTRUCTOR_APPEND_ELT(vid->inits, NULL_TREE, init);
}
/* Add the offset-to-top entry. It comes earlier in the vtable than
the typeinfo entry. Convert the offset to look like a
function pointer, so that we can put it in the vtable. */
init = build_nop(vfunc_ptr_type_node, offset);
CONSTRUCTOR_APPEND_ELT(vid->inits, NULL_TREE, init);
}
i have also modified vid.index in build_vtbl_initializer
vid.index = ssize_int(flag_rtti ? -3 : -2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
This seems to work and gcc compiles. Although I have not tested the code it
generates yet. One problem is that it breaks the build for libsupc++, as it uses
typeid. Is there a way to build libsupc++ with -fno-rtti?
Otherwise is it possible to build libstdc++ without libsupc++?
Finally my goal would be to remove the offset-to-top entry. Just
commenting it out
in build_rtti_vtbl_entries breaks quite a few things during runtime as
vid->inits
remains empty. Any pointers for any other modifications I should make?
Finally, would it be possible to implement this in a plugin rather than
modifying GCC itself?
Thank you all in advance,
Luigi Sciolla