Performance:
    + create a small test library
    + find some genuinely weak / duplicate symbols in OO.o ...
    + add annotation etc. to that
    + checkout vtable instantation etc.


We are still doing too much work with symbol lookup
    + most of it highly avoidable.

    + ~95% is relocation processing ...
	+ fn relocations ...
    + populating vtable:
	+ looking up global / weak symbols [ why ? ]
	+ [ can they not be -Bsymbolic or something ? ]
	+ if 'dllexport' or the visibility attribute are 
	  used - we should/could hide local vtable
	  lookup bits ?
	+ we want the symbols to be 'protected' so they
	  are exported - by are resolved internally to
	  symbol-freea relocations
	+ The whole thing is crazy:
	    + we need only 1 'get-vtable' method per class ...
	+ Mark all 'virtual' methods of (SPECIFIED && DEFAULT)
	  linkage as 'protected' - ditto for generated thunks (?)
    + Understand the weak symbol issue [!?]
	+ add a throw/catch ...
	  fprintf (file, " %c%c%c%c%c%c%c",
	    ((type & BSF_LOCAL)
	    ? (type & BSF_GLOBAL) ? '!' : 'l'
	    : (type & BSF_GLOBAL) ? 'g' : ' '),
	   (type & BSF_WEAK) ? 'w' : ' ',
	   (type & BSF_CONSTRUCTOR) ? 'C' : ' ',
	   (type & BSF_WARNING) ? 'W' : ' ',
	   (type & BSF_INDIRECT) ? 'I' : ' ',
	   (type & BSF_DEBUGGING) ? 'd' : (type & BSF_DYNAMIC) ? 'D' : ' ',
	   ((type & BSF_FUNCTION)
	    ? 'F'
	    : ((type & BSF_FILE)
	       ? 'f'
	       : ((type & BSF_OBJECT) ? 'O' : ' '))));
	+ Weak symbols generated by:
	    + Templates ...
	    + Reference<Foo> type stuff ...
	    	    + non-virtual thunks
		    + type info (_ZTI)
		    + vtables (_ZTV)

    + [all to do with typeinfo behavior]
	+ re-read: http://www.nedprod.com/programs/gccvisibility.html
	  very carefully ...
    + Can we annotate the source with 'protected' for most methods ?

    + parent chaining ?
	+ doesn't go via vtable - but direct fn. call ...

    + Looks like we do all those bindings (relocs?)
	+ at dlopen time [!?] [ 10k relocations building vtables ? ]

    + need to check vs. gcc-4.x ...
	[ should be able to prune ... ]

Thoughts: (problem/soln/problem/...)
    + the deep / vcl OutputDevice -> Window -> Control -> ...
      vtable building issue is bad, bad news.
	+ why can't we get/copy the parent's vtable
	  with 'memcpy' ? instead of lots of lookups ?
    + can we parallelise the linker ?
	+ this problem is easily partitionable, surely ...
	    + [ no thread support in the linker ... ]

    + a 'thunk' fn does:
	+ adjust 'this' pointer & call method [ and MI feature ]

+ Things to check:
	+ anonymous namespaces ... - file path mangled in ?



** Parent / Copy VTables ... **
    + Use: options to dump tree data to aid debugging.

	-fdump-class-hierarchy[-N]
    + With this we get:
	cp/class.c (dump_vtable):

eg.

Vtable for SubClass
SubClass::_ZTV8SubClass: 9u entries
0     (int (*)(...))0
4     (int (*)(...))(& _ZTI8SubClass)
8     SubClass::doFoo
12    BaseClass::count
16    BaseClass::operator[]
20    SubClass::doAnother
24    (int (*)(...))-0x000000008
28    (int (*)(...))(& _ZTI8SubClass)
32    SubClass::_ZThn8_N8SubClass9doAnotherEi

Called from:
    + cp/class.c (initialize_vtable)
	+ We need to identify simple cases somewhere
	  here & eliminate sillies.

/* Make BINFO's vtable have N entries, including RTTI entries,
   vbase and vcall offsets, etc.  Set its type and call the backend
   to lay it out.  */

static void
layout_vtable_decl (tree binfo, int n)

/* Virtual function table initialization.  */

/* Create all the necessary vtables for T and its base classes.  */

static void
finish_vtbls (tree t)

Calls:

/* Initialize the vtable for BINFO with the INITS.  */

static void
initialize_vtable (tree binfo, tree inits)

* It seems initializer ordering is unpredictable:

works:

extern ParamFoo aBaa;
ParamFoo aBaa;
StaticInit aStatic(aBaa);

doesn't work:

extern ParamFoo aBaa;
StaticInit aStatic(aBaa);
ParamFoo aBaa;

* Initialization etc. bits:

http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gccint/Initialization.html

.ctors section.
    + find something that puts code in
      the .ctors section (?)

Emit a fn. that will do the construction (?)
    + make it a .ctor (?)


*/

static void
finish_vtbls (tree t)

Calls:

/* Initialize the vtable for BINFO with the INITS.  */

static void
initialize_vtable (tree binfo, tree inits)

* It seems initializer ordering is unpredictable:

works:

extern ParamFoo aBaa;
ParamFoo aBaa;
StaticInit aStatic(aBaa);

doesn't work:

extern ParamFoo aBaa;
StaticInit aStatic(aBaa);
ParamFoo aBaa;

* Initialization etc. bits:

http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gccint/Initialization.html

.ctors section.
    + find something that puts code in
      the .ctors section (?)

Emit a fn. that will do the construction (?)


* Avoid duplicate VTable construction:

    + need to hook the vague linkage constructs:

http://m68hc11.serveftp.org/doc/gcc_6.html

    + but for methods [ ie. same as 'inline' methods ?! ;-]


+ 1st step:
    + get gcc to emit a constructor call to
      a custom fn ...

+ 2nd step
    + generate bit-masks &
      impl. that function to do a copy

+ 3rd step
    + generate that fn. internally



** Ordering:
    + absolutely critical ...
	+ to make it efficient:
	    + have to copy from direct parents only
		=> have to ensure the parent is initialized
		   (copied) itself first ...
	    + have to copy only once
    + Linker support ...

** Assumption:
    + it will ~always be more compact and
      efficient to do vtable copies ourself
      (in shared libraries)
	    + we can make this dependent on -fPIC ...

** Minimality
    + is it possible to do the ordering without
      binutils support ?
	+ we could call a 'weak'
	  parent 'copyVTable' method (if present)
	+ each constructor:
	    + initVTable<Name>
	    + emit a constructor call to that
		+ let initialization sort it out (?)
		+ [ would that break stuff ?]
	    + how bad would that be ?
		+ can we add support to elide
		  duplicate constructors in binutils ?

    + could we do (idle) vtable construction on 1st
      class instance use ?
	+ might be somewhat bloating & evil.
	+ OTOH currently ~valid - since no parent
	  use without foo ?

    + With binutils support:
	+ can call a minimal number of fn's ...
	    + but more difficult (?) ...
	+ the 'sort' is easy
	    + need code walk-through;
		+ where are vtables emitted (by the backend) [!?]
	+ can be made more succinct
	    + can be made .rodata (?)
		+ then needs glibc support [?]
		    + [ for symbol lookup ? ]

** Questions:
    + what forms of symbol / invocation ellision can we use ?

    + I -like- the idea of an 'initVTable' method
      being called (with ~weak stuff?)
	+ isolates the fix in g++ itself, with no
	  binutils/glibc pain.

    + in gcc: where is the vtable building code ?
	+ class.c: initialize_vtable
	    + [ initialize_artificial_var (...)
	+ class.c: (build_vtbl_initializer)
	    + sets up BINFO_VTABLE -
	      (an expression that points at an
	      offset into the vtable ].
	+ class.c (

    + in gcc: where is the vtable emission code ?
	+ 


    + helpful blurb:

   Define accessor macros for information about type inheritance
   and basetypes.

   A "basetype" means a particular usage of a data type for inheritance
   in another type.  Each such basetype usage has its own "binfo"
   object to describe it.  The binfo object is a TREE_VEC node.

   Inheritance is represented by the binfo nodes allocated for a
   given type.  For example, given types C and D, such that D is
   inherited by C, 3 binfo nodes will be allocated: one for describing
   the binfo properties of C, similarly one for D, and one for
   describing the binfo properties of D as a base type for C.
   Thus, given a pointer to class C, one can get a pointer to the binfo
   of D acting as a basetype for C by looking at C's binfo's basetypes.  */



* Considerations:
    + Information
    + Representaiton
    + Data sharing
    + Space efficiency

M-x set-variable\ntab-width 8



<micha> What I implemented until then was just some dumping routines
in the frontend to see how and where it put together the member method
decls, and if it were a overrider, or something inherited.  Then I
thought about it, and thought the whole complicateness is not needed
anymore anyway, then we spoke about it, then I thought again that it's
needed, but never returned to do something on it.  But the patch for
getting a feel in cp/class.c is somewhere

<micha> ...
<micha> ~matz/copy-vtable/diff

<micha> What's left is a multitude of stuff: 1) remembering in
lists-per-class, where the overriders were, 2) emitting a decl for
that list, which could be interpreted at runtime, 3) writing the
runtime support to interpret all these lists, 4) make ld.so call that
runtime support before everything else (also before other static
ctors)

* So
    + we can (I think correctly) identify the slots we want to copy

* Next:
    + generating a new section:
	+ read the constructor code ...

+ decl2.c - remember ? - RTL generation etc. ? :-)

./gcc/cp/decl2.c:#define SSDF_IDENTIFIER "__static_initialization_and_destruction"
./gcc/cp/decl2.c:  char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
./gcc/cp/decl2.c:     SSDF_IDENTIFIER_<number>.  */
./gcc/cp/decl2.c:  sprintf (id, "%s_%u", SSDF_IDENTIFIER, count);

./gcc/cp/cp-tree.h:extern GTY(()) tree static_aggregates;



    static_aggregates = tree_cons (init, decl, static_aggregates);

  while (*var)
    {
      tree t = *var;
      tree decl = TREE_VALUE (t);
      tree init = TREE_PURPOSE (t);

      *var = TREE_CHAIN (t);
      TREE_CHAIN (t) = result;
    }


** We need an intermediate representation (!?)
    + trees of what ?
	+ 2 tree pairs ?
	+ source & dest ?
	    + source == ptr to vtable + offset ...
		+ [ can we make an offset expression ? - perhaps ... ]
	    + dest == ptr to vtable + offset ...

	+ can we use DECL_VINDEX instead ?
	    [ then we have it all ]
	    + just store the fn ptr ?
		+ do we duplicate the fn. decls
		  per vtable ?

    + Then sort/crunch these on output ...
	+ 

    + cp_finish_decl builds 'static_aggregates'

+ Question:
    + is there a different fn. decl per vtable slot
      assignment ? - with a different DECL_VINDEX ?
	+ since we assign DECL_VINDEX on a BV_FN(fn):
	    + it must be ...
      for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t));
	{
	  tree fndecl = BV_FN (fn);
	  ...
	    DECL_VINDEX (fndecl) = build_int_cst (NULL_TREE, vindex);
	}

        + in vtbl_initialize - 'fn' - is the BV_FN ...

    + Is there already a list of vtables we can
      come back to & operate on later (at emission time ?)
	... 
	+ why not build one ? & operate on it later ?
	+ First build simple list:
	    + then re-consider: can we post-generate this ?

    + can we just sort binutils to ensure that no source
      address is read before a dest is written (?)
	+ then sort read/writes etc.


** Global vars etc. & sorting

+ interestingly a compile emits:

.globl __gxx_personality_v0


Foo aGlobal;
Baa aBaa;

compiles to:

	.type	_Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:

	.text
	.align 2
	.type	_Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB9:
	pushl	%ebp
.LCFI14:
	movl	%esp, %ebp
.LCFI15:
	subl	$24, %esp
.LCFI16:
	movl	%eax, -4(%ebp)
	movl	%edx, -8(%ebp)
	cmpl	$1, -4(%ebp)
	jne	.L13
	cmpl	$65535, -8(%ebp)
	jne	.L13
	movl	$aGlobal, (%esp)
	call	_ZN3FooC1Ev
	movl	$aBaa, (%esp)
	call	_ZN3BaaC1Ev
.L13:
	leave
	ret
.LFE9:
	.size	_Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
	.align 2
	.type	_GLOBAL__I_aGlobal, @function
_GLOBAL__I_aGlobal:
.LFB10:
	pushl	%ebp
.LCFI17:
	movl	%esp, %ebp
.LCFI18:
	subl	$8, %esp
.LCFI19:
	movl	$65535, %edx
	movl	$1, %eax
	call	_Z41__static_initialization_and_destruction_0ii
	leave
	ret
.LFE10:
	.size	_GLOBAL__I_aGlobal, .-_GLOBAL__I_aGlobal


binutils/ld/ldctor.c (ctor_prio):
    + gets the priority of a g++ global constructor
      (or destructor) from the symbol name
        + [ gets an integer prio. from the symbol name ]
    + these functions are sorted (somehow)
    + ldctor_build_sets:
	+ this is what builds the constructor_list ...
	    + [ linker script 'CONSTRUCTORS' command (?) ]

    + FIXME: what good are linker scripts ?
	+ what function do they serve ?

binutils:
http://www.gnu.org/software/binutils/manual/ld-2.9.1/html_chapter/ld_3.html

gcc/collect2.c:
/* Collect static initialization info into data structures that can be
   traversed by C++ initialization and finalization routines. */
    + Interesting [!]


** Generate at least some data out ... &
   a _GLOBAL_<foo> thing ...


* Debugging:
eg. gdb /data/opt/gcc/bin/../libexec/gcc/i686-pc-linux-gnu/4.1.0/cc1plus


* COMDAT linkage
    /* With weak symbols, we simply make the variable COMDAT;
       that will cause copies in multiple translations units to
       be merged.  */
    comdat_linkage (decl);
    + Question: is this an overlaying merge or can it
      be more complex ? [ appending eg. ]

* Assertion failed:

4079      if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
4080        {
4081          /* An automatic variable with an incomplete type: that is an error.
4082             Don't talk about array types here, since we took care of that
4083             message in grokdeclarator.  */
4084          error ("storage size of %qD isn't known", decl);


** We initialize the artificial var
    + but ... how is it output ?

** Have we got the initialization for this thing right ?!


** TODO:
    + emit a '_GLOBAL_...?' fixup function - with
      a 'magic' priority ? so it gets sorted
      first-of-all (!?)
    + terminate the copy constructor foo ...
    + run a simple test with a single constructor ?
    + create a .ctors section ?


** binutils/ld/ldctor.c:
    + ldctor_add_set_entry is called a lot ...
    + can we trigger the binutils feature on the
      presence of compiler emitted 'magic'
      symbols ? [ fun ... ] (nicer for sure !)


    + Can we re-arrange the sections ?
	+ or is this information lost by this time ?
	+ can we extract & move stuff ?
	+ what is possible at link time ?

crtbegin.c:
/* Specialized bits of code needed to support construction and
   destruction of file-scope objects in C++ code.
   Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998,
   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
   Contributed by Ron Guilmette (rfg@monkeys.com).

** Wow - gcc/crtstuff.c
    + looks like an ideal place to put this stuff ...

eg.:

STATIC func_ptr __CTOR_END__[1]
  __attribute__((section(".ctors"), aligned(sizeof(func_ptr))))
  = { (func_ptr) 0 };


** Generating our own section:
    + gcc/except.c (default_exception_section)
    + named_section_flags (".gcc_except_table", flags);
    + -> TARGET_ASM_EXCEPTION_SECTION
	-> target-def.h (

We get std. decls into other sections (somehow) with:
surely ?
TARGET_ASM_CONSTRUCTOR,			\
TARGET_ASM_DESTRUCTOR,                  \

gcc/c-decl.c:
    c_expand_body ...


varasm.c: hmm ...

/* Switch to section for variable DECL.  RELOC is the same as the
   argument to SELECT_SECTION.  */

void
variable_section (tree decl, int reloc)
{
  if (IN_NAMED_SECTION (decl))
    named_section (decl, NULL, reloc);
  else
    targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));


elflink.c:
     + check elf_gc_propagate_vtable_entries_used
also + elf_gc_smash_unused_vtentry_relocs

Can we hook into:
    bfd_boolean
    bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
    

/* Called from check_relocs to record the existence of a VTINHERIT reloc.  */

.vtable_inherit & .vtable_entry - pseudo-ops from old 'gas'
http://sources.redhat.com/ml/binutils/2001-02/msg00485.html

gas/config/obj-elf.c:
  /* These are GNU extensions to aid in garbage collecting C++ vtables.  */
  {"vtable_inherit", (void (*) (int)) &obj_elf_vtable_inherit, 0},
  {"vtable_entry", (void (*) (int)) &obj_elf_vtable_entry, 0},

* Interesting ! :-) *
    + [ ... neato ...]

* To understand the linker:

  read binutils/include/bfdlink.h

<micha> You just have to make sure, that it's called before static ctors.  So either before __do_global_ctors, or before the call to frame_dummy (which in turn calls __register_frame_info).
<micha> So it's perhaps enough if you put that call to fixup_inheritance (or the like) in crtstuff.c right before here:
<micha> #ifdef INIT_SECTION_ASM_OP
<micha> CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, frame_dummy)
<micha> #else /* defined(INIT_SECTION_ASM_OP) */
<micha> static func_ptr __frame_dummy_init_array_entry[]
<micha>   __attribute__ ((__unused__, section(".init_array")))
<micha>   = { frame_dummy };
<micha> #endif /* !defined(INIT_SECTION_ASM_OP) */
<micha> #endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
<micha> Perhaps outside the USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME ifdef
<michael_> hokay :-)

Looking at:
    + ld/eelf_i386.c ... (interesting)
          assigns: ld_elf_i386_emulation =
	    -> ldemul-list.h EMULATION_LIST
    

/* Do the final step of an ELF link.  */

bfd_boolean
bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)

binutils overview:
    + ldmain.c:469
	+ yyparse (); [ on linker script ]

Most of the action is here:
	+ lang_process [ldlang.c]
	    + open_input_bfds:
		+ load_symbols [ end ]
		    + ... ->
elflink.c		+ "bfd_elf_link_add_symbols"
			    ** hack here ! **
	    + ldemul_after_open
	    + ldctor_build_sets [ .ctor handling ? ]
	    + ldemul_before_allocation
		+ by this stage we -know- all the sizes
		    + including relocation count etc. ? [!]

 -> ldwrite.c:577