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

Reply via email to