This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Version 2 of vtable thunks bug fix (long)


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.

diff.gz


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]