This is a patch series that changes the way vtables are constructed in the C++ frontend (the first two are small preliminary patches, the meat will be in 3/3). The problem I was trying to solve was that on the port I was working on, function pointers are smaller than data pointers, and size_t is smaller than a data pointer too. All three kinds of types are used in vtables.
The C++ frontend assumes all three sizes are identical and constructs references to them by just multiplying an index with a (constant) size. (There is a target macro to add extra padding to the data members, but it's unsuitable for the situation I described, and in any case wastes too much space to be useful.) This patch series changes that so that along with a vtable and its initializers, we build up a list of structure fields and create a vtable type from these. We can then access the various elements by using COMPONENT_REFs without having to know exactly what the offsets are. Incidentally, libsupc++ already uses a "struct vtable_prefix" to describe the layout. I think this is a cleanup, but since the port won't be contributed I could understand if the C++ maintainers don't want to risk this patch set. If it doesn't go in, maybe it will be useful as a reference for others when porting to a similar target. There is one assumption here that needs to be pointed out, and one little piece of ugliness. The assumption is that on current targets, size_type_node is always the same size as const_ptr_type_node (i.e. sizeof (void *) == sizeof (size_t)), and also that they have the same alignment. This is required because the data fields of the vtable are now created using a size_type_node. If someone knows of a target where this isn't true, it would be helpful to know. Given the size_t/uintptr_t testsuite patch I just submitted I'm thinking they don't exist, but I'm kind of wondering about m32c, so Cc'ing DJ. The small ugliness is that we must allow empty arrays in the middle of structures since we must be able to take the address of such an array field to get an object's vtable pointer. GCC seems to have no problems with this concept in general, but since 4.5 (which I was working on) one little problem has crept in: we crash in varasm.c when finding such an array while initializing the vtable. This is addressed by the following small preliminary patch which essentially just restores the previous code. Bootstrapped and tested on x86_64-linux, ok? Bernd
commit 618d06f7d414842a934fb360fa98972478e13483 Author: Bernd Schmidt <ber...@codesourcery.com> Date: Tue Apr 23 15:19:07 2013 +0200 Allow empty arrays to be initialized This undoes an earlier change in output_constructor_regular_field so that we no longer crash when a zero-size array is initialized. This is in preparation for changes to the way C++ vtables are laid out. * varasm.c (output_constructor_regular_field): Don't crash for arrays with empty DECL_SIZE_UNIT. diff --git a/gcc/varasm.c b/gcc/varasm.c index 2532d80..830fdd0 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -4833,7 +4833,7 @@ output_constructor_regular_field (oc_local_state *local) better be last. */ gcc_assert (!fieldsize || !DECL_CHAIN (local->field)); } - else + else if (DECL_SIZE_UNIT (local->field)) fieldsize = tree_low_cst (DECL_SIZE_UNIT (local->field), 1); } else