Version 2 of vtable thunks bug fix (long)
Martin v. Loewis
martin@mira.isdn.cs.tu-berlin.de
Sun Apr 4 13:34:00 GMT 1999
This is the second release of the vtable thunks bug fix. It is functionally complete, with the following limitations:
- There is no backwards compatibility with the current thunk in case
of polymorphic vbases; I'm not sure whether I will provide one at in
time for egcs 1.2.
- The compiler currently emits vlists into all object files. This
should work similar to the vtable export-import business, but I
couldn't figure out how this really works.
As it is, this patch can be used on the current egcs, and shows no
regressions (tested in a slightly modified way on
i586-pc-linux-gnu). If applied as-is, it changes the compiler
behaviour only under -fnew-abi, even on Linux. An additional flag
-fv1-thunks is provided to activate the current code; to test this
patch, -fvtable-thunks -fno-v1-thunks is recommended.
ABI issues (this eventually goes into gxxint.texi): For 'polymorphic
virtual bases' (pvbases), an additional parameter __vlist is added
after the in_chrg parameter to ctors and dtors; the parameter type is
mangled as _Vlist. This parameter points to an array of vtables, which
is consumed as initialization progresses. The ctors process it in
forward direction, the dtors reverse.
For each class with pvbases, a new vlist table is emitted, mangled as
__vl.<class>. For the base classes, special vtables are emitted, which
are named __vc.<path to base>_<path from base to vfield>. This is
different from the vtable naming: it doesn't try to be smart about
omitting path items during mangling, and therefore doesn't depend on
the order in which vtables are created.
ABI questions:
1) The callers of ctors and dtors always pass 0 as the vlist; the
ctor/dtor then references the __vl variable in the if(__in_chrg)
part. Alternatively, callers could be required to pass the real
vlist pointer. Which is better?
2) If a dtor is called virtually, the caller is not guaranteed to pass
any argument in place of the __vlist. Therefore, even storing into
it is not safe. The dtor makes a local variable __vlist, and
initializes it from __vlist1 (the parameter) if not in charge, or
from the __vl variable otherwise. Is this safe on all platforms
(i.e. invoking a function taking two parameters with only one
argument, when the function then won't look at the second
parameter) ? Alternatively, a wrapper must be put into the vtable
in place of the dtor.
3) Is compatibility with the current thunks desirable? This would add
wrappers for ctors and dtors which don't take the vlist
parameter. They would always pass the __vl.class as vlist (even if
not in charge), thus offering bug-compatibility with the current
code.
Those wrappers won't work for varargs constructors, in which case
the compiler would be sorry. They will also copy all their
arguments. Fortunately, non-POD types are passed by invisible
reference, AFAIK.
If the base class is not recompiled, the base constructor taking a
vlist won't be available at link time. The compatibility code would
try to generate a weak symbol, and generate code that tests the
weak symbol, and calls the old ctor/dtor if the new one is not
available. This approach would only work with weak
symbols. Fortunately, it would work on Linux/ELF, where it would be
primarily used.
If you are still with me, I'd appreciate any comments on the
approaches taken, and the implementation developed. I won't be looking
at the code for a few days, which is why I'm releasing it now (release
early, release often :-) Anybody interested in the backward
compatibility: Please go ahead.
Regards,
Martin
1999-04-03 Martin von Löwis <loewis@informatik.hu-berlin.de>
* class.c (prepare_ctor_vtable, finish_one_ctor_vtable,
prepend_ctor_vfields_for_vbase, finish_ctor_vtables_for_vbases,
finish_ctor_vtables_1, prepend_vbase_vfields,
finish_ctor_vtables): New functions.
(finish_struct_1): Call finish_ctor_vtables.
* cp-tree.h (flag_v1_thunks): Declare.
(TYPE_USES_PVBASES): New macro.
(constructor_for_vbase_attr): Widen to two bits.
(CONSTRUCTOR_FOR_VBASE, CONSTRUCTOR_FOR_PVBASE,
DESTRUCTOR_FOR_PVBASE): New macros.
(DECL_CONSTRUCTOR_FOR_VBASE_P): Adopt to new enumeration.
(DECL_CONSTRUCTOR_FOR_VBASE): New macro.
(DECL_CONSTRUCTOR_FOR_PVBASE_P, DECL_DESTRUCTOR_FOR_PVBASE_P): New
macros.
(vlist_identifier, vlist_type_node, vlist_zero_node): Declare.
(VCTABLE_NAME, VLIST_NAME_FORMAT, VLIST_NAME, VLIST1_NAME,
VLIST_TYPE_NAME): New macros.
(LOOKUP_HAS_VLIST): New macro.
(build_base_dtor_call, init_vlist): Declare.
(build_destructor_name): Add int argument.
* decl.c (vlist_identifier, vlist_type_node, vlist_zero_node):
Define.
(init_decl_processing): Initialize them.
(grokdeclarator): Handle vlist argument.
(copy_args_p): Likewise.
(grok_ctor_properties): Don't try to skip initial int for
templates. Skip vlist if available.
(xref_basetypes): Set TYPE_USES_PVBASES.
(finish_dtor, finish_ctor): New functions, moved out of ...
(finish_function): ... here.
* decl2.c (flag_v1_thunks): Define.
(lang_f_options): Add v1-thunks.
(lang_decode_option): Reset flag_v1_thunks for new-abi.
(maybe_retrofit_in_chrg): Retrofit __vlist parameter.
(grokclassfn): Pass pvbase flag into mangled name.
* init.c (build_base_dtor_call): New function.
(build_partial_cleanup_for): Call it.
(pvbasecount, init_vlist, ): New functions.
(emit_base_init): Process vlist argument.
(expand_aggr_vbase_init_1): Likewise.
(expand_aggr_vbase_init): Likewise.
(expand_default_init): Likewise.
(build_new_1): Pass null vlist argument.
(build_delete): Likewise. Call build_base_dtor_call.
* lang-options.h: New flag v1-thunks.
* method.c (process_overload_item): Mangle _Vlist specially.
(build_base_path, get_vlist_vtable_id): New functions.
(build_destructor_name): Potentially mangle _Vlist into it.
(do_build_copy_constructor): Skip vlist argument.
(synthesize_method): Likewise.
* pt.c (has_pvbases_p): New function.
(instantiate_class_template): Call it.
(tsubst_decl): Retrofit before mangling. Pass pvbase_p to
destructor mangling.
* search.c (expand_direct_vtbls_init_thunks): New function.
(expand_indirect_vtbls_init_thunks): New function.
(expand_indirect_vtbls_init): Call it.
* call.c (add_function_candidate): Process vlist argument.
(build_user_type_conversion_1): Add vlist argument.
(convert_like): Likewise.
(build_over_call): Likewise.
(build_new_method_call): Likewise.
More information about the Gcc-patches
mailing list