C++ ABI Summary
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

C++ ABI Summary



Attached are updates to the issue pages, along with a new one
provided by Sun describing their RTTI/dynamic cast algorithm.
(I haven't just incorporated the latter because of Sun's patent
filing.  Sun should indicate whether they will allow use of their
patent in this ABI -- if not, I presume we'll avoid it.)

Issues B-1 and B-6 remain very much open, and I expect the main
topic of discussion.  Please think over last week's discussion
(which I mentioned only sketchily) and be prepared to talk about
this this week.  If Daveed can get something out on A-6/B-8,
that would be the next priority.  If either Priti or Christophe
can provide an exception model description (PLEASE...), we can
move into those issues.

I am on a jury, and won't be there Thursday (barring a plea
bargain or some such), but Shin will host the meeting.  (I'm
hoping to be done by the next meeting.)

Also, remember that the phone number will change, not this week,
but the next one.  See the summary page.
<HTML>

<HEAD>
<title>C++ ABI Summary</title>

<link rel=stylesheet href=small-table.css type="text/css">

<hr>

<font size=6><i><b>
<p>
C++ ABI Summary
</b></i></font>

<p>
<i>Revised 17 August 1999</i>

</center>

</HEAD>

<BODY>

<p>
<h4>Links</h4>

<ul>
<li> Full <a href=cxx-open.html>open</a> issues list.
<li> Full <a href=cxx-closed.html>closed</a> issues list.
<li> Draft <a href=abi-layout.html>data layout</a> specification.
</ul>

<p>
<hr>

<p>
<h4>Meetings</h4>

<p>
<table align=center border=on cellpadding=3>

<tr class=small>
<th colspan=2> When </th>
<th> Where </th>
<th> Phone </th>
</tr>

<tr class=small>
<td> 12 August </td> <td> 10:00-12:00 PDT </td>
<td align=left colspan=2> completed </td>
</tr>

<tr class=small>
<td> 19 August </td>
<td> 10:00-12:00 PDT </td>
<td> SGI Sapphire 20L </td>
<td> 650-933-7976 </td>
</tr>

<tr class=small>
<td> 26 August </td>
<td> 10:00-12:00 PDT </td>
<td> SGI Sapphire 20L </td>
<td> 650-933-7952 </td>
</tr>

<tr class=small>
<td> 2 September </td>
<td> 10:00-12:00 PDT </td>
<td> SGI Sapphire 20L </td>
<td> 650-933-7952 </td>
</tr>

<tr class=small>
<td> 9 September </td>
<td> 10:00-12:00 PDT </td>
<td> SGI Sapphire 20L </td>
<td> 650-933-7952 </td>
</tr>

<tr class=small>
<td> 16 September </td>
<td> 10:00-12:00 PDT </td>
<td> SGI Sapphire 20L </td>
<td> 650-933-7952 </td>
</tr>

<tr class=small>
<td> 23 September </td>
<td> 10:00-12:00 PDT </td>
<td> SGI Sapphire 20L </td>
<td> 650-933-7952 </td>
</tr>

<tr class=small>
<td> 30 September </td>
<td> 10:00-12:00 PDT </td>
<td> SGI Sapphire 20L </td>
<td> 650-933-7952 </td>
</tr>

<tr class=small>
<td> 7 October </td>
<td> 10:00-12:00 PDT </td>
<td> SGI Sapphire 20L </td>
<td> 650-933-7952 </td>
</tr>

<tr class=small>
<td> 14 October </td>
<td> 10:00-12:00 PDT </td>
<td> SGI Sapphire 20L </td>
<td> 650-933-7952 </td>
</tr>

<tr class=small>
<td> 21 October </td>
<td> 10:00-12:00 PDT </td>
<td> SGI ??? </td>
<td> 650-933-7952 </td>
</tr>

<tr class=small>
<td> 28 October </td>
<td> 10:00-12:00 PDT </td>
<td> SGI ??? </td>
<td> 650-933-7952 </td>
</tr>

</table>

<p>
Note:  When calling the SGI telephone bridges,
the first caller continues to ring until the second party joins.
To get rid of it, you can call from a second phone,
and hang it up once someone else calls.

<p>
<hr>

<p>
<h4>Participants</h4>

<p>
<table border=on cellpadding=3>

<tr class=small>
<th> Company </th>
<th> Name </th>
<th> Telephone </th>
<th> Fax </th>
<th> Email </th>
</tr>

<tr class=tiny>
<th rowspan=1> </th>
<td colspan=3> overall reflector </td>
<td> <a href=mailto:cxx-abi@xxxxxxxxxxxxxxxxxxxx>cxx-abi@xxxxxxxxxxxx</a> </td>
</tr>

<tr class=tiny>
<th rowspan=6> SGI </th>
<td> Jim Dehnert </td>
<td> (650) 933-4272 </td>
<td> (650) 932-4272 </td>
<td> <a href=mailto:dehnert@xxxxxxx> dehnert@xxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Matt Austern </td>
<td> (650) 933-4196 </td>
<td> (650) 932-4196 </td>
<td> <a href=mailto:austern@xxxxxxxxxxxx> austern@xxxxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Hans Boehm </td>
<td> (650) 933-7144 </td>
<td> (650) 932-7144 </td>
<td> <a href=mailto:boehm@xxxxxxxxxxxx> boehm@xxxxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Shin-Ming Liu </td>
<td> (650) 933-4287 </td>
<td> (650) 932-4287 </td>
<td> <a href=mailto:shin@xxxxxxxxxxxx> shin@xxxxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> John Wilkinson </td>
<td> (650) 933-4298 </td>
<td> (650) 932-4298 </td>
<td> <a href=mailto:jfw@xxxxxxxxxxxx> jfw@xxxxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td colspan=3> reflector </td>
<td> <a href=mailto:cxx-abi-sgi@xxxxxxxxxxxx>
cxx-abi-sgi@xxxxxxxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=1> CodeSourcery </th>
<td> Mark Mitchell </td>
<td> (650) 365-3064 </td>
<td> (650) 375-7694 </td>
<td> <a href=mailto:mark@xxxxxxxxxxxxxxxx> mark@xxxxxxxxxxxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=4> Cygnus </th>
<td> Jason Merrill </td>
<td> (408) 542-9665 </td>
<td> (408) 542-9765 </td>
<td> <a href=mailto:jason@xxxxxxxxxx> jason@xxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Ian Carmichael </td>
<td> (416) 482-3946 </td>
<td> (416) 482-6299 </td>
<td> <a href=mailto:iancarm@xxxxxxxxxx> iancarm@xxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Ulrich Drepper </td>
<td> (408) 765-4699 </td>
<td> ? </td>
<td> <a href=mailto:drepper@xxxxxxxxxx> drepper@xxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td colspan=3> reflector </td>
<td> <a href=mailto:c++abi@xxxxxxxxxx> c++abi@xxxxxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=1> EDG </th>
<td> Daveed Vandevoorde </td>
<td> (650) 592-5768 </td>
<td> (650) 592-5781 </td>
<td> <a href=mailto:daveed@xxxxxxx> daveed@xxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=1> EPC </th>
<td> Colin McPhail </td>
<td> +44 (131) 225-6262 </td>
<td> +44 (131) 225-6644 </td>
<td> <a href=mailto:colin@xxxxxxxxx> colin@xxxxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=4> Hewlett- Packard </th>
<td> Cary Coutant </td>
<td> (408) 447-5759 </td>
<td> (408) 447-4244 </td>
<td> <a href=mailto:cary@xxxxxxxxxx> cary@xxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Christophe de Dinechin </td>
<td> (408) 447-5491 </td>
<td> (408) 447-4244 </td>
<td> <a href=mailto:ddd@xxxxxxxxxx> ddd@xxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Sassan Hazeghi </td>
<td> (408) 447-5007 </td>
<td> (408) 447-4244 </td>
<td> <a href=mailto:sassan@xxxxxxxxxx> sassan@xxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td colspan=3> reflector </td>
<td> <a href=mailto:cxx-abi-hp@xxxxxxxxxxxxxxxxxx>
cxx-abi-hp@xxxxxxxxxxxxxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=1> Humboldt- Universit&auml;t zu Berlin </th>
<td> Martin von L&ouml;wis </td>
<td> +49 30 2093 3118 </td>
<td> +49 30 2093 3112 </td>
<td> <a href=mailto:loewis@xxxxxxxxxxxxxxxxxxxxxxx> 
loewis@xxxxxxxxxxxxxxxxxxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=3> IBM </th>
<td> Mark Mendell </td>
<td> (416) 448-3485 </td>
<td> (416) 448-4414 </td>
<td> <a href=mailto:mendell@xxxxxxxxxx> mendell@xxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Allan H. Kielstra </td>
<td> (416) 448-3558 </td>
<td> (416) 448-4414 </td>
<td> <a href=mailto:kielstra@xxxxxxxxxx> kielstra@xxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td colspan=3> reflector </td>
<td> <a href=mailto:CxxABI-ADTC-CAN@xxxxxxxxxx>
CxxABI-ADTC-CAN@xxxxxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=4> Intel </th>
<td> Sunil Saxena </td>
<td> (408) 765-5272 </td>
<td> (408) 653-8511 </td>
<td> <a href=mailto:Sunil.Saxena@xxxxxxxxx> Sunil.Saxena@xxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Suresh Rao </td>
<td> (408) 765-5416 </td>
<td> (408) 765-5165 </td>
<td> <a href=mailto:Suresh.K.Rao@xxxxxxxxx>
Suresh.K.Rao@xxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Priti Shrivastav </td>
<td> (408) 765-4699 </td>
<td> (408) 765-5165 </td>
<td> <a href=mailto:Priti.Shrivastav@xxxxxxxxx>
Priti.Shrivastav@xxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td colspan=3> reflector </td>
<td> <a href=mailto:cxx-abi@xxxxxxxxxxxxxxxxxxxx>
cxx-abi@xxxxxxxxxxxxxxxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=1> SCO </th>
<td> Jonathan Schilling </td>
<td> (908) 790-2364 </td>
<td> (908) 790-2426 </td>
<td> <a href=mailto:jls@xxxxxxx> jls@xxxxxxx </a></td>
</tr>

<tr class=tiny>
<th rowspan=4> Sun </th>
<td> George Vasick </td>
<td> (650) 786-5123 </td>
<td> (650) 786-9551 </td>
<td> <a href=mailto:george.vasick@xxxxxxxxxxx>
george.vasick@xxxxxxxxxxx <a></td>
</tr>
<tr class=tiny>
<td> Michael Lam </td>
<td> (650) 786-3492 </td>
<td> (650) 786-9551 </td>
<td> <a href=mailto:michael.lam@xxxxxxxxxxx> michael.lam@xxxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Michael Ball </td>
<td> (650) 786-9109 </td>
<td> (650) 786-9551 </td>
<td> <a href=mailto:michael.ball@xxxxxxxxxxx> michael.ball@xxxxxxxxxxx </a></td>
</tr>
<tr class=tiny>
<td> Reza Monajjemi </td>
<td> (650) 786-6175 </td>
<td> ? </td>
<td> <a href=mailto:reza.monajjemi@xxxxxxxxxxx>
     reza.monajjemi@xxxxxxxxxxx </a></td>
</tr>

</table>

<p>
<hr>

<p>
<h4> Objectives </h4>

<ul>
<p>
<li>
Interoperable C++ compilation on IA-64:
we want users to be able to build relocatable objects with
different compilers and link them together,
and if possible even to ship common DSOs.
This objective implies agreement on:
    <ul>    
    <li> Data representation
    <li> Object file representation
    <li> Library API
    </ul>

<p>
<li>
ISO Standard C++:
highest priority is functionality and performance of standard-compliant code.
It should not be sacrificed for the benefit of language extensions or
legacy implementations (though considering them as tie-breakers is fine).

<p>
<li>
Some areas will be easier to agree on than others.
Our priorities should be based on achieving as much
interoperability as possible if we can't attain perfection.
That is, it is better to end up with a few restrictions being required
for interoperable code, than to have no interoperability at all.
This suggests priorities as follows:
    <ol>
    <li> Items requiring base ABI changes that might affect other
	languages, and will therefore become impossible soon.
	Examples include exception handling / stack unwind,
	or ELF changes (not extensions).
    <li> Core features where differences will prevent virtually any
	C++ object code from porting.
	Examples include data layout and calling conventions.
    <li> Limited usage features,
	where users can achieve portability by avoiding the feature.
	An example might be multi-threading.
    <li> Peripheral features,
	where the requirements on users to achieve
	portability are clear and easy to implement.
	An example is non-explicit inlining,
	where compilers would presumably allow it to just be suppressed.
    <li> Tool interfaces, which affect how users build code,
	rather than what they build.
	An example is the compilation command line.
    </ol>

<p>
<li>
Mechanisms/methods which allow coexistence of incompatible
implementations may be suitable in some cases.
For instance, packaging vendor-specific compiler support runtimes
in DSOs occupying distinct namespaces might allow multiple such DSOs to
be loaded for mixed objects and avoid requiring that all vendors have
the same support runtimes.

</ul>

<p>
<hr>

<p>
<h4> Action Item Status </h4>

<p>
<table border=on cellpadding=3>

<tr class=small>
<th> # </th>
<th> Action </th>
<th> Who </th>
<th> Status </th>
<th> Opened </th>
<th> Closed </th>
</tr>

<tr class=small> <td> 1 </td>
<td> Distribute Sun C++ ABI </td>
<td> Mike Ball </td>
<td> open </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> 2 </td>
<td> Distribute Sun C++ ABI Rationale </td>
<td> Mike Ball </td>
<td> open </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> 3 </td>
<td> Distribute Taligent C++ ABI </td>
<td> Cary Coutant </td>
<td> open </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> 4 </td>
<td> Expedite IA-64 RT Arch doc release </td>
<td> Cary Coutant </td>
<td> closed </td>
<td> 990603 </td>
<td> 990720 </td>
</tr>

<tr class=small> <td> 5 </td>
<td> Set up n-way NDA for eligible members </td>
<td> Priti Shrivastav </td>
<td> open </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> 6 </td>
<td> Organize/summarize object layout issues and alternatives </td>
<td> Matt Austern </td>
<td> closed </td>
<td> 990603 </td>
<td> 990624 </td>
</tr>

<tr class=small> <td> 7 </td>
<td> Write-up of Vfunc call protocol
</td>
<td> Christophe de Dinechin </td>
<td> closed </td>
<td> 990610 </td>
<td> 990805 </td>
</tr>

<tr class=small> <td> 8 </td>
<td> Write-up of object layout strawman </td>
<td> Matt Austern </td>
<td> closed </td>
<td> 990610 </td>
<td> 990624 </td>
</tr>

<tr class=small> <td> 9 </td>
<td> Check with c++-core about empty base placement </td>
<td> Jason Merrill </td>
<td> closed </td>
<td> 990610 </td>
<td> 990618 </td>
</tr>

<tr class=small> <td> 10 </td>
<td> Describe dynamic cast / inaccessible base issue </td>
<td> Daveed Vandevoorde </td>
<td> closed </td>
<td> 990617 </td>
<td> 990701 </td>
</tr>

<tr class=small> <td> 11 </td>
<td> Summarize ctor/dtor issues </td>
<td> Michael Lam </td>
<td> closed </td>
<td> 990617 </td>
<td> 990729 </td>
</tr>

<tr class=small> <td> 12 </td>
<td> Describe Intel exception model </td>
<td> Priti Shrivastav </td>
<td> open </td>
<td> 990624 </td>
<td> </td>
</tr>

<tr class=small> <td> 13 </td>
<td> Propose RTTI representation </td>
<td> Daveed Vandevoorde </td>
<td> open </td>
<td> 990701 </td>
<td> </td>
</tr>

<tr class=small> <td> 14 </td>
<td> Open EDG exception stack? </td>
<td> Daveed Vandevoorde </td>
<td> open </td>
<td> 990715 </td>
<td> </td>
</tr>

<tr class=small> <td> 15 </td>
<td> Priority scheme descriptor for C-2 </td>
<td> Jim Dehnert </td>
<td> closed </td>
<td> 990715 </td>
<td> 990804 </td>
</tr>

<tr class=small> <td> 16 </td>
<td> Covariant return scheme </td>
<td> Jason Merill </td>
<td> closed </td>
<td> 990715 </td>
<td> 990729 </td>
</tr>

<tr class=small> <td> 17 </td>
<td> Validate Christophe's B-6 Vtable layout </td>
<td> Jim Dehnert </td>
<td> closed </td>
<td> 990729 </td>
<td> 990811 </td>
</tr>

<tr class=small> <td> 18 </td>
<td> Check Sun dynamic cast algorithm </td>
<td> Michael Lam </td>
<td> closed </td>
<td> 990805 </td>
<td> 990812 </td>
</tr>

<tr class=small> <td> 19 </td>
<td> Write up C-3 destructor proposal </td>
<td> Jim Dehnert </td>
<td> closed </td>
<td> 990805 </td>
<td> 990811 </td>
</tr>

<tr class=small> <td> 20 </td>
<td> Look at implications of discussion on B-1, B-6 </td>
<td> Christophe de Dinechin </td>
<td> open </td>
<td> 990812 </td>
<td> </td>
</tr>

<tr class=small> <td> 21 </td>
<td> Look at alternative implementations of C-2 </td>
<td> Jim Dehnert </td>
<td> open </td>
<td> 990812 </td>
<td> </td>
</tr>


</table>

<p>
<hr>

<p>
<h4> Issue Status </h4>

In the following table,
the <b><i>class</i></b> column attempts to classify the issue on the
basis of what it likely affects.
The identifiers used are:

<table>
<tr class=small> <td> call </td>
<td> Function call interface, i.e. call linkage </td>
</tr>

<tr class=small> <td> data </td>
<td> Data layout </td>
</tr>

<tr class=small> <td> lib </td>
<td> Runtime library support </td>
</tr>

<tr class=small> <td> lif </td>
<td> Library interface, i.e. API </td>
</tr>

<tr class=small> <td> g </td>
<td> Potential gABI impact </td>
</tr>

<tr class=small> <td> ps </td>
<td> Potential psABI impact </td>
</tr>

<tr class=small> <td> source </td>
<td> Source code conventions (i.e. API, not ABI) </td>
</tr>

<tr class=small> <td> tools </td>
<td> May affect how program construction tools interact </td>
</tr>
</table>

<p>
<hr width=50%>

<p>
<table border=on cellpadding=3>

<tr class=small>
<th> # </th>
<th> Issue </th>
<th> Class </th>
<th> Status </th>
<th> Source </th>
<th> Opened </th>
<th> Closed </th>
</tr>

<tr class=small> </tr>
<tr class=small> <th> A </th>
<th colspan=6> <a href=issues-C++-layout.html> Object Layout </a> </th>
</tr>

<tr class=small> <td> A-1 </td>
<td> Vptr location </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990624 </td>
</tr>

<tr class=small> <td> A-2 </td>
<td> Virtual base classes </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990624 </td>
</tr>

<tr class=small> <td> A-3 </td>
<td> Multiple inheritance </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990701 </td>
</tr>

<tr class=small> <td> A-4 </td>
<td> Empty base classes </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990624 </td>
</tr>

<tr class=small> <td> A-5 </td>
<td> Empty parameters </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990701 </td>
</tr>

<tr class=small> <td> A-6 </td>
<td> RTTI (<code>type_info</code>) .o representation </td>
<td> data call ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> A-7 </td>
<td> Vptr sharing with primary base class </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990729 </td>
</tr>

<tr class=small> <td> A-8 </td>
<td> (Virtual) base class alignment </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990624 </td>
</tr>

<tr class=small> <td> A-9 </td>
<td> Sorting fields as allowed by [class.mem]/12 </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990624 </td>
</tr>

<tr class=small> <td> A-10 </td>
<td> Class parameters in registers </td>
<td> call </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990701 </td>
</tr>

<tr class=small> <td> A-11 </td>
<td> Pointers to member functions </td>
<td> data </td>
<td> closed </td>
<td> Cygnus </td>
<td> 990603 </td>
<td> 990812 </td>
</tr>

<tr class=small> <td> A-12 </td>
<td> Merging secondary vtables </td>
<td> data </td>
<td> closed </td>
<td> Sun </td>
<td> 990610 </td>
<td> 990805 </td>
</tr>

<tr class=small> <td> A-13 </td>
<td> Parameter struct field promotion </td>
<td> call </td>
<td> closed </td>
<td> SGI </td>
<td> 990603 </td>
<td> 990701 </td>
</tr>

<tr class=small> <td> A-14 </td>
<td> Pointers to data members </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990729 </td>
<td> 990805 </td>
</tr>

<tr class=small> </tr>
<tr class=small> <th> B </th>
<th colspan=6> <a href=issues-C++-layout.html#vfunc>
Virtual Function Handling </a> </th>
</tr>

<tr class=small> <td> B-1 </td>
<td> Adjustment of "this" pointer (e.g. thunks) </td>
<td> data call </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> B-2 </td>
<td> Covariant return types </td>
<td> call </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990722 </td>
</tr>

<tr class=small> <td> B-3 </td>
<td> Allowed caching of vtable contents </td>
<td> call </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990805 </td>
</tr>

<tr class=small> <td> B-4 </td>
<td> Function descriptors in vtable </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990805 </td>
</tr>

<tr class=small> <td> B-5 </td>
<td> Where are vtables emitted? </td>
<td> data </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> B-6 </td>
<td> Virtual function table layout </td>
<td> data </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> B-7 </td>
<td> Objects and Vtables in shared memory </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990624 </td>
<td> 990805 </td>
</tr>

<tr class=small> <td> B-8 </td>
<td> dynamic_cast </td>
<td> data </td>
<td> open </td>
<td> SGI </td>
<td> 990628 </td>
<td> </td>
</tr>


<tr class=small> </tr>
<tr class=small> <th> C </th>
<th colspan=6> Object Construction/Destruction </th>
</tr>

<tr class=small> <td> C-1 </td>
<td> Interaction with .init/.fini </td>
<td> lif ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> C-2 </td>
<td> Order of ctors/dtors w.r.t. link </td>
<td> lif ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> C-3 </td>
<td> Order of ctors/dtors w.r.t. DSOs </td>
<td> ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> C-4 </td>
<td> Calling vfuncs in ctors/dtors </td>
<td> call </td>
<td> open </td>
<td> Cygnus </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> C-5 </td>
<td> Calling virtual destructors </td>
<td> call </td>
<td> open </td>
<td> Sun </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> C-6 </td>
<td> Extra parameters to ctors/dtors </td>
<td> call </td>
<td> open </td>
<td> Cygnus </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> C-7 </td>
<td> Passing value parameters by reference </td>
<td> call </td>
<td> closed </td>
<td> All </td>
<td> 990625 </td>
<td> 990805 </td>
</tr>

<tr class=small> <td> C-8 </td>
<td> Returning classes with non-trival copy constructors </td>
<td> call </td>
<td> closed </td>
<td> All </td>
<td> 990625 </td>
<td> 990722 </td>
</tr>


<tr class=small> </tr>
<tr class=small> <th> D </th>
<th colspan=6> Exception Handling </th>
</tr>

<tr class=small> <td> D-1 </td>
<td> Language-specific data area format </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> D-2 </td>
<td> Unwind personality routines </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> D-3 </td>
<td> Unwind process clarification </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> D-4 </td>
<td> Unwind routines nested? </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> D-5 </td>
<td> Interaction with other languages (e.g. Java) </td>
<td> lib ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> D-6 </td>
<td> Allow resumption in other languages? </td>
<td> lib ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> D-7 </td>
<td> Interaction with signals or asynch events </td>
<td> lib ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> D-8 </td>
<td> Interaction with threads packages </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990603 </td>
<td> </td>
</tr>


<tr class=small> </tr>
<tr class=small> <th> E </th>
<th colspan=6> Template Instantiation Model </th>
</tr>

<tr class=small> <td> E-1 </td>
<td> When does instantiation occur? </td>
<td> tools </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> E-2 </td>
<td> Separate compilation model </td>
<td> tools </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> E-3 </td>
<td> Template repository </td>
<td> tools </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>


<tr class=small> </tr>
<tr class=small> <th> F </th>
<th colspan=6> Name Mangling </th>
</tr>

<tr class=small> <td> F-1 </td>
<td> Mangling convention </td>
<td> call </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> F-2 </td>
<td> Mangled name size </td>
<td> call g </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>

<tr class=small> <td> F-3 </td>
<td> Distinguish template instantiation and specialization
</td>
<td> call g </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>


<tr class=small> </tr>
<tr class=small> <th> G </th>
<th colspan=6> Miscellaneous </th>
</tr>

<tr class=small> <td> G-1 </td>
<td> Basic command line options </td>
<td> tools </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> G-2 </td>
<td> Detection of 1-def rule violations </td>
<td> call </td>
<td> open </td>
<td> Sun </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> G-3 </td>
<td> Inlined routine linkage </td>
<td> call </td>
<td> open </td>
<td> Sun </td>
<td> 990603 </td>
<td> </td>
</tr>

<tr class=small> <td> G-4 </td>
<td> Dynamic init of local static objects and multithreading </td>
<td> call </td>
<td> open </td>
<td> SCO </td>
<td> 990607 </td>
<td> </td>
</tr>

<tr class=small> <td> G-5 </td>
<td> Varargs routine interface </td>
<td> call </td>
<td> open </td>
<td> HU-B </td>
<td> 990810 </td>
<td> </td>
</tr>

<tr class=small> </tr>
<tr class=small> <th> H </th>
<th colspan=6> Runtime Library Interface </th>
</tr>

<tr class=small> <td> H-1 </td>
<td> Runtime library DSO name </td>
<td> tools </td>
<td> open </td>
<td> SGI </td>
<td> 990616 </td>
<td> </td>
</tr>

<tr class=small> <td> H-2 </td>
<td> Runtime library API </td>
<td> lif </td>
<td> open </td>
<td> SGI </td>
<td> 990616 </td>
<td> </td>
</tr>


</table>

<p>
<hr>

<p>
<h4> Procedure Notes from 3 June 1999 </h4>

<ul>
<li> Meetings:  10-12 Thursdays at SGI for the near term.
<li> Intel NDA:  Generally unnecessary.  Priti will set up n-way
     for eligible members for cases where needed.  Cary expects RT
     architecture/software conventions document to be released in the
     next month or two, removing most of the issues.
<li> Communication:  Use of reflector encouraged for discussion.
     NDA communication will be handled with password-protected PDF
     once Intel sets up n-way.
<li> Available documents:  Parties with existing, relevant documents
     (includes Sun, HP) will send them to group.
<li> Intellectual property:  Participants don't expect problems with
     release of any of their IP.  Microsoft has extensive patents in
     the area, but they are excessively broad (covering obvious ideas
     and prior art), so expectation is that they are not a problem.
     Nonetheless, we should be aware of them.
</ul>

<p>
<hr>

<p>
Please send corrections to <a href=mailto:dehnert@xxxxxxx>Jim Dehnert</a>.


</BODY>
</HTML>
<HTML>

<HEAD>
<title>C++ ABI Open Issues</title>

<link rel=stylesheet href=small-table.css type="text/css">
<link rel=stylesheet href=code.css type="text/css">

<hr>

<font size=6><i><b>
<p>
C++ ABI Open Issues
</b></i></font>

<font size=-1>
<p>
<i>Revised 17 August 1999</i>

</center>

</HEAD>

<BODY>

<p> <hr> <p>
<h3> Revisions </h3>

<p>
<font color=blue>[990813]</font>
Closed <a href=cxx-closed.html#A11>A-11</a>.
Additions to <a href=#A6>A-6</a>,
<a href=#B1>B-1</a>, <a href=#B6>B-6</a>, <a href=#B8>B-8</a>,
<a href=#C2>C-2</a>,
<a href=#G5>G-5</a>.

<p>
<font color=blue>[990810]</font>
New issue <a href=#G5>G-5</a>.
Additions to <a href=#B6>B-6</a>, <a href=#C2>C-2</a>, <a href=#C3>C-3</a>.

<p>
<font color=blue>[990805]</font>
Closed A-12, A-14, B-3, B-4, B-7, C-7.
Additions to <a href=#A6>A-6</a>, <a href=#A11>A-11</a>,
<a href=#B1>B-1</a>, <a href=#B6>B-6</a>, <a href=#F1>F-1</a>.

<p>
<font color=blue>[990729]</font>
Closed A-7.
Additions to A-11, A-12, C-2.
Summary added for A-12.
New issue A-14.

<p>
<font color=blue>[990727]</font>
Closed B-2, C-8.
Additions to A-9 (closed), C-2.
Summaries added for C-4, C-6, D-1 to D-4.

<p>
<font color=blue>[990720]</font>
Additions to B-2, B-5, C-2, D-1.

<p>
<font color=blue>[990701]</font>
Closed A-3, A-5, A-10, A-13.
Additions to A-6, B-6, B-7, B-8, C-2, C-7.

<p>
<font color=blue>[990625]</font>
Closed A-1, A-2, A-4, A-8, A-9.
Additions to A-3, A-5, A-7, B-4, B-5, B-7, G-3, G-4.
New issues B-6, B-7, B-8, C-7, C-8.

<p>
<font color=blue>[990616]</font>
Added HP summaries.
Added sketchy notes from 990610 discussions (A and B issues).
A-10 was intended by HP as something different than I described,
so it was renamed, and a new issue A-13 opened as an SGI issue.
HP did not submit A-12, so relabeled as Sun's (is that right?).
Added library interface issues, H-1 and H-2.


<p> <hr> <p>
<h3> Definitions </h3>

<p>
The issues below make use of the following definitions:

<dl>

<p>
<dt> <i>empty class</i> </dt>
<dd>
A class with no non-static data members,
no virtual functions, no virtual base classes,
and no non-empty non-virtual base classes.)

<p>
<dt> <i>nearly empty class</i> </dt>
<dd>
A class, the objects of which contain only a Vptr.

<p>
<dt> <i>vague linkage</i> </dt>
<dd>
The treatment of entities --
e.g. inline functions, templates, vtables --
with external linkage that can be
defined in multiple translation units,
while the ODR requires that the program
behave as if there were only a single definition.

</dl>


<p> <hr> <p>
<h3> Issue Status </h3>

In the following sections,
the <b><i>class</i></b> of an issue attempts to classify it on the
basis of what it likely affects.
The identifiers used are:

<table>
<tr> <td> call </td>
<td> Function call interface, i.e. call linkage </td>
</tr>

<tr> <td> data </td>
<td> Data layout </td>
</tr>

<tr> <td> lib </td>
<td> Runtime library support </td>
</tr>

<tr> <td> lif </td>
<td> Library interface, i.e. API </td>
</tr>

<tr> <td> g </td>
<td> Potential gABI impact </td>
</tr>

<tr> <td> ps </td>
<td> Potential psABI impact </td>
</tr>

<tr> <td> source </td>
<td> Source code conventions (i.e. API, not ABI) </td>
</tr>

<tr> <td> tools </td>
<td> May affect how program construction tools interact </td>
</tr>
</table>

<p> <hr> <p>
<h3> Object Layout Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=A1></a> <td> A-1 </td>
<td> Vptr location </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Where is the Vptr stored in an object (first or last are the usual answers).
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
First.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=A2></a> <td> A-2 </td>
<td> Virtual base classes </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Where are the virtual base subobjects placed in the class layout?
How are data member accesses to them handled?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Virtual base subobjects are normally placed at the end (see issue A-9).
The Vtable will contain an offset to the beginning of the base object
for use by member accesses to them (see issue B-6).
</td> </tr>

</table>

<p>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-3 </td>
<td> Multiple inheritance </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990701 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Define the class layout in the presence of multiple base classes.
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
See the class layout description in closed issue A-9.
Briefly, empty bases will normally go at offset zero,
non-virtual base classes at the beginning,
and virtual base classes at the end.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-4 </td>
<td> Empty base classes </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Where are empty base classes allocated?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
At offset zero if possible.  See A-9.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-5 </td>
<td> Empty parameters </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990701 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
When passing a parameter with an empty class type by value,
what is the convention?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Except for cases of non-trivial copy constructors (see C-7),
and parameters in the variable part of varargs lists,
no parameter slot will be allocated to empty parameters.
</td> </tr>

</table>


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=A6></a> <td> A-6 </td>
<td> RTTI .o representation </td>
<td> data call ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Define the data structure to be used for RTTI, that is:
<ul>
<li> for user <code>type_info</code> calls;
<li> for dynamic_cast implementation; and
<li> for exception-handling.
</ul>
</td> </tr>

</table>

<p>
<font color=blue>[990701 All]</font>
Daveed will put together a proposal by the 15th (action #13);
the group will discuss it on the 22nd.

<p>
<font color=blue>[990805 All]</font>
Daveed should have his proposal together for discussion.
Michael Lam will look into the Sun dynamic cast algorithm.

<p>
It was noted that appropriate name selection along with the normal
DSO global name resolution should be sufficient to produce a unique
address for each class' RTTI struct,
which address would then be a suitable identifier for comparisons.

<p>
<font color=blue>[990812 Sun -- Michael]</font>
Sun has provided a description,
<a href=Sun-RTTI-990812.html>in a separate page</a>,
describing their implementation.
They are filing for a patent on the algorithms described.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-7 </td>
<td> Vptr sharing with primary base class </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990729 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
It is in general possible to share the virtual pointer with a
polymorphic base class (the <i>primary</i> base class).
Which base class do we use for this?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Share with the first non-virtual polymorphic base class,
or if none with the first nearly empty virtual base class.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-8 </td>
<td> (Virtual) base class alignment </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
A (virtual) base class may have a larger alignment constraint than a
derived class.
Do we agree to extend the alignment constraint to the derived class?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
The derived class will have at least the alignment of any base class.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-9 </td>
<td> Sorting fields as allowed by [class.mem]/12 </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The standard constrains ordering of class members in memory only if
they are not separated by an access clause.
Do we use an access clause as an opportunity to fill the gaps left by padding?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
See <a href=cxx-closed.html#A9>closed issue list</a>.
</td> </tr>

</table>

<p>
<font color=blue>[990722 all]</font>
The precise placement of empty bases when they don't fit at offset zero
remained imprecise in the original description.
Accordingly, a precise layout algorithm is described in
a separate writeup of <a href=abi-layout.html>Data Layout</a>.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-10 </td>
<td> Class parameters in registers </td>
<td> call </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990701 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The C ABI specifies that small structs are passed in registers.
Does this apply to small non-POD C++ objects passed by value?
What about the copy constructor and <code>this</code> pointer in that case?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Non-POD C++ objects are passed like C structs,
except for cases with non-trivial copy constructors identified in C-7.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=A11></a> <td> A-11 </td>
<td> Pointers to member functions </td>
<td> data </td>
<td> closed </td>
<td> Cygnus </td>
<td> 990603 </td>
<td> 990812 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
How should pointers to member functions be represented?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
As a pair of values, a "pointer" and a this adjustment.
See the closed list for a more detailed description.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=A12></a> <td> A-12 </td>
<td> Merging secondary vtables </td>
<td> data </td>
<td> closed </td>
<td> Sun </td>
<td> 990610 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Sun merges the secondary Vtables for a class (i.e. those for
non-primary base classes) with the primary Vtable by appending them.
This allows their reference via the primary Vtable entry symbol,
minimizing the number of external symbols required in linking,
in the GOT, etc.
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Concatenate the Vtables associated with a class in the same order
that the corresponding base subobjects are allocated in the object.
</td> </tr>

</table>


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-13 </td>
<td> Parameter struct field promotion </td>
<td> call </td>
<td> closed </td>
<td> SGI </td>
<td> 990603 </td>
<td> 990701 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
It is possible to pass small classes either as memory images,
as is specified by the base ABI for C structs,
or as a sequence of parameters, one for each member.
Which should be done, and if the latter,
what are the rules for identifying "small" classes?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
No special treatment will be specified by the ABI.
</td> </tr>

</table>


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr class=small> <a name=A14></a> <td> A-14 </td>
<td> Pointers to data members </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990729 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
How should pointers to data members be represented?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Represented as one plus the offset from the base address.
</td> </tr>

</table>


<p> <hr> <p>
<h3> Virtual Function Handling Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=B1></a> <td> B-1 </td>
<td> Adjustment of "this" pointer (e.g. thunks) </td>
<td> data call </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
There are several methods for adjusting the <i>this</i> pointer
for a member function call,
including thunks or offsets located in the vtable.
We need to agree on the mechanism used,
and on the location of offsets, if any are needed.
To maximize performance on IA64,
a slightly unusual approach such as using secondary entry points
to perform the adjustment may actually prove interesting. 
</td> </tr>

</table>

<p>
<font color=blue>[990623 HP -- Christophe]</font>

<p>
<h4>Open Issues Relevant To This Discussion</h4>

<ol>
<p>
<li>
Keeping all of a class in a single load module.
The vtable contains the target address and one copy of the target GP.
This implies that it is not in text, and that it is generated by dld.

<p>
<li>
Detailed layout of the virtual table.

<p>
<li>
How can we share class offsets?

</ol>


<p>
<h4> 1. Scope and "State of the Art"</h4>

<p>
The following proposal applies only to calls to virtual functions  
when a this pointer adjustment is required from a base class to a  
derived class.
Essentially, this means multiple inheritance, and the  
existence of two or more virtual table pointers (vptr)
in the complete object.
The multiple vptrs are required so that the layout  
of all bases is unchanged in the complete object.
There will be one additional vptr for each base class which already
required a vptr,  
but cannot be placed in the whole object so that it shares its vptr  
with the whole object.
Note: when the vptr is shared,
the base class  is said to be the "primary base class",
and there is only one such class.

<p>
For the primary base class, no pointer adjustment is needed.
For all  other bases, a pointer to the whole object is not a pointer
to the base class,
so whenever a pointer to the base class is needed,  
adjustment will occur.

<p>
In particular, when calling a virtual function,
one does not know in advance in which class the function was actually defined.
Depending on the actual class of the object pointed to,
pointer adjustment may be needed or not,
and the pointer adjustment value may vary from class to class.
The existing solution is to have the vtable point not to the function itself,
but to a "thunk" which does pointer adjustment when needed,
and then jumps to the actual function.  
Another possibility is to have an offset in the vtable,
which is used by the called function.
However, more often than not, this implies adding zero.

<p>
Virtual bases make things slightly more complicated.
In that case, the data layout is such that there is only
one instance of the virtual base in the whole object.
Therefore, the offset from a this  
pointer to a same virtual base may change along the inheritance tree.  
This is solved by placing an offset in the virtual table,
which is used to adjust the this pointer to the virtual base.


<p>
<h4> 2. Proposal and Rationale </h4>

<p>
My proposal is to replace thunks with offsets,
with two additional tricks:
<ul>
<li>
Give a virtual function two entry points,
so as to bypass the adjustment when it's known to be zero.
<li>
Moving the adjustment at call-site,
where it can be scheduled more easily,
using a "reasonable" value,
so that the adjustment is bypassed even more often.
</ul>

<p>
The thunks are believed to cost more on IA64 than they would on  
other platforms.
The reason is that they are small islands of code spread throughout the code,
where you cannot guarantee any cache locality.
Since they immediately follow an indirect branch,
chances are we will always encounter both a branch misprediction and a  
I-cache miss in a row.

<p>
On the other hand,
a virtual function call starts by reading the virtual function address.
Reading the offset immediately thereafter should almost never cause a
D-cache miss (cache locality should be good).
More often than not, no adjustment is needed,
or the adjustment will be done at call site correctly.
In the worst case scenario, we perform two adjustments,
one static at call site, and one dynamic in the callee,
but this case should be really infrequent.


<p>
<h4> 3. New Calling Convention </h4>

<p>
The new calling convention requires that the 'this' pointer on entry  
points to the class for which the virtual function is just defined.  
That is, for A::f(),
the pointer is an A* when the main entry of the function is reached.
If the actual pointer is not an A*,
then an adjusting entry point is used,
which immediately precedes the function.

<p>
In the following, we will assume the following examples:
<p>
<code><pre>
    struct A { virtual void f(); };
    struct B { virtual void g(); };
    struct C: A, B { }
    struct D : C { virtual void f(); virtual void g(); }
    struct E: Other, C { virtual void f(); virtual void g(); }
    struct F: D, E { virtual void f(); }

    void call_Cf(C *c) { c->f(); }
    void call_Cg(C *c) { c->g(); }
    void call_Df(D* d) { d->f(); }
    void call_Dg(D* d) { d->g(); }
    void call_Ef(E* e) { e->f(); }
    void call_Eg(E* e) { e->g(); }
    void call_Ff(F *ff) { ff->f(); }
    void call_Fg(F *ff) { ff->g(); }	// Invalid: ambiguous
</pre></code>

<dl>
<p>
<dt> a) Call site:
<dd>
The caller performs adjustment to match the class of the last  
overrider of the given function.

<ul>
<p>
<li> call_Cf will assume that the pointer needs to be cast to an A*,  
since C::f is actually A::f. Since A is the primary base class, no  
adjustment is done at call site.

<p>
<li> call_Cg is similar, but assumes that the actual type is a B*, and  
performs the adjustment, since B is not the primary base class.

<p>
<li> call_Df and call_Dg will assume that the pointer needs to be cast  
to a D*, which is where D::f is defined. No adjustment is performed  
at call site.
</ul>
</dd>


<p>
<dt> b) Callee
<dd>
<ul>
<p>
<li> A::f and B::g are defined in classes where there is a single vptr.  
They don't define a secondary entry point. Because of call-site  
conventions, they expect to always be called with the correct type.

<p>
<li> D::f is defined in a class where there is more than one vptr, so  
it needs a secondary entry point and an entry 'convert_to_D' in the  
vtable. That's because it can be potentially called with either an A*  
or a B*. There are two vtables, one for A in D, one for B in D. The  
D::f entry in A in D points to the non-adjusting entry point, since A  
shares its vptr.

<p>
<li> D::g requires a secondary entry point, that will read the same  
offset 'convert_to_D' from the vtable.

<p>
<li> E also will require a 'convert_to_E' entry in the vtable, but this  
time, the vtable for A in C will have to point to an adjusting entry  
point, since A no longer shares the vptr with E (assuming Other has  
a vptr). This vtable is also the vtable of C in E.
</ul>
</dd>


<p>
<dt> c) Offsets in the vtable
<dd>
Offsets have to be placed in the vtable at a position which does not  
conflict with any offset in the inheritance tree.

<p>
convert_to_D and convert_to_E are likely to be at the same offset in  
the vtable. This is not a problem, even if D and E are used in the  
same class, such as F, because this is the same offset in different  
vtables.

<ul>
<p>
<li> call_Fg is invalid, because it is ambiguous.

<p>
<li> A notation such as ((E*) ff)->g() can be used to disambiguate, but  
in that case, we don't use the same vtable (either the E in F or D  
in F vtable). The E in F vtable uses that offset as 'convert_to_E',  
whereas the D in F vtable uses that offset as 'convert_to_D'.

<p>
<li> Similarly, call_Cf called with an F object will actually be called  
with the E in F or D in F, which disambiguates which C is actually  
used. The actual C* passed will have been adjusted by the caller  
unambiguously, or the call will be invalid.

<p>
<li> For functions overriden in F, an entry 'convert_to_F' is created  
anyway. This entry will not overlap with either convert_to_E or  
convert_to_D.
</ul>

<p>
The fact that an offset is reserved does not mean that it is  
actually used. A vtable need to contain the offset only if it refers  
to a function that will use it. An offset of 0 is not needed, since  
the function pointer will point to the non-adjusting entry point in  
that case.
</dd>

</dl>


<p>
<h4> 4. Cases where adjustment is performed </h4>

<ul>
<p>
<li> For call_Cf: No adjustment is done at call site. No adjustment is  
done at callee site if the dynamic type is C,  or D, or D in F (that  
is, F casted to an E).

<p>
<li> For call_Cg: Adjustment to B* is done at call-site. No further  
adjustment is needed if the dynamic type is C, D, or D in F. On the  
other hand, a second adjustment may happen for an E or E in F,  
because C is not their primary base.
</ul>

<p>
In other words, adjustment is made only when necessary, and at a  
place where it is better scheduled than with thunks. The only bad  
case is double adjustment for call_Cg called with an E*. This case  
can probably be considered rare enough, compared to calls such as  
call_Cg called with a C*, where we now actually do the adjustment at  
the call-site.


<p>
<h4> 5. Comparing the code trails </h4>

<p>
Currently, the sequence for a virtual function call in a shared  
library will look as follows. I'm assuming +DD64, there would be some  
additional addp4 in +DD32. The trail below is the dynamic execution  
sequence. In bold and between #if/#endif, the affected code.

<p>
<code><pre>
        // Compute the address of the vptr in the object,
	// from the this pointer
        // Optional, since vptroffset is often 0.
	// This also adjusts to the class of the final overrider
        addi            Rthis=vptroffset_of_final_overrider,Rthis
        ;;
        // Load the vptr in a register
        ld8             Rvptr=[Rthis]
        ;;
        // Add the offset to get to the function descriptor pointer
	// in the vtable.  Never zero, this instruction is always generated
        addi            Rfndescr=fndescroffset,Rvptr
        ;;
        // (Assuming inlined stub) Load the function address and new GP
        ld8             Rfnaddr=[Rfndescr],8
        ;;
        // Load the new GP
        ld8             GP=[Rfndescr]
        mov             BRn=Rfnaddr
        ;;
        // Perform the actual branch to the target

        // ...
        // ... Branch misprediction almost always, followed by
        // ... I-Cache miss almost always if jumping to a thunk
        br.call B0=BRn

#if OLD_ADJUST
thunk_A::f_from_a_B:
        // If the 'adjustment_from_B_to_A is the 'adjustment_to_A' above,
        // then in the new case, the vtable directly points to A::f
        addi            Rthis,adjustment_from_B_to_A

        // In most cases, we can probably generate a PC-relative branch here
        // It is unclear whether we would correctly predict that branch
        // (since it is assumed that we arrive here immediately following
        // a misprediction at call site)
        br              A::f
#endif // OLD_ADJUST

// This occurs less often than OLD_ADJUST
// (it does not happen when call-site adjustment is correct)
#if NEW_ADJUST
adjusting_entry_A::f
        // Can't be executed in less than 3 cycles?
        addi            Rvptr=class_adjustment_offset,Rvptr
        ;;
        // This loads data which is close to the fn descriptor,
        // so it's likely to be in the D-cache
        ld8             Rvptr=[Rvptr]
        ;;
        add             Rthis=Rthis,Rvptr
#endif

A::f:
        alloc   ...
</pre></code>

<p>
<font color=blue>[990812 All]</font>
Discussion of B-6 raises questions of impact on the above approach.
Christophe will look at the issues.


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=B2></a> <td> B-2 </td>
<td> Covariant return types </td>
<td> call </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990722 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
There are several methods for adjusting the 'this' pointer of the
returned value for member functions with covariant return types.
We need to decide how this is done.
Return thunks might be especially costly on IA64,
so a solution based on returning multiple pointers may prove more interesting.
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Provide a separate Vtable entry for each return type.
</td> </tr>

</table>


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=B3></a> <td> B-3 </td>
<td> Allowed caching of vtable contents </td>
<td> call </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The contents of the vtable can sometimes be modified,
but the concensus is that it is nonetheless always allowed to "cache" elements,
i.e. to retain them in registers and reuse them,
whenever it is really useful.
However, this may sometimes break "beyond the standard" code,
such as code loading a shared library that replaces a virtual function.
Can we all agree when caching is allowed? 
</td> </tr>
<tr> <td colspan=7>
<b> Resolution </b>:
Caching is allowed within a member function.
</td> </tr>

</table>


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=B4></a> <td> B-4 </td>
<td> Function descriptors in vtable </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
For a runtime architecture where the caller is expected to load the GP
of the callee (if it is in, or may be in, a different DSO), e.g. HP/UX,
what should vtable entries contain?
One possibility is to put a function address/GP pair in the vtable.
Another is to include only the address of a thunk which loads the GP
before doing the actual call.
</td> </tr>
<tr> <td colspan=7>
<b> Resolution </b>:
The Vtable will contain a function address/GP pair.
</td> </tr>

</table>


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=B5></a> <td> B-5 </td>
<td> Where are vtables emitted? </td>
<td> data </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
In C++, there are various things with external linkage that can be
defined in multiple translation units,
while the ODR requires that the program
behave as if there were only a single definition.
>From the user's standpoint, this applies to inlines and templates.
>From the implementation's perspective,
it also applies to things like vtables and RTTI info.
(We call this <i>vague linkage</i>.)
</td> </tr>

</table>

<p>
<font color=blue>[990624 Cygnus -- Jason]</font>
There are several ways of dealing with vague linkage items:
<ol>
<li> Emit them everywhere and only use one.
<li> Use some heuristic to decide where to emit them.
<li> Use a database to decide where to emit them.
<li> Generate them at link time.
</ol>

<p>
#3 and #4 are feasible for templates,
but I consider them too heavyweight to be used for other things.

<p>
The typical heuristic for #2 is "with the first non-inline,
non-abstract virtual function in the class".
This works pretty well,
but fails for classes that have no such virtual function,
and for non-member inlines.
Worse, the heuristic may produce different results in different
translation units,
as a method could be defined inline after being declared non-inline
in the class body.
So we have to handle multiple copies in some cases anyway.

<p>
The way to handle this in standard ELF is weak symbols.
If all definitions are marked weak,
the linker will choose one
and the others will just sit there taking up space.

<p>
Christophe mentioned the other day that the HP compiler used the
typical heuristic above,
and handled the case of different results by encoding the
key function in the vtable name.
But this seems unnecessary when we can just choose one of multiple defns.

<p>
A better solution than weak symbols alone would be to set things up so
that the linker will discard the extra copies.
Various existing implementations of this are:

<ol>
<p>
<li>
The Microsoft PE/COFF defn includes support for COMDAT sections,
which key off of the first symbol defined.
One copy is chosen, others are discarded.
You can specify conditions to the linker
(must have same contents, must have same size).

<p>
<li>
The IBM XCOFF platform includes a garbage-collecting linker;
sections that are not referenced in a sweep from main are discarded.
In xlC, template instantiations are emitted in separate sections,
with encoded names;
at link time, one copy is renamed to the real mangled name,
and the others are discarded by garbage collection.
</ol>

<p>
The GNU ELF toolchain does a variant of #1 here;
any sections with names beginning with ".gnu.linkonce."
are treated as COMDAT sections.
It seems more sensible to me to key off of the section name
than the first symbol name as in PE.

<p>
The GNU linker recently added support for garbage collection,
and I've been thinking about changing our handling of vague
linkage to make use of it, but haven't.

<p>
I propose that the ia64 base ABI be extended to
provide for either COMDAT sections or garbage collection,
and that we use that support for vague linkage.

<p>
I further propose that we not use heuristics to
cut down the number of copies ahead of time;
they usually work fine, but can cause problems in some situations,
such as when not all of the class's members are in the same symbol space.
Does the ia64 ABI provide for controlling which symbols
are exported from a shared library?

<p>
A side issue: What do we want to do with
dynamically-initialized variables?
The same thing, or use COMMON?
I propose COMMON.

<p>
See also G-3, for vague linkage of inlined routines and their static variables.

<p>
<font color=blue>[990624 SGI summarizing others]</font>
HP uses COMDAT for many cases, keying from the symbol names.
HP also uses some heuristics.
HP observes that IA-64 objects will already be large.
>From the base ABI discussions,
any use of WEAK or COMMON symbols will need to take care not to depend
on vendor-specific treatment.

<p>
Defining a COMDAT mechanism doesn't preclude using heuristics to avoid
some copies up front.
A COMDAT mechanism should also specify how to get rid of associated
sections like debugging info, unless the identical mechanism works.

<p>
<font color=blue>[990629 HP -- Christophe]</font>
First, the "usual" heuristic
(which is usual because it dates back to Cfront)
is to emit vtables in the translation unit that contains  
the definition of the first non inline, non pure virtual function.  
That is, for:
<pre><code>
        struct X {
                void a();
                virtual void f() { return; }
                virtual void g() = 0;
                virtual void h();
                virtual void i();
        };
</code></pre>
the vtable is emitted only in the TU that contains the definition of h().

<p>
This breaks and becomes non-portable if:
<ul>
<li>There is no such thing. In that case,
    you generally emit duplicate versions of vtables
<li>There is a "change of mind",
    such as having the above class followed by:
    <code><p>
    <dd>inline void X::h() { f(); }
    </code>
</ul>

<p>
Now, the COMDAT issue is as follows:
a COMDAT section is, in some cases, slightly more difficult to handle
(at least, that's the impression Jason gave me).
For statics with runtime initialization,  
what you can do is reserve COMMON space ('easier'),
then initialize that space at runtime.
As I said, the problem is if two compilers disagree on whether this
is a runtime or a compile time initialization, such as in :
<pre><code>
	int f() { return 1; }
	int x = f();	// Static (COMDAT) or Dynamic (COMMON) initialization?
</code></pre>

<p>
So I personally recommend that we put everything in COMDAT.

<p>
<font color=blue>[990715 All]</font>
Consensus so far: use a heuristic for vtable and typeinfo emission,
based on the definition of the key function.
(The first virtual function that is not
declared inline in the class definition.)
The vtable must be emitted where the key function is defined,
it may also be emitted in other translation units as well.
If there is no key function then the vtable must be emitted in any
translation unit that refers to the vtable in any way.

<p>
Implication: the linker must be prepared to discard duplicate vtables.
We want to use COMDAT sections for this
(and for other entities with vague linkage.)

<p>
Open issue: the elf format allows only 16 bits for section identifiers,
and typically two of those bits are already taken up for other things.
So we've only got 16k sections available,
which is unacceptable if we're creating lots of small sections.

<p>
Jason - COMDATs disappear into text and data at link time,
so the issue is really only serious if we've got more than 16k vtables
(or template instantiations, etc.)
in a single translation unit.

<p>
Daveed - HP has gotten around this problem by hacking their ELF files
to steal another 8 bits from somewhere else.

<p>
Jack - a new kind of section table could be a viable solution.
However, it would break everything if we did it for ia32.
Is a solution that only works on ia64 acceptable?
Note also that the elf section table has its own string table,
which we wouldn't be able to share with the new kind of section table.
Index and link fields often point into section table,
we would have to figure out how to deal with this.
(Jack is not opposed to the idea of an alternate section table,
he is just pointing out some of the issues we will have to resolve.)


<p>
<font color=blue>[990805 All]</font>
We need a specific proposed representation for COMDAT.
IBM's version is restricted to one symbol per section.
Jim will look for Microsoft's PECOFF definition.
Anyone else with a usable definition should send it.



<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=B6></a> <td> B-6 </td>
<td> Virtual function table layout </td>
<td> data </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
What is the layout of the Vtable?
</td> </tr>

</table>

<p>
<font color=blue>[990624]</font>
Issue split from A-1.

<p>
<font color=blue>[990630 HP - Christophe]</font>

<p>
Here is a short description of the virtual tables layout. This is
mostly taken out of the existing Taligent runtime.


<p>
<h4>Virtual tables</h4>

<p>
Virtual tables (vtables) are used to dispatch virtual functions, to  
access virtual base class subobjects, and to access information for  
runtime type identification (RTTI). Each class that has virtual
member functions or virtual bases has an associated set of vtables.  
The vtable pointers within all the objects (instances) of a class
point to the same set of vtables.


<p>
<h4>Vtable layout</h4>

<p>
Each vtable consists of the following parts, in the order listed.
All offsets in a vtable are of type ptrdiff_t.

<p>
"Virtual base offsets" are used to access the virtual bases of an
object and to non virtual bases when pointer adjustment is required  
for some overriden virtual function. Each entry is a displacement to  
a virtual base subobject from the location within the object of the  
vtable pointer that addresses this vtable. These entries are only
necessary if the class directly or indirectly inherits from virtual  
base classes, or if it overrides a virtual function defined in a base  
class and if  adjustment from the based to the derived class is
needed. The values can be positive or negative.

<p>
"Offset to top" holds the displacement to the top of the object from  
the location within the object of the vtable pointer that addresses  
this vtable. A negative value indicates the vtable pointer is part of  
an embedded base class subobject; otherwise it is zero. The offset
provides a way to find the top of the object from any base subobject  
with a vtable
pointer. This is necessary for dynamic_cast<void*> in particular.
The virtual pointer points to the "offset to top" field.

<p>
"Typeinfo pointer" points to the typeinfo object used for RTTI. All  
entries in each of the vtables for a given class point to the same
typeinfo object.

<p>
"Duplicate base information pointer" points to a table used to
perform runtime disambiguation of duplicate base classes for dynamic  
casts. The entries in each of the vtables for a given class do not
all point to the same table of duplicate base information.

<p>
Function pointers are used for virtual function dispatch. Each
pointer holds either the address of a virtual function of the class,  
or the address of a secondary entry point that performs certain
adjustments before transferring control to a virtual function. [To be  
discussed] In the case of shared library builds, [Solution 1] a
function pointer entry contains the address of a function descriptor,  
which contains the target GP value and the actual function address
[Solution 2] a function pointer entry contains two words: the value  
of the target GP value and the actual function address [Solution 3] a  
function pointer points to an import table generated by the dynamic  
loader, which will transfer control to the target function.

<p>
The function pointers are grouped so that the entries for all
virtual functions introduced by a base class are kept together, in
declaration order. Function pointers from a derived class immediately  
follow those for the base class. The order of function pointers
therefore depends on the static type of subobject whose vtable
pointer points to that virtual table.

<p>
A vtable pointer in an object addresses the "offset to top" field
of a vtable. This location is known as the address point of the
vtable. Note that the virtual base offsets are at negative
displacements from the address point.

<p>
The typeinfo and duplicate base information are covered in separate  
discussions.



<p>
<h4>Types of vtables</h4>

<p>
The following categories describe the rules for how vtables of a
class are constructed from the vtables of its bases.

<p>
<b>Category 1</b>

<p>
This category is for a class that inherits no base classes. If the
class declares no virtual functions, then it has no vtable, and its  
objects have no vtable pointers.

If the class declares virtual functions, then it has a single vtable  
containing RTTI fields followed by function pointer entries. There  
is one function pointer entry for each virtual function declared in  
the class. The vtable pointer in an object of the class addresses
this vtable.

<p>
<b>Category 2</b>

<p>
This category is for a class that inherits only non-virtual base
classes, and the non- virtual base classes have no base classes, and  
there is no adjustment in any of the overriden virtual functions.

<p>
If none of the base classes have vtables, a vtable is constructed
for the class according to the same rules as in Category 1. Otherwise  
the class has a vtable for each base class that has a vtable. The
class's vtables are constructed from copies of the base class
vtables. The entries are the same, except:
<ul>
<li>The RTTI fields contain information for the class, rather than
for the base class.
<p>
<li>The function pointer entries for virtual functions inherited from  
the base class and
overridden by this class are replaced with the addresses of the
overridden functions
(or the corresponding adjustor secondary entry points),
<p>
<li>At negative offsets, offsets to the base classes are generated if  
used by adjustor secondary entry points.
</ul>

<p>
Informally, each of these vtables has a name in the form
Base-in-Derived vtable, where Base is a base class and Derived is the  
derived class. Each vtable pointer in an object addresses one of
these vtables for the class. The vtable pointer of an A subobject
within a B object would address the A-in-B vtable.

<p>
The vtable copied from the primary base class is also called the
primary vtable; it is addressed by the vtable pointer at the top of  
the object. The other vtables of the class are called secondary
vtables; they are addressed by vtable pointers inside the object.


<p>
Aside from the function pointer entries that correspond to those of  
the primary base class, the primary vtable holds the following
additional entries at its tail:
- Entries for virtual functions introduced by this class
- Entries for overridden virtual functions not already in the
vtable. (These are also called replicated entries because they are
already in the secondary vtables of the class.) [I wonder if this is  
actually needed, this seems to be a consequence of RRBC]

<p>
The primary vtable, therefore, has the base class functions
appearing before the derived
class functions. The primary vtable can be viewed as two vtables
accessed from a shared
vtable pointer.


<p>
Note Another benefit of replicating virtual function entries is
that it reduces the number of this pointer adjustments during virtual  
calls. Without replication, there would be more cases where the this  
pointer would have to be adjusted to access a secondary vtable prior  
to the call. These additional cases would be exactly those where the  
function is overridden in the derived class, implying an additional  
thunk adjustment back to the original pointer. Thus replication saves  
two adjustments for each virtual call to an overridden function
introduced by a non-primary base class.


<p>
<b>Category 3</b>

<p>
This category is for a class that inherits only virtual base
classes, and the virtual base classes have no base classes.

<p>
The class has a vtable for each virtual base class that has a
vtable. These are all secondary vtables and are constructed from
copies of the base class vtables according to the same rules as in
Category 2. The vtable pointers of the virtual base subobjects within  
the object address these vtables.

<p>
The class also has a vtable that is not copied from the virtual base  
class vtables. This vtable is the primary vtable of the class and
addressed by the vtable pointer at the top of the object, which is
not shared. It holds the following function pointer entries:
<ul>
<li>
Entries for virtual functions introduced by this class
<li>
Entries for overridden virtual functions. (These are also called
replicated entries, because they are already in the secondary vtables  
of the class)
</ul>

<p>
The primary vtable also has virtual base offset entries to allow
finding the virtual base subobjects. There is one virtual base
offset entry for each virtual base class. For a class that inherits  
only virtual bases, the entries are in the reverse order in which the  
virtual bases appear in the class declaration, that is, the entry
for the leftmost virtual base is
closest to the address point of the vtable.


<p>
<b>Category 4</b>

<p>
This category is for a class that directly or indirectly inherits
base classes that are either virtual or non-virtual.

<p>
The rules for constructing vtables of the class are a combination of  
the rules from Categories 2 and 3, and for the most part can be
determined inductively. However the rules for placing virtual base
offset entries in the vtables requires elaboration.

<p>
The primary vtable has virtual base offset entries for all virtual
bases directly or indirectly inherited by the class. Each secondary  
vtable has entries only for virtual bases visible to the
corresponding base class. The entries in the primary vtable are
ordered so that entries for virtual bases visible to the primary base  
class appear below entries for virtual bases only visible to this
class.

<p>
For virtual bases only visible to this class, the entries are in the  
reverse order in which the virtual bases are encountered in a
depth-first, left-to-right traversal of the inheritance graph formed  
by the class definitions. Note
that this does not follow the order that virtual bases are placed in  
the object.



<p>
<h4>Vtables for partially constructed objects</h4>

<p>
In some situations, a special vtable, called a construction vtable
is used during the execution of base class constructors and
destructors. These vtables are for specific cases of virtual
inheritance.

<p>
During the construction of a class object, the object assumes the
type of each of its base classes, as each base class subobject is
constructed. RTTI queries in the base class constructor will return  
the type of the base class, and virtual calls will resolve to member  
functions of the base class rather than the complete class. Normally,  
this behavior is accomplished by setting, in the base class
constructor, the object's vtable pointers to the addresses of the
vtables for the base class.

<p>
However, if the base class has direct or indirect virtual bases, the  
vtable pointers have to be set to the addresses of construction
vtables. This is because the normal base class vtables may not hold  
the correct virtual base index values to access the virtual bases of  
the object under construction, and adjustment addressed by these
vtables may hold
the wrong this parameter adjustment if the adjustment is to cast
from a virtual base to another part of the object. The problem is
that a complete object of a base class and a complete object of a
derived class do not have virtual bases at the same offsets.

<p>
A construction vtable holds the virtual function addresses and the
RTTI information associated with the base class and the virtual base  
indexes and the addresses of adjustor entry points with this
parameter adjustments associated with objects of the complete class.

<p>
To ensure that the vtable pointers are set to the appropriate
vtables during base class construction, a table of vtable pointers,  
called the VTT, which holds the addresses of construction and
non-construction vtables is generated for the complete class. The
constructor for the complete class passes to each base class
constructor a pointer to the appropriate place in the VTT where the  
base class constructor can find its set of vtables. Construction
vtables are used in a similar way during the execution of base class  
destructors.


<p>
<font color=blue>[990701 All]</font>
The above arrived to late for everyone to read it carefully.
It was agreed that we would consider it outside the meetings,
discuss any issues noted by email,
and attempt to close on 22 July.
(Christophe is on vacation until that week,
and Daveed leaves on vacation the next week.)

<p>
<font color=blue>[990811 SGI -- Jim]</font>
I've put a reworked version of Christophe's writeup in the
<a href=abi-layout.html#vtable>data layout document</a>,
along with a number of questions it raises.

<p>
<font color=blue>[990812 All]</font>
Extensive discussion of this issue produced the observations that
<ul>
<li> The number of virtual base offsets changes for vtables
    embedded in derived vtables.
<li> Therefore, one cannot reference one by a compile-time-constant
    offset from another (within the set associated with a type).
<li> Therefore, one cannot omit vfunc pointers from a derived vtable
    just because they appear in one of the base class vtables.
</ul>
Christophe will look at the implications of these observations.
Others should too.


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=B7></a> <td> B-7 </td>
<td> Objects and Vtables in shared memory </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990624 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Is it possible to allocate objects in shared memory?
For polymorphic objects, this implies that the Vtable must also be
in shared memory.
</td> </tr>
<tr> <td colspan=7>
<b> Resolution </b>:
No special representation is useful in support of shared memory.
</td> </tr>

</table>


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=B8></a> <td> B-8 </td>
<td> dynamic_cast </td>
<td> data </td>
<td> open </td>
<td> SGI </td>
<td> 990628 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
What information to we put in the vtable to enable (a) dynamic_cast
from pointer-to-base to pointer-to-derived (including detection of
ambiguous base classes) and (b) dynamic_cast to void*?
</td> </tr>

</table>

<p>
<font color=blue>[990701 All]</font>
This should be part of the proposal Daveed will put together
by the 15th (action #13); the group will discuss it on the 22nd.

<p>
<font color=blue>[990812 Sun -- Michael]</font>
Sun has provided a description,
<a href=Sun-RTTI-990812.html>in a separate page</a>,
describing their implementation.
They are filing for a patent on the algorithms described.


<p> <hr> <p>
<h3> Object Construction/Destruction Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=C1></a> <td> C-1 </td>
<td> Interaction with .init/.fini </td>
<td> lif ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Static objects with dynamic constructors must be constructed at
intialization time.
This is done via the executable object initialization functions that
are identified (in ELF) by the DT_INIT and DT_INITARRAY dynamic tags.
How should the compiler identify the constructors to be called in this way?
One traditional mechanism is to put calls in a .init section.
Another, used by HP, is to put function addresses in a .initarray section.
<p>
The dual question arises for static object destructors.
Again, the extant mechanisms include putting calls in a .fini section,
or putting function addresses in a .finiarray section.
<p>
Finally, which mechanism (DT_INIT or DT_INITARRAY, or the FINI versions)
should be used in linked objects?
The gABI, and the IA-64 psABI, will support both,
with DT_INIT being executed before the DT_INITARRAY elements.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=C2></a> <td> C-2 </td>
<td> Order of ctors/dtors w.r.t. link </td>
<td> lif ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Given that the compiler has identified constructor/destructor calls for
static objects in each relocatable object, in what order should the
static linker combine them in the linked executable object?
(The initialization order determines the finalization order,
as its opposite.)
</td> </tr>

</table>

<p>
<font color=blue>[990610 All]</font>
Meeting concensus is that the desirable order is right to left on the
link command line, i.e. last listed relocatable object is initialized
first.

<p>
<font color=blue>[990701 SGI]</font>
We propose that global constructors be handled as follows:
<ul>
<p>
<li>
The compiler shall emit global constructor calls as one or more entries
in an SHF_INIT_ARRAY section.
<p>
<li>
The linker shall combine them according to the rules of the base gABI,
namely as a concatenated array of entries, in link argument order,
pointed to by a DT_INIT_ARRAY tag.
(The linker may intersperse entries from command line flags or modules
from other languages, but that is beyond the C++ ABI scope.)
</ul>

<p>
This does not address the global destructor problem.
That solution needs to deal not only with the global objects seen by
the compiler, but also interspersed local static objects.
This treatment seems to be tied up in the question of how early
unloading of DSOs is handled, and the data structure used for that
purpose (issue C-3).

<p>
<font color=blue>[990715 All]</font>
Cygnus scheme:
priorities are 16-bit unsigned integers, lower numbers are higher priority.
In each translation unit,
there's a single initialization function for each priority.
Anything that's prioritized has a higher priority than anything that
isn't explicitly assigned a priority.

<p>
IBM scheme:
priorities are 32-bit signed integers, higher numbers are higher priority.
Something that isn't explicitly assigned a priority effectively
gets a priority of 0.

<p>
Consensus:
nobody is sure that negative priorities are very important,
but also nobody can think of a reason not to allow them.
We accept the idea that priorities are 32-bit signed integers.
On a source level Cygnus will keep lower numbers as higher priority,
but that's a source issue, not an ABI issue.

<p>
Status: No real technical issues,
we have consensus on everything that matters.
We need to write up the finicky details.

<p>
<font color=blue>[990722 all]</font>
It was decided to follow the IBM approach, including:
<ul>
<li> The source pragma will use a 32-bit signed priority.
	The default will map to 0,
	and larger numbers are lower priority.

<li> Priorities MIN_INT .. MIN_INT+1000 are reserved to the implementation.

<li> The object representation will use a 32-bit unsigned priority,
	obtained from the source priority by subtracting INT_MIN.

<li> Initialization priorities are only relevant within a DSO.
	Between DSOs, the normal ELF ordering based on object order applies.

</ul>

<p>
To be resolved are the precise source pragma definition (possibly IBM's),
and the ELF file representation.

<p>
<font color=blue>[990729 all]</font>
SGI suggested an object representation involving (in relocatables)
a new section type, containing pairs &lt;priority, entry address>.
The linker would merge all such sections,
include any initialization entries specified by other means,
and leave one or more DT_INITARRAY entries for normal runtime
initialization, either building a routine to call the entries,
or referencing a standard runtime routine.

<p>
IBM noted that they combine their equivalent data structures in the
linker, but don't sort them, leaving that to a runtime routine.
This can be done without explicit linker support,
but involves runtime overhead.

<p>
Cygnus suggested that if we are going to require linker sorting,
we should make the facility more general.

<p>
Jim will write up a more precise proposal.

<p>
<font color=blue>[990804 SGI -- Jim]</font>
<h4> Proposal </h4>

<p>
My objectives are:
<ul>
<li> Simple representation in relocatable objects.
<li> No new representation in executable objects.
<li> Simple static linker processing (general if possible).
<li> Minimal unnecessary runtime cost.
<li> Minimal library interface.
<li> Integration with other initialization (at source priority zero).
</ul>

<p>
<h5> Object File Representation </h5>

<p>
Define a new section type, e.g. <code><b>SHT_CXX_PRIORITY_INIT</b></code>.
Its elements are structs:
<code><pre>
	typedef struct {
	  ElfXX_Word	pi_pri;
	  ElfXX_Addr	pi_addr;
	} ElfXX_Cxx_Priority_Init;
</pre></code>
The semantics are that <code>pi_addr</code> is a function pointer,
with an <code>unsigned int</code> priority parameter,
which performs some initialization at priority <code>pi_pri</code>.
Each of these functions will be called with the GP of the
executable object containing the table.
The section header field <code>sh_entsize</code> is 8 for ELF-32,
or 16 for ELF-64.

<p>
<h5> Runtime Library Support </h5>

<p>
Each implementation shall provide a runtime library function with
prototype:
<code><center>
void __cxx_priority_init ( ElfXX_Cxx_Priority_Init *pi, int cnt );
</center></code>
It will be called with the address of a <code>cnt</code>-element
(sub-)vector of the priority initialization entries,
and will call each of them in order.
It will be called with the GP of the initialization entries.

<p>
<h5> Linker Processing </h5>

<p>
The linker must take the collection of SHT_CXX_PRIORITY_INIT section
entries from the relocatable object files being linked,
and other initialization tasks specified in other ways
(and treated as source priority 0 or object priority -MIN_INT),
and produce an executable object file which executes the initialization
tasks in priority order using only <code>DT_INIT</code>,
<code>DT_INIT_ARRAY</code>, and <code>__cxx_priority_init</code>.
Priority order is first according to the priority of the task,
and then according to the order of relocatable objects and options
in the link command.
The order of tasks specified by other methods,
relative to SHT_CXX_PRIORITY_INIT tasks of priority zero,
is implementation defined.
There are several possible implementations.  Two extremes are:

<ul>
<p>
<li>
The linker sorts the SHT_CXX_PRIORITY_INIT sections together.
If it inserts entries for initialization tasks specified in other ways,
it may make a single DT_INIT_ARRAY entry pointing to __cxx_priority_init.
If not, it must break it into subranges,
interspersing DT_INIT_ARRAY entries for the other tasks with entries
for the SHT_CXX_PRIORITY_INIT entries.
(This implementation will minimize runtime overhead.)

<p>
<li>
The linker simply appends the SHT_CXX_PRIORITY_INIT sections.
It inserts DT_INIT_ARRAY entries before and after the entries for other
initialization tasks which sort this vector and then execute the
negative-priority calls on the first call,
and the positive-priority ones on the second call.
(I believe this is much like today's IBM implementation.)
However, to be conforming, the routine which performs these tasks
must be linked with the resulting executable object,
or shippable with it as an associated DSO.

</ul>

<p>
Note that if one is linking ELF-32 objects into a 64-bit program,
the entries must be expanded as part of this process.

<p>
<h5> Sorting Sections </h5>

<p>
Jason suggested that if we base this feature on sorting sections,
we should provide a general mechanism.
Following is a proposal for that purpose.

<p>
Define a new section header flag, <code>SHF_SORT</code>.
If present, the linker is required to sort the elements of the
concatenated sections of the same type,
where the elements are determined by <code>sh_entsize</code>.
The sort is controlled by fields in <code>sh_info</code>:

<dl>
<p>
<dt> <code>#define SH_INFO_KEYSIZE(info) (info & 0xff)</code>
<br><dd>	The size of the sort key (bytes).
<p>
<dt> <code>#define SH_INFO_KEYSTART(info) ((info>>8) & 0xff)</code>
<br><dd>	The start byte of the sort key within element, from 0.
<p>
<dt> <code>#define SH_INFO_SORTKIND(info) ((info>>16) & 0xf)</code>
<br><dd>	The kind of sort data:
		0 for unsigned integer, 1 for signed integer.

</dl>

<p>
The sort must be stable.
The sort key must be naturally aligned.

<p>
Other conceivable options would be to allow sorting strings
(like SHF_MERGE, this would be indicated by setting SHF_STRING
and putting the character size in <code>sh_entsize</code>),
or floating point data.
Also, note that if we don't anticipate using such a general mechanism,
it becomes possible to avoid padding words in the ELF-64 format by
separating the priority and address vectors.

<p>
<font color=blue>[990810 HU-B -- Martin]</font>
Global destructor ordering must not only interleave with static locals,
but also with atexit.
This gives two problems:
atexit is only guaranteed to support 32 functions;
and dynamic unloading of DSOs break when functions are atexit registered.

<p>
<font color=blue>[990810 SGI -- Matt]</font>
Yes, the interleaving is required by the C++ standard.
It's a nuisance, and I don't think there's any good reason for it,
but the requirement is quite explicit.

<p>
The relevant part of the C++ standard is section 3.6.3, paragraph 3:

<p>
<dl><dd>
<cite>
"If a function is registered with atexit (see <cstdlib>, 18.3) then
following the call to exit, any objects with static storage duration
initialized prior to the registration of that function shall not be
destroyed until the registered function is called from the termination
process and has completed. For an object with static storage duration
constructed after a function is registered with atexit, then following
the call to exit, the registered function is not called until the
execution of the object's destructor has completed. If atexit is called
during the construction of an object, the complete object to which it
belongs shall be destroyed before the registered function is called."
</cite>
</dd></dl>

<p>
What this implies to me is that atexit, and the part of the runtime
library that handles destructors for static objects, must know about
each other.

<p>
<font color=blue>[990812 All]</font>
Some people would prefer a sorting scheme based on the section name
instead of the data, and also less linker impact.
Jim will look into alternatives.


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=C3></a> <td> C-3 </td>
<td> Order of ctors/dtors w.r.t. DSOs </td>
<td> ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Given the constructor/destructor calls for each executable object
comprising a program, what is the order of execution between objects?
For constructors, there is not much question:
unless we choose some explicit means of control,
file-scope objects will be initialized by the DT_INIT/DT_INITARRAY
functions in the order determined by the base ABI order rules,
and local objects will be initialized in the order their containing
scopes are entered.
<p>
For destructors, the Standard requires opposite-order destruction,
which implies a runtime structure to keep track of the order.
Furthermore, the potential for dynamic unloading of a DSO
(e.g. by dlclose)
requires a mechanism for early destruction of a subset.
</td> </tr>

</table>

<p>
<font color=blue>[990804 SGI -- Jim]</font>
<h4> Proposal </h4>

<p>
My objectives are:
<ul>
<li> Simple library interface.
<li> Efficient handling during construction.
<li> Standard-conforming treatment during normal program exit.
<li> Reasonable treatment during early DSO unload (e.g. dlclose).
<li> Minimal dynamic and static linker impact.
</ul>

<p>
<h5> Runtime Data Structure </h5>

<p>
The runtime library shall maintain a list of termination functions
with the following information about each:

<ul>
<li> A function pointer (a pointer to a function descriptor on IA-64).
<li> A void* operand to be passed to the function.
<li> A void* handle for the <i>home DSO</i> of the entry (below).
</ul>

<p>
The representation of this structure is implementation defined.
All references are via the API described below.

<p>
<h5> Runtime API </h5>

<ol type=A>
<p>
<li> Object construction:
<p>
When a global or local static object is constructed,
which will require destruction on exit,
a termination function is <i>registered</i> as follows:
<center><code>
int __cxx_atexit ( void (*f)(void *), void *p, dso_handle d );
</code></center>
This registration, e.g. <code>__cxx_atexit(f,p,d)</code>,
is intended to cause the call <code>f(p)</code> when DSO d is unloaded,
before all such termination calls registered before this one.
It returns zero if registration is successful, nonzero on failure.
<font color=red>Should we use exceptions instead?</font>

<p>
The registration function is called separate from the constructor.

<p>
<li> User atexit calls:
<p>
When the user registers exit functions with <code>atexit</code>,
they should be registered with NULL parameter and DSO handle, i.e.
<center><code>
__cxx_atexit ( f, NULL, NULL );
</code></center>
<font color=red>
Should we also allow user registration with a parameter?
With a home DSO?
</font>

<p>
<li> Termination:
<p>
When linking any DSO containing a call to <code>__cxx_atexit</code>,
the linker should define a hidden symbol <code>__dso_handle</code>,
with a value which is an address in one of the object's segments.
(It doesn't matter what address,
as long as they are different in different DSOs.)
It should also include a call to the following function in the FINI
list (to be executed first):
<center><code>
void __cxx_finalize ( dso_handle d );
</code></center>
The parameter passed should be <code>__dso_handle</code>.

<p>
Note that the above can be accomplished either by explicitly providing
the symbol and call in the linker, or by implicitly including a
relocatable object in the link with the necessary definitions,
using a .fini_array section for the FINI call.
Also, note that these can be omitted for an object with no calls to
<code>__cxx_atexit</code>, but they can be safely included in all objects.

<p>
Finally, a main program should be linked with a FINI call to
<code>__cxx_finalize</code> with NULL parameter.

<p>
When <code>__cxx_finalize(d)</code> is called,
it should walk the termination function list,
calling each in turn if <code>d</code> matches
<code>__dso_handle</code> for the termination function entry.
If <code>d == NULL</code>, it should call all of them.
Multiple calls to <code>__cxx_finalize</code> should not result in
calling termination function entries multiple times;
the implementation may either remove entries or mark them finished.

<p>
<font color=red>
Issue: By passing a NULL-terminated vector of DSO handles to
<code>__cxx_finalize</code> instead of one,
we could deal with unloading multiple DSOs at once.
However, <code>dlclose</code> closes one at a time,
so I'm not sure the extra complexity is worthwhile.
</font>

</ol>

<p>
Since <code>__cxx_atexit</code> and <code>__cxx_finalize</code>
must both manipulate the same termination function list,
they must be defined in the implementation's C++ runtime library,
rather than in the individual linked objects.




<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=C4></a> <td> C-4 </td>
<td> Calling vfuncs in ctors/dtors </td>
<td> call </td>
<td> open </td>
<td> Cygnus </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
When calling a virtual function from the constructor/destructor of a
base subobject,
the version specific to the base type is required,
unlike the typical case when calling such a vfunc for the full object
from some other context.
Since the pointer for that vfunc in the full object's vtable
(or even the subobject's sub-vtable) is the full object version,
some other means is required for accessing the correct vfunc.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=C5></a> <td> C-5 </td>
<td> Calling destructors </td>
<td> call </td>
<td> open </td>
<td> Sun </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
What is the calling convention for destructors?
Do virtual destructors require special treatment?
Is delete() integrated with the destructor call or separate?
How is delete() handled when invoked on a base subobject?
</td> </tr>

</table>

<p>
<font color=blue>[990729 all]</font>
Some implementations combine destructors with deletion,
checking a flag in the destructor to determine whether to delete.
This produces somewhat less code,
especially if there are many delete() calls.
However, it adds overhead to any destructor which does not require
deletion, e.g. base and member objects, automatic objects.
There is some concern that a runtime test is sometimes required,
but noone has yet identified why.


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=C6></a> <td> C-6 </td>
<td> Extra parameters to ctors/dtors </td>
<td> call </td>
<td> open </td>
<td> Cygnus </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
When calling constructors and destructors for classes with virtual bases,
information about the virtual base subobjects in the full class
must be transmitted somehow to the ctor/dtor.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=C7></a> <td> C-7 </td>
<td> Passing value parameters by reference </td>
<td> call </td>
<td> closed </td>
<td> All </td>
<td> 990624 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
It may be desirable in some cases where a type has a non-trivial
copy constructor to pass value parameters of that type by performing
the copy at the call site and passing a reference.
</td> </tr>
<tr> <td colspan=7>
<b> Resolution </b>:
Whenever a class type has a non-trivial copy constructor,
pass value parameters of that type by performing
the copy at the call site and passing a reference.
</td> </tr>

</table>


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=C8></a> <td> C-8 </td>
<td> Returning classes with non-trival copy constructors </td>
<td> call </td>
<td> closed </td>
<td> All </td>
<td> 990625 </td>
<td> 990722 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
How do we return classes with non-trivial copy constructors?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
The caller allocates space,
and passes a pointer as an implicit first parameter
(prior to the implicit <i>this</i> parameter).
</td> </tr>

</table>

<p> <hr> <p>
<h3> Exception Handling Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=D1></a> <td> D-1 </td>
<td> Language-specific data area format </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The IA-64 runtime conventions describe language-independent descriptors
for restoring registers when unwinding the stack.
The do not specify how C++ performs language-specific unwinding for
exception handling, i.e. locating a handler and destroying automatic
objects.
Note that this can be handled by agreeing on common descriptors,
or by agreeing on per-frame personality routines with common APIs.
</td> </tr>

</table>

<p>
<font color=blue>[990715 Cygnus -- Jason]</font>
The languge-specific part of the EH stack in g++ contains these
elements:

<p>
<code><pre>
void *value; // pointer to the thrown object, or the thrown value
             // itself if a pointer
void *type;  // pointer to the type_info node for the thrown object
void (*cleanup)(void *, int) // pointer to the dtor for the object
bool caught; // has this exception been caught since its last throw?
long handlers; // how many catch handlers are active for this exception
</code></pre>

<p>
Both 'caught' and 'handlers' are needed to handle rethrowing and
catching within a catch block.

<p>
Language interaction is handled by recording the language of both the
exception region and the thrown exception.  Each thrown exception also
includes a pointer to a language-specific matching function which is
called to compare the types of the exception and handler.


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=D2></a> <td> D-2 </td>
<td> Unwind personality routines </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The IA-64 runtime conventions provide for a personality routine
pointer for language-specific actions when unwinding the stack.
They do not specify its interface.
There are typically two required actions for C++:
locating a handler (non-destructively)
and destroying automatic objects while unwinding.
This issue involves specification of the API (see also D-3).
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=D3></a> <td> D-3 </td>
<td> Unwind process clarification </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The IA-64 runtime conventions provide for a personality routine
pointer for language-specific actions when unwinding the stack.
However, they are quite muddy about the precise sequence of calls.
This issue involves specification of unwind process (see also D-2).
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=D4></a> <td> D-4 </td>
<td> Unwind routines nested? </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The IA-64 runtime conventions call for the unwind personality routine
to behave like a routine nested in the routine raising an exception.
Is that the preferred definition?
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=D5></a> <td> D-5 </td>
<td> Interaction with other languages (e.g. Java) </td>
<td> lib ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The IA64 exceptions handling framework is largely language independent.
What is the behaviour of a C++ runtime receiving, for instance,
an exception thrown from Java?
Does it call terminate()?
Does it allow the exception to pass through C++ code with destructors
if there is no catch clause?
Does it allow the exception to be caught in a catch(...) provided this
catch(...) ends with a rethrow?
Does it allow even more?
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=D6></a> <td> D-6 </td>
<td> Allow resumption in other languages? </td>
<td> lib ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The exception handling framework requires the interaction of the
runtime of all the languages "on the stack" during exception processing.
Some of these languages may have very different exception handling semantics.
What are the constraints we impose on the C++ exception handling runtime
to preserve the relative language neutrality of the EH framework?
Example: do we allow a handler to cleanup and resume at the point
where the exception was thrown?
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=D7></a> <td> D-7 </td>
<td> Interaction with signals or asynch events </td>
<td> lib ps </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The Standard says that the behavior of anything other than
"pure C code" (POF) is implementation defined,
and warns (in a note) against using EH in a signal handler.
We should define what is supported,
possibly explicitly stating that signal handler code must be a POF.
We could allow any feature but exception handling to be used.
We could allow some EH routines to be called
(for instance, <code>uncaught_exception()</code>).
Or we could allow even an exception to be thrown,
if it does not exit the handler.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=D8></a> <td> D-8 </td>
<td> Interaction with threads packages </td>
<td> lib ps </td>
<td> open </td>
<td> SGI </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
What happens when an exception is not caught in the thread where raised?
What does uncaught_exception() return if another thread is currently
processing an exception?
</td> </tr>

</table>

<p> <hr> <p>
<h3> Template Instantiation Model Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>


<tr> </tr>
<tr> <th> E </th>
<th colspan=6> Template Instantiation Model </th>
</tr>

<tr> <a name=E1></a> <td> E-1 </td>
<td> When does instantiation occur? </td>
<td> tools </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
There are two principal models for instantiation.
The <i>early instantiation</i> (or Borland) model performs all
instantiation at compile time,
potentially resulting in extra copies which are removed at link time.
The <i>pre-link instantiation</i> model identifies the required
instantiations prior to linking and instantiates them via a special
compile step.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=E2></a> <td> E-2 </td>
<td> Separate compilation model </td>
<td> tools </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
[SGI]
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=E3></a> <td> E-3 </td>
<td> Template repository </td>
<td> tools </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Independent of the template instantiation model,
we need to make sure that whatever template persistent storage is used
by one vendor does not interact negatively with other vendors' mechanisms.
Issues:
  (1) Avoiding conflict on the name of any repository.
  (2) If .o files are used,
	describe how this information is to be preserved, ignored, etc.
  (3) Evaluate if tools such as make, ld, ar, or others, can
	break because .o files get written at unexpected times.
</td> </tr>

</table>

<p> <hr> <p>
<h3> Name Mangling Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=F1></a> <td> F-1 </td>
<td> Mangling convention </td>
<td> call </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
What rules shall be used for mangling names,
i.e. for encoding the information other than the source-level object
name necessary to resolve overloading?
</td> </tr>

</table>

<p>
<font color=blue>[990806 SGI -- Jim]</font>
Naming to be resolved under this issue includes:
<ul>
<li> Global and member operator names
<li> Global and member function names
<li> Vtable names (primary and initialization)
<li> RTTI struct names
<li> Template instance names
<li> Namespace effects
</ul>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=F2></a> <td> F-2 </td>
<td> Mangled name size </td>
<td> call g </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Typical name mangling schemes to date typically begin to produce very
long names.  SGI routinely encounters multi-kilobyte names,
and increasing usage of namespaces and templates will make them worse.
This has a negative impact on object file size, and on linker speed.
<p>
SGI has considered solutions to this problem including modified string
tables and/or symbol tables to eliminate redundancy.
Cygnus, HP, and Sun have also considered or implemented approaches
which at least mitigate it.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=F3></a> <td> F-3 </td>
<td> Distinguish template instantiation and specialization
</td>
<td> call g </td>
<td> open </td>
<td> SGI </td>
<td> 990520 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
In order to allow detection of conflicting template instantiation
and specialization (in different translation units),
should we name them differently?
If we do so in an easily recognizable way,
the linker could check for conflicts and report the ODR violation.
</td> </tr>

</table>

<p> <hr> <p>
<h3> Miscellaneous Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=G1></a> <td> G-1 </td>
<td> Basic command line options </td>
<td> tools </td>
<td> open </td>
<td> HP </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Can we agree on basic command line options (compiler and linker)
for fundamental functionality,
possibly allowing portable makefiles?
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=G2></a> <td> G-2 </td>
<td> Detection of ODR violations </td>
<td> call </td>
<td> open </td>
<td> Sun </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
[Sun]
(See also F-3.)
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=G3></a> <td> G-3 </td>
<td> Inlined routine linkage </td>
<td> call </td>
<td> open </td>
<td> Sun </td>
<td> 990603 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Inline routines with external linkage require a method of handling
vague linkage (see B-5 for definition) for the out-of-line instance,
as well as for any static data they contain.
The latter includes string constants per [7.1.2]/4.
</td> </tr>

</table>

<p>
<font color=blue>[990624 Cygnus -- Jason]</font>
How should we handle local static variables in inlines?
G++ currently avoids this issue by suppressing
inlining of functions with local statics.
If we don't want to do that,
we'll need to specify a mangling for the statics,
and handle multiple copies like we do above.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=G4></a> <td> G-4 </td>
<td> Dynamic init of local static objects and multithreading </td>
<td> call </td>
<td> open </td>
<td> SCO </td>
<td> 990607 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The Standard requires that local static objects with dynamic
constructors be initialized exactly once, the first time the containing
scope is entered.
Multi-threading renders the simple check of a flag before
initialization inadequate to prevent multiple initialization.
Should the ABI require locking for this purpose,
and if so, what are the necessary interfaces?
In addition to the locking of the initialization,
special exception handling treatment is required to deal with an
exception during construction.
</td> </tr>

</table>

<p>
<font color=blue>[990607 SCO -- Jonathan]</font>
The standard is mute on multiple threads of control in general, so 
there is no requirement in the language to support what I'm talking
about. But as a practical matter compilers have to do it (Watcom gave
a paper on their approach during the standardization process, if I
remember).  This example using UI/SVR4 threads will usually show
whether a compiler does it or not: 

<pre><code>
thr5.C:
// static local initialization and threads

#include <stdlib.h>
#define EXIT(a) exit(a)
#define THR_EXIT() thr_exit(0)

#include <thread.h>

int init_count = 0;
int start_count = 0;

int init()
{
  
        ::thr_yield();
        return ++init_count;
}

void* start(void* s)
{
  
        start_count++;
        static int i = init();
        if (i != 1) EXIT(5);
        THR_EXIT();
        return 0;
}
                
int main()
{
  
        thread_t t1, t2;
        if (::thr_create(0, 0, start, 0, 0L, &t1) != 0) EXIT(1);
        if (::thr_create(0, 0, start, 0, 0L, &t2) != 0) EXIT(2);
        if (::thr_join(t1, 0, 0) != 0) EXIT(3);
        if (::thr_join(t2, 0, 0) != 0) EXIT(4);
        if (start_count != 2)
                EXIT(6);
        if (init_count != 1)
                EXIT(7);
        THR_EXIT();
}
</code></pre>

<p>
When compiled with CC -Kthread thr5.C on UnixWare 7, for instance,
it passes by returning 0.  When compiled with CC -mt thr5.C on
Solaris/x86 C++ 4.2 (sorry don't have the latest version!), it
fails by returning 5.


<p>
<font color=blue>[990607 Sun -- Mike Ball]</font>
As far as I can tell, the language says that the automatic blocking 
issue isn't a valid approach.  It says what has to happen, and
it isn't that.

<p>
If you look at the entire statement you find that it reads:
<quote>
"Otherwise such an object is initialized the first time control passes
through its declaration; such an object is considered initialized upon
the completion of its initialization.
If the initialization exits by throwing an exception,
the initialization is not complete,
so it will be tried again the next time control enters the declaration.
If control re-enters the declaration (recursively)
while the object is being initialized,
the behavior is undefined."
</quote>

<p>
The word "recursively" is normative,
so eliminates that sentence from consideration.

<p>
One can, of course, make any extension to the language,
but in this case I think the extension invalidates some otherwise valid code.

<p>
The sentence I'm referring to is that the object is considered
initialized upon the completion of its initialization.
This is explicit, and the reason for it is covered in the following sentence,
which discusses an initialization that terminates with an exception.
A person catching such an exception has the right to try again
without danger that the static variable will be initialized in the meantime.

<p>
I don't see anything at all to justify semantics that say,
"after initialization is started, Any other threads of control are
blocked until that thread completes the initialization,
unless, of course, it executes by an exception,
in which case the other thread can do the initialization before the
exception handler gets a chance to try again, except...."
 Take an attempt to define the semantics as far as you like.

<p>
The problem is that there is no way for the compiler writer to know
what the programmer really wanted to do.
I can (and will at some other date, if necessary)
come up with scenarios justifying a variety of mutual exclusion policies,
including none.

<p>
The solution is to let the programmer write the mutual exclusion, the
same as we do for every other potential race condition.
It's a real mess, and, I claim, an unwise one to put in as an extension.

<p>
<font color=blue>[990608 HP -- Christophe]</font>
The semantics currently implemented in the HP aC++ compiler is as follows:
<ul>
<li> No two thread can enter a static initialization at the same time
<li> Threads are blocked until immediately after the static  
    initialization either succeeds or fails with an exception.
</ul>

<p>
There are details of our implementation that I disagree with, but in  
general, the semantics seem clear and sane, not as convoluted as you  
seemed to imply. In particular, it correctly covers the case where  
the static initialization fails with an exception. Any thread at that  
point can attempt the initialization.

<p>
<font color=blue>[990608 SCO -- Jonathan]</font>
Here's what the SCO UnixWare 7 C++ compiler does for IA-32,
from a (slightly sanitized) design document.
 It meets Jim's goal of having no overhead for non-threaded programs
and minimal overhead for threaded programs unless
actual contention occurs (infrequent),
and meets Mike's goal of handling exceptions in the initialization correctly
(although it doesn't guarantee that the thread getting the exception is
the one that gets next crack at initializing the static).
 It's also worth noting that dynamic initialization of local variables
(static or otherwise) is very common in C++,
since that's what most object constructions involve,
so I don't think this case is as rare as Jim does.


<p>
[...] This is in local static variables with dynamic initialization,
where the compiler generates out a static one-time flag to guard the
initialization.
Two threads could read the flag as zero before either of them set it,
resulting in multiple initializations.

<p>
[...] Accordingly, when compilation is done with -Kthread on,
a code sequence will be generated to lock this initialization.  
[...] the basic idea is to have one guard saying whether the
initialization is done (so that multiple initializations do not occur)
and have another guard saying whether initialization is in progress
(so that a second thread doesn't access what it thinks is
an initialized value before the first thread has finished the
initialization).  [...]

<p>
When compiled with -Kthread, the generated code for a dynamic
initialization of a local static variable will look like the
following. guard is a local static boolean, initialized to zero,
generated by the [middle pass of the compiler]. 
Two bits of it are used: the low-order 'done bit'
and the next-low-order 'busy bit'.

<pre><code>
.again:
        movl    $guard,%eax
        testl   $1,(%eax)       // test the done bit
        jnz     .done           // if set, variable is initialized,
done
        lock; btsl  $1,(%eax)   // test and set the busy bit
        jc      .busy
        < init code >           // not busy, do the initialization
        movl    $guard,%eax
        movl    $3,(%eax)       // set the done bit
        jmp     .done
.busy:
        pushl   %eax            // call RTS routine to wait, passing address
        call1   __static_init_wait      // of guard to monitor
        testl   %eax,%eax       // 1 means exception occurred in init code,
        popl    %ecx
        jnz     .again                  // start the whole thing over
.done                                   // 0 means wait finished
</code></pre>

<p>
The above code will work for position-independent code as well.

The complication due to exceptions is:
what happens if the initialization code throws an exception?
The [compiler] EH tables will have set up a special region and flag in
their region table to detect this situation,
along with a pointer to the guard variable.
Because the initialization never completed,
when the RTS sees that it is cleaning up from such a region,
it will reset the guard variable back to both zeroes.
This will free up a busy-waiting thread, if any,
or will reset everything for the next thread that calls the function.

<p>
The idea of the __static_init_wait() RTS routine is to monitor the
value of guard bits passed in, by looping on this decision table:
<pre><code>
    done    busy
    0       0       return 1 in %eax        (EH wipe-out)
    1       1       return 0 in %eax        (no longer busy)
    0       1       continue to wait        (still busy)
    1       0       internal error, shouldn't happen
</code></pre>

<p>
As for how the wait is done [... not relevant for ABI,
although currently we're using thr_yield(),
which may or may not be right for this context].

<p>
<font color=blue>[990608 SGI -- Hans]</font>
I'd like to make some claims about function scope static constructor
calls in multithreaded environments.
I personally can't recall ever having used such a construct,
which somewhat substantiates my claims,
but also implies some lack of certainty.
I'd be interested in hearing any arguments to the contrary.

<p>
I believe that these arguments imply that this problem is not important
enough to warrant added ABI complexity or overhead for sequential code.

<p>
Consider the following skeletal example:

<p><code>
f(int x) { static foo a(...); ... }
</code>

<ol>
<p>
<li>
If the constructor argument doesn't depend on the function parameter,
and the code behaves reasonably, it should be possible to rewrite this as

<p><code>
static foo a(...);
<br>
f(int x) { ... }
</code>

<p>
<li>
If I read the standard correctly (and that's a big disclaimer),
the compiler is entitled to perform the above transformation under
conditions that are usually true,
but hard for the compiler to deduce.
Thus code that relies on the initialization occurring during the
execution of f is usually broken.

<p>
<li>
Thus the foo constructor cannot rely on its caller holding any locks.
It must explicitly acquire any locks it needs.

<p>
<li>
It is far preferable to write the transformed form with a file scope
static variable to start with.
The initial form risks deadlock,
since f may be called with locks held which the constructor
can't assume are held.
If it needs one of those locks it will need to reacquire it.
With default mutex semantics that results in deadlock with itself.
(If locks may be reentered,
it may fail in a more subtle manner since the foo constructor may
acquire a monitor lock whose monitor invariant doesn't hold.)

<p>
<li>
File scope static constructor calls aren't a problem and require no locking,
since they are executed in a single thread before main is called or
before dlopen returns.
(Forking a thread in a static constructor should probably be disallowed.
Threads may not have been fully initialized, among other issues.)

<p>
<li>
Static function scope constructor calls which depend on function
arguments are likely to involve a race condition anyway,
if multiple instances of the function can be invoked concurrently.
Any of the calls might determine the constructor parameters.
Thus these aren't very interesting either.
And if they are really needed, they can be replaced with a file scope
static constructor call plus an assignment.

</ol>


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr class=small> <a name=G5></a> <td> G-5 </td>
<td> Varargs routine interface </td>
<td> call </td>
<td> open </td>
<td> HU-B </td>
<td> 990810 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The underlying C ABI defines conventions for calling varargs routines.
Does C++ need, or would it benefit from, any modifications or special cases?
How should we pass references or class objects?
Is any runtime library support required?
</td> </tr>

</table>

<p>
<font color=blue>[990810 HU-B Martin]</font>
I'd like to see an indirection in vararg lists,
so they can be passed through thunks.
This is necessary at least for the covariant returns,
but might have other applications as well.

<p>
<font color=blue>[990810 HU-B Martin]</font>
Since there already was the decision not to return a list of
pointers from a covariant method,
the only alternative to real thunks
is code duplication (as done in Sun Workshop 5).
<i>(Or alternate entrypoints...  Jim)</i>

<p>
With real thunks, you have to copy the argument list.
That is not possible for a varargs list,
so here is my proposal for varargs in C++:

<p>
In the place of the ellipsis, a pointer to the first argument is passed.
In case of a thunk for covariant returns,
this pointer can be copied to the destination function.
The variable arguments are put on the stack as they normally would.

<p>
With that, the issue is in which cases to use such a calling
convention:
<ol>
<li> only for vararg calls to virtual methods, or
<li> only for vararg calls to functions with C++ linkage, or
<li> for all vararg calls.
     That would probably require a change to the C ABI
</ol>
<p>
Option (1) could be further restricted to methods returning a pointer
or reference to class type. 

<p>
<font color=blue>[990812 All]</font>
In response to a question,
it was observed that passing one variant of a class hierarchy in a
varargs list and referencing another variant in the va_arg macro is undefined,
and we don't need to worry about a mechanism for doing the conversion.





<p> <hr> <p>
<h3> Library Interface Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=H1></a> <td> H-1 </td>
<td> Runtime library DSO name </td>
<td> tools </td>
<td> open </td>
<td> SGI </td>
<td> 990616 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Determine the name of the common C++ runtime library DSO,
e.g. <code>libC.so</code>.
If there are to be vendor-specific support libraries which must coexist
in programs from mixed sources, identify naming convention for them.
</td> </tr>

</table>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=H2></a> <td> H-2 </td>
<td> Runtime library API </td>
<td> lif </td>
<td> open </td>
<td> SGI </td>
<td> 990616 </td>
<td> </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Define the required entrypoints in the common C++ runtime library DSO,
and their prototypes.
</td> </tr>

</table>

<p>
<hr>

<p>
Please send corrections to <a href=mailto:dehnert@xxxxxxx>Jim Dehnert</a>.


</BODY>
</HTML>
<HTML>

<HEAD>
<title>C++ ABI Closed Issues</title>

<link rel=stylesheet href=small-table.css type="text/css">
<link rel=stylesheet href=code.css type="text/css">

<hr>

<font size=6><i><b>
<p>
C++ ABI Closed Issues
</b></i></font>

<font size=-1>
<p>
<i>Revised 17 August 1999</i>

</center>

</HEAD>

<BODY>

<p> <hr> <p>
<h3> Issue Status </h3>

In the following sections,
the <b><i>class</i></b> of an issue attempts to classify it on the
basis of what it likely affects.
The identifiers used are:

<table>
<tr> <td> call </td>
<td> Function call interface, i.e. call linkage </td>
</tr>

<tr> <td> data </td>
<td> Data layout </td>
</tr>

<tr> <td> lib </td>
<td> Runtime library support </td>
</tr>

<tr> <td> lif </td>
<td> Library interface, i.e. API </td>
</tr>

<tr> <td> g </td>
<td> Potential gABI impact </td>
</tr>

<tr> <td> ps </td>
<td> Potential psABI impact </td>
</tr>

<tr> <td> source </td>
<td> Source code conventions (i.e. API, not ABI) </td>
</tr>

<tr> <td> tools </td>
<td> May affect how program construction tools interact </td>
</tr>
</table>

<p> <hr> <p>
<h3> A.  Object Layout Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-1 </td>
<td> Vptr location </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Where is the Vptr stored in an object (first or last are the usual answers).
</td> </tr>

</table>

<p>
<font color=blue>[990610 All]</font>
Given the absence of addressing modes with displacements on IA-64,
the consensus is to answer this question with "first."

<p>
<font color=blue>[990617 All]</font>
Given a Vptr and only non-polymorphic bases,
which (Vptr or base) goes at offset 0?
<ul>
<li> HP: Vptr at end, but IA-64 is different because no load displacement
<li> Sun: Vptr at 0 probably preferred
<li> g++: Vptr at end today
</ul>
<p>
Tentative decision:  Vptr always goes at beginning.

<p>
<font color=blue>[990624 All]</font>
Accepted tentative decision.
Rename, close this issue, and open separate issue (B-6) for Vtable layout.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-2 </td>
<td> Virtual base classes </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Where are the virtual base subobjects placed in the class layout?
How are data member accesses to them handled?
</td> </tr>

</table>

<p>
<font color=blue>[990610 Matt]</font>
With regard to how data member accesses are handled,
the choices are to store either a pointer or an offset in the Vtable.
The concensus seems to be to prefer an offset.

<p>
<font color=blue>[990617 All]</font>
Any number of empty virtual base subobjects (rare) will be placed at
offset zero.
If there are no non-virtual polymorphic bases,
the first virtual base subobject with a Vpointer will be placed at
offset zero.
Finally, all other virtual base subobjects will be allocated at the
end of the class, left-to-right, depth-first.

<p>
<font color=blue>[990624 All]</font>
Define an empty object as one with no non-static, non-empty data members,
no virtual functions,
no virtual base classes,
and no non-empty non-virtual base classes.
Define a nearly empty object as one which contains only a Vptr.
The above resolution is accepted, restated as follows:

<p>
Any number of empty virtual base subobjects
(rare, because they cannot have virtual functions or bases themselves)
will be placed at offset zero, subject to the conflict rules in A-3
(i.e. this cannot result in two objects of the same type at the same
address).
If there are no non-virtual polymorphic base subobjects,
the first nearly empty virtual base subobject will be placed at offset zero.
Any virtual base subobjects not thus placed at offset zero will be
allocated at the end of the class,
in left-to-right, depth-first declaration order.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-3 </td>
<td> Multiple inheritance </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990701 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Define the class layout in the presence of multiple base classes.
</td> </tr>

</table>

<p>
<font color=blue>[990617 All]</font>
At offset zero is the Vptr whenever there is one,
as well as the primary base class if any (see A-7).
Also at offset zero is any number of empty base classes,
as long as that does not place multiple subobjects of the same type at
the same offset.
If there are multiple empty base classes such that placing two of them
at offset zero would violate this constraint, the first is placed there.
(First means in declaration order.)

<p>
All other non-virtual base classes are laid out in declaration order at
the beginning of the class.
All other virtual base subobjects will be allocated at the
end of the class, left-to-right, depth-first.

<p>
The above ignores issues of padding for alignment,
and possible reordering of class members to fit in padding areas.
See issue A-9.

<p>
<font color=blue>[990624 All]</font>
There remains an issue concerning the selection of the primary base
class (see A-7), but we are otherwise in agreement.
We will attempt to close this on 1 July, modulo A-7.

<p>
<font color=blue>[990701 All]</font>
This issue is closed.
A full description of the class layout can be found in issue A-9.
(At this time, A-7 remains to be closed,
waiting for the Taligent rationale.)

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-4 </td>
<td> Empty base classes </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Where are empty base classes allocated?
(An empty base class is one with no non-static data members,
no virtual functions, no virtual base classes,
and no non-empty non-virtual base classes.)
</td> </tr>

</table>

<p>
<font color=blue>[990624 All]</font>
Closed as a duplicate of A-3.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-5 </td>
<td> Empty parameters </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990701 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
When passing a parameter with an empty class type by value,
what is the convention?
</td> </tr>

</table>

<p>
<font color=blue>[990623 SGI]</font>
We propose that no parameter slot be allocated to such parameters,
i.e. that no register be used,
and that no space in the parameter memory sequence be used.
This implies that the callee must allocate storage at a unique address
if the address is taken (which we expect to be rare).

<p>
<font color=blue>[990624 All]</font>
In addition to the address-taken case,
care is required if the object has a non-trivial copy constructor.
HP observes that in (some?) such cases,
they perform the construction at the call site and pass the object by
reference.

<p>
<font color=blue>[990625 SGI -- Jim]</font>
I understand that the Standard explicitly allows elimination of
even non-trivial copy construction in some cases.
Is this one of them?  Where should I look?
Also, of course, varargs processing for elided empty parameters would
need to be careful.

<p>
I have opened a new issue (C-7) for passing copy-constructed
parameters by reference.
Since doing so would turn an empty value parameter
into a non-empty reference parameter,
this issue can ignore such cases.

<p>
<font color=blue>[990701 All]</font>
An empty parameter will not occupy a slot in the parameter sequence
unless:
<ol>
<li> its type is a class with a non-trivial copy constructor; or
<li> it corresponds to the variable part of a varargs parameter list.
</ol>

<p>
Daveed and Matt will pursue the question of when copy constructors may
be ignored for parameters with the Core committee,
and if they identify cases where the constructors may clearly be
omitted, those (empty) parameters will also be elided.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-7 </td>
<td> Vptr sharing with primary base class </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990729 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
It is in general possible to share the virtual pointer with a
polymorphic base class (the <i>primary</i> base class).
Which base class do we use for this?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Share with the first non-virtual polymorphic base class,
or if none with the first nearly empty virtual base class.
</td> </tr>

</table>

<p>
<font color=blue>[990617 All]</font>
It will be shared with the first polymorphic non-virtual base class,
or if none, with the first nearly empty polymorphic virtual base class.
(See A-2 for the definition of <i>nearly empty</i>.)

<p>
<font color=blue>[990624 All]</font>
HP noted that Taligent chooses a base class with virtual bases before
one without as the primary base class),
probably to avoid additional "this" pointer adjustments.
SGI observed that such a rule would prevent users from controlling the
choice by their ordering of the base classes in the declaration.
The bias of the group remains the above resolution,
but HP will attempt to find the Taligent rationale before this is decided.

<p>
<font color=blue>[990729 All]</font>
Close with the agree resolution.
If a convincing Taligent rationale is found, we can reconsider.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-8 </td>
<td> (Virtual) base class alignment </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
A (virtual) base class may have a larger alignment constraint than a
derived class.
Do we agree to extend the alignment constraint to the derived class?
(An alternative for virtual bases:
allow the virtual base to move in the complete object.)
</td> </tr>

</table>

<p>
<font color=blue>[990623 SGI]</font>
We propose that the alignment of a class be the maximum alignment of
its virtual and non-virtual base classes,
non-static data members, and Vptr if any.

<p>
<font color=blue>[990624 All]</font>
Above proposal accepted.
(SGI observation:
the size of the class is rounded up to a multiple of this alignment,
per the underlying psABI rules.)

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> <a name=A9>A-9</a> </td>
<td> Sorting fields as allowed by [class.mem]/12 </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990624 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The standard constrains ordering of class members in memory only if
they are not separated by an access clause.
Do we use an access clause as an opportunity to fill the gaps left by padding?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
See separate writeup of <a href=abi-layout.html>Data Layout</a>.
</td> </tr>

</table>

<p>
<font color=blue>[990610 all]</font>
Some participants want to avoid attempts to reorder members differently
than the underlying C struct ABI rules.
Others think there may be benefit in reordering later access sections
to fill holes in earlier ones, or even in base classes.

<p>
<font color=blue>[990617 all]</font>
There are several potential reordering questions, more or less independent:
<ol>
<li> Do we reorder whole access regions relative to one another?
<li> Do we attempt to fill padding in earlier access regions with
	initial members from later regions?
<li> Do we fill the tail padding of non-POD base classes with members from
	the current class?
<li> Do we attempt to fill interior padding of non-POD base classes with later
	members?
</ol>

<p>
There is no apparent support for (1),
since no simple heuristic has been identified with obvious benefits.
There is interest in (2), based on a simple heuristic which might
sometimes help and will never hurt.
However, it is not clear that it will help much,
and Sun objects on grounds that they prefer to match C struct layout.
Unless someone is interested enough to implement and run experiments,
this will be hard to agree upon.
G++ has implemented (3) as an option,
based on specific user complaints.
It clearly helps HP's example of a base class containing a word and flag,
with a derived class adding more flags.
Idea (4) has more problems, including some non-intuitive (to users) layouts,
and possibly complicating the selection of bitwise copy in the compiler.

<p>
<font color=blue>[990624 all]</font>
We will not do (1), (2), or (4).  We will do (3).
Specifically, allocation will be in modified declaration order as follows:
<ol>
<li> Vptr if any, and the primary base class per A-7.
<li> Any empty base classes allocated at offset zero per A-3.
<li> Any remaining non-virtual base classes.
<li> Any non-static data members.
<li> Any remaining virtual base classes.
</ol>
Each subobject allocated is placed at the next available position that
satisfies its alignment constraints, as in the underlying psABI.
This is interpreted with the following special cases:
<ol>
<li> The "next available position" after a non-POD class subobject
	(base class or data member) with tail padding is at the
	beginning of the tail padding, not after it.
	(For POD objects, the tail padding is not "available.")
<li> Empty classes are considered to have alignment and size 1,
	consisting solely of one byte of tail padding.
<li> Placement on top of the tail padding of an empty class must avoid
	placing multiple subobjects of the same type at the same
	address.
</ol>
After allocation is complete,
the size is rounded up to a multiple of alignment (with tail padding).

<p>
<font color=blue>[990722 all]</font>
The precise placement of empty bases when they don't fit at offset zero
remains imprecise in the above.
Accordingly, a precise layout algorithm is described in
a separate writeup of <a href=abi-layout.html>Data Layout</a>.

<p>
<font color=blue>[990729 all]</font>
The layout writeup was accepted,
with the first choice for empty base placement.
That is, if placement at offset zero doesn't work,
it will be placed like a normal base/member.
The concensus was that this won't happen often,
and such bases will often overlap with the preceding tail padding or
following components anyway.
Jim will modify the writeup accordingly.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-10 </td>
<td> Class parameters in registers </td>
<td> call </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990710 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The C ABI specifies that structs are passed in registers.
Does this apply to small non-POD C++ objects passed by value?
What about the copy constructor and <code>this</code> pointer in that case?
</td> </tr>

</table>

<p>
<font color=blue>[990701 all]</font>
A separate issue (C-7) deals with cases where a non-trivial copy
constructor is required; we ignore those cases here.
Our conclusion is that, without a non-trivial copy constructor,
we need not be concerned about the class object moving in the process
of being passed, and there is no need to use a mechanism different from
the base ABI C struct mechanism.
At the same time, if we do use the underlying C struct mechanism,
the user has complete control of the passing technique,
by choosing whether to pass by value or reference/pointer.

<p>
Therefore, except in cases identified by issue C-7 for different treatment,
class parameters will be passed using the underlying C struct protocol.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <a name=A11></a> <td> A-11 </td>
<td> Pointers to member functions </td>
<td> data </td>
<td> closed </td>
<td> Cygnus </td>
<td> 990603 </td>
<td> 990812 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
How should pointers to member functions be represented?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
As a pair of values, described below.
</td> </tr>

</table>

<p>
<font color=blue>[990729 All]</font>
Jason described the g++ implementation, which is a three-member struct:
<ol>
<li> The adjustment to <i>this</i>.
<li> The Vtable index plus one of the function, or -1.
     (Zero is a NULL pointer.)
<li> If (2) is an index, the offset from the full object to the member
     function's Vtable.  If -1, a pointer to the function (non-virtual).
</ol>

<p>
A concern about covariant returns was raised.
It was observed that, given our decision to use distinct Vtable entries
for distinct return types, no further concern is required here.
Others will describe their representations.
IBM has an alternative, but it is believed to be patented by Microsoft.

<p>
<font color=blue>[990805 All]</font>
It is agreed that a two-element struct will be used for a pointer to a
member function, with elements as follows:

<dl>
<p>
<dt> <code>ptr</code>:
<dd> For a non-virtual function, this field is a simple function pointer.
     (Under current base IA-64 psABI conventions,
     this is a pointer to a GP/function address pair.)
     For a virtual function,
     it is 1 plus twice the Vtable offset of the function.
     The value zero is a NULL pointer.

<p>
<dt> <code>adj</code>:
<dd> The required adjustment to <i>this</i>.
</dl>

<p>
Although we agreed to close this, SGI suggests a minor modification.
Since the Vtable offset of a virtual function will always be even,
we suggest that it not be doubled before adding 1.
This is because shifts are more restricted on many processors than
other integer ALU operations (shifters are large structures),
so an XOR or NAND will often be cheaper than a right shift.

<p>
<font color=blue>[990812 All]</font>
Close this issue with the suggested modification.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-12 </td>
<td> Merging secondary vtables </td>
<td> data </td>
<td> closed </td>
<td> Sun </td>
<td> 990610 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Sun merges the secondary Vtables for a class (i.e. those for
non-primary base classes) with the primary Vtable by appending them.
This allows their reference via the primary Vtable entry symbol,
minimizing the number of external symbols required in linking,
in the GOT, etc.
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Concatenate the Vtables associated with a class in the same order
that the corresponding base subobjects are allocated in the object.
</td> </tr>

</table>

<p>
<font color=blue>[990701 Michael Lam]</font>
Michael will check what the Sun ABI treatment is and report back.

<p>
<font color=blue>[990729 All]</font>
A separate issue raised in conjunction with A-7 is whether to include
Vfunc pointers in the primary Vtable for functions defined only in the
base classes and not overridden.
If the primary and secondary Vtables are concatenated,
this is no longer an issue,
since all can be referenced from the primary Vptr.

<p>
<font color=blue>[990805 All]</font>
All of the Vtables associated with a class will be concatenated,
and a single external symbol used
(to be identified as part of the mangling issue F-1).
The order of the tables will be the same as the order of base class
subobjects in an object of the class,
i.e. first the primary Vtable,
then the non-virtual base classes in declaration order,
and finally the virtual base classes in depth-first declaration order.

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> A-13 </td>
<td> Parameter struct field promotion </td>
<td> call </td>
<td> closed </td>
<td> SGI </td>
<td> 990603 </td>
<td> 990701 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
It is possible to pass small classes either as memory images,
as is specified by the base ABI for C structs,
or as a sequence of parameters, one for each member.
Which should be done, and if the latter,
what are the rules for identifying "small" classes?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
No special treatment will be specified by the ABI.
</td> </tr>

</table>

<p>
<font color=blue>[990701 all]</font>
Define no special treatment for this case in the ABI.
A translator with control over both caller and callee may choose to optimize.



<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr class=small> <td> A-14 </td>
<td> Pointers to data members </td>
<td> data </td>
<td> closed </td>
<td> SGI </td>
<td> 990729 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
How should pointers to data members be represented?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Represented as one plus the offset from the base address.
</td> </tr>

</table>

<p>
<font color=blue>[990729 SGI]</font>
We suggest an offset from the base address of the class,
represented as a <code>ptrdiff_t</code>.

<p>
<font color=blue>[990805 All]</font>
Such pointers are represented as one plus the offset from the base
address of the class, as a <code>ptrdiff_t</code>.
NULL pointers are zero.


<p> <hr> <p>
<h3> B.  Virtual Function Handling Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> B-2 </td>
<td> Covariant return types </td>
<td> call </td>
<td> closed </td>
<td> SGI </td>
<td> 990520 </td>
<td> 990722 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
There are several methods for adjusting the 'this' pointer of the
returned value for member functions with covariant return types.
We need to decide how this is done.
Return thunks might be especially costly on IA64,
so a solution based on returning multiple pointers may prove more interesting.
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
Provide a separate Vtable entry for each return type.
</td> </tr>

</table>

<p>
<font color=blue>[990610 Matt]</font>
One possibility is to have two Vtable entries,
which might point to different functions, different entrypoints,
or a real entrypoint and a thunk.
Another is to return two result pointers (base/derived),
and have the caller select the right one.

<p>
<font color=blue>[990715 All]</font>
Daveed presented his multiple-return-value scheme,
including an example that involved virtual base classes,
return values that are pointers to nonpolymorphic classes,
and other equally horrible things.

<p>
Consensus: we need to get the horrible cases correct,
but speed only matters in the simple case.
The simple case: class B has a virtual function f returning a B1*
and class D has a virtual function f returning a D1*,
where all four classes are polymorphic,
B is a primary base of D, and B1 is a primary base of D1.
(The really important case is where B1 is B and D1 is D,
but that simplification doesn't make any difference.)

<p>
Jason: Would the usual multiple-entry-point scheme work just as well?
That is, would it be just as fast as Daveed's scheme in the simple case,
and still preserve enough information for the more complicated cases?
It appears so, but we don't have a proof.
Jason will try to provide one.


<p>
<font color=blue>[990716 Cygnus -- Jason]</font>
Proof?
You always know what types a given override must be able to return,
and you know how to convert from the return type to those base types.
You know from the entry point which type is desired.
Seems pretty straightforward to me.



<p>
<font color=blue>[990716 Cygnus -- Jason]</font>
The alternative I was talking about yesterday goes something like this:

<p>
When we have a non-trivial covariant return situation,
we create a new entry in the vtable for the new return type.
The caller chooses which vtable entry to use based on the type they want.

<p>
This could be implemented several ways,
at the discretion of the vendor:

<ol>
<p>
<li>
Multiple entry points to one function,
with an internal flag indicating which type to return.
<p>
<li>
Thunks which intercept the function's return and modify the return value.
Note that unlike the case of calling virtual functions,
for covariant returns we always know which adjustments will be needed,
so we don't have to pay for a long branch.
We do, however, lose the 1-1 correspondence between calls and returns,
which apparently affects performance on the Pentium Pro.
<p>
<li>
Function duplication.
</ol>

<p>
The advantage of this approach to the complex case is that we don't have to
do a dynamic_cast when faced with multiple levels of virtual derivation.
It is also strictly simpler;
Daveed's model already requires something like
this in cases of multiple inheritance.

<p>
Of course, we can always mix and match;
we could choose to only do this in cases of virtual inheritance,
or use Daveed's proposal and do this only in
cases of repeated virtual inheritance.
In that case, the multiple returns
would just be an optimization for the single virtual inheritance case.

<p>
Since we don't seem to care about the performance of
anything but single nonvirtual inheritance,
it seems simpler not to bother with multiple returns.

<p>
The remaining question is how to handle the case of nontrivial
nonvirtual inheritance:
do we use multiple slots or have the caller do the adjustment?
My inclination is to have the caller adjust.

<p>
WRT patents,
the idea of having the function return the base-most class and having
the caller adjust is parallel to the patented Microsoft scheme whereby
they pass the base-most class as the 'this' argument to virtual functions,
but the word 'return' does not appear anywhere in the patent,
so it seems safe.


<p>
<font color=blue>[990722 All]</font>
The group was generally agreed that the simplicity of multiple entries
in the vtable outweighed any space/performance advantage of more
complex schemes (e.g. the method Daveed described on 15 July).
Discussion focussed on whether it is worthwhile to eliminate some of
the entries in cases where they are unnecessary because the caller
knows the required conversion,
namely when the return type has a unique non-virtual subobject of the
original return type.

<p>
Agreement was reached to avoid the complication of eliminating some of
the Vtable entries.
Thus, the Vtable will have one entry for each accessible return type of
a covariant virtual function.
These may be implemented in a variety of ways,
e.g. duplicated functions, separate entrypoints, or stubs,
and the ABI need not specify the choice.
The location of the Vtable entries is part of the separate Vtable
layout issue B-6.


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> B-3 </td>
<td> Allowed caching of vtable contents </td>
<td> call </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
The contents of the vtable can sometimes be modified,
but the concensus is that it is nonetheless always allowed to "cache" elements,
i.e. to retain them in registers and reuse them,
whenever it is really useful.
However, this may sometimes break "beyond the standard" code,
such as code loading a shared library that replaces a virtual function.
Can we all agree when caching is allowed? 
</td> </tr>
<tr> <td colspan=7>
<b> Resolution </b>:
Caching is allowed.
</td> </tr>

</table>

<p>
<font color=blue>[990604 HP -- Christophe]</font>
Mike (Ball) gave me what I believe is an excellent definition of  
when caching is allowed.  I'd like him to present it.

<p>
<font color=blue>[990805 All]</font>
Christophe explained that the rule is simply that,
within a call to a member function of the class,
the class Vtable may not be modified.
Between such calls, no assumption may be made.
With this observation, the issue is closed.

<p>
<font color=blue>[990812 All]</font>
The rule is even simpler.
Once a program changes the type of a pointer's target,
the pointer is invalidated, and its value may not be reused.
Therefore, a code sequence which repeatedly refers to the same pointer
value is invalid if the pointee's vtable has been changed.


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> B-4 </td>
<td> Function descriptors in vtable </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990603 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
For a runtime architecture where the caller is expected to load the GP
of the callee (if it is in, or may be in, a different DSO), e.g. HP/UX,
what should vtable entries contain?
One possibility is to put a function address/GP pair in the vtable.
Another is to include only the address of a thunk which loads the GP
before doing the actual call.
</td> </tr>
<tr> <td colspan=7>
<b> Resolution </b>:
The Vtable will contain a function address/GP pair.
</td> </tr>

</table>

<p>
<font color=blue>[990624 All]</font>
Note that putting GP in the Vtable prevents putting it in shared memory.
See B-7.

<p>
<font color=blue>[990805 All]</font>
It was decided that special representations to accomodate shared memory
would be expensive and therefore undesirable.
Therefore, the decision is to put the function address/GP pair in the
vtable, avoiding the cost of an extra indirection in using it.


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> B-7 </td>
<td> Objects and Vtables in shared memory </td>
<td> data </td>
<td> closed </td>
<td> HP </td>
<td> 990624 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
Is it possible to allocate objects in shared memory?
For polymorphic objects, this implies that the Vtable must also be
in shared memory.
</td> </tr>
<tr> <td colspan=7>
<b> Resolution </b>:
No special representation is useful in support of shared memory.
</td> </tr>

</table>

<p>
<font color=blue>[990624 All]</font>
Note that putting GP in the Vtable prevents putting it in shared memory.
This interacts with B-4.

<p>
<font color=blue>[990624 HP -- Cary]</font>
For a C++ object to be placed into shared memory,
its vtable pointer must be valid in all processes
that are sharing that object.

<ol>
<p>
<li>
If the vtable can be placed in text, that would be fine,
but the vtable contains function pointers (or descriptors)
that require runtime relocation, so it must be in data.

<p>
<li>
We can place the vtables in shared memory,
but only if the function pointers/descriptors are valid in all processes.
The entry point addresses, which refer to shared text, should be shareable,
but the gp values may not be identical for all processes.
(RTTI pointers are also an issue,
and could be solved by putting the RTTI information in shared memory as well.)

<p>
<li>
We can place the vtables in private memory,
provided they are at the same address in all processes.
</ol>

<p>
One way or another,
we need a way of ensuring that a pointer from shared 
memory to private memory is valid in all processes,
which means that we will need a means to ensure that certain shared
library data segments can get mapped at the same address in all
processes that load those certain libraries.

<p>
My wild idea a few years ago was to put the vtables in shared memory
(by allocating and building them at load time, as Taligent did),
and store a shared library index in place of the gp value
in each function descriptor.
Each process would have its own table of gp values,
indexed by this shared library index,
but the index space would be managed system-wide.
The C++ runtime library would have been responsible for allocating
a new index for each unique C++ shared library loaded on the system,
then storing the process-local copy of the gp pointer in the 
appropriate slot of the table.

<p>
<font color=blue>[990628 SGI -- Jim]</font>
Note a further problem with vtables in shared memory (Cary's point 2).
If a virtual function comes from another DSO,
it may be pre-empted differently in different programs.
Hence, the function pointer itself is a problem even if the GP isn't.

<p>
<font color=blue>[990701 All]</font>
An extensive discussion boiled down to a few points:
<ul>
<p>
<li> The primary issue is objects in shared memory --
    vtables aren't interesting in themselves, but rather because
    putting the object in shared memory implies having the vtable at
    the same address in all sharing processes.

<p>
<li> Many of us have a few customers asking for this.
    It is not clear just how extensive a facility they need,
    or how automatic it needs to be.
    We should attempt to gauge the need.

<p>
<li> Noone thinks we should penalize the non-shared case for
    the rare instances of shared demand.

<p>
<li> It is questionable whether we can define an ABI mechanism
    which will work on all of our systems,
    but we'd like not to preclude OS-specific extensions to do
    this if we can't.

<p>
<li> One possible approach would be an API allowing a user to
    place an object in shared memory,
    and then "install" it by setting its vtable pointers,
    possibly to copies also placed in the same shared memory.

<p>
<li> A more automatic approach would be something which allocated
    certain objects/vtables to shared memory,
    gave up at link time if not all pointers were internal to the
    object being linked,
    attempted to place the relevant segments at the same runtime
    addresses to allow sharing,
    and gave up on sharing if this was not possible.
    Such an approach would perhaps still require some care on the part
    of the user to prevent problematic runtime situations.
</ul>

<p>
These ideas are very fuzzy.
Participants should think about the need and possibilities and attempt
to identify more concrete approaches.

<p>
<font color=blue>[990805 All]</font>
It was determined (largely based on consideration by Jason)
that the only practical approach to putting objects in shared memory
is to force the objects, Vtables, functions, etc. to the same addresses
in the various processes involved.
If this is done, data representation issues are irrelevant.
Therefore, this issue is closed as moot.

<p>
Note that the base psABI defines a flag, EF_IA_64_ABSOLUTE,
which forces an executable object to the addresses specified in ELF,
so at least one method of representing this is already available.


<p> <hr> <p>
<h3> C.  Object Construction/Destruction Issues </h3>

<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> C-7 </td>
<td> Passing value parameters by reference </td>
<td> call </td>
<td> closed </td>
<td> All </td>
<td> 990624 </td>
<td> 990805 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
It may be desirable in some cases where a type has a non-trivial
copy constructor to pass value parameters of that type by performing
the copy at the call site and passing a reference.
</td> </tr>
<tr> <td colspan=7>
<b> Resolution </b>:
Whenever a class type has a non-trivial copy constructor,
pass value parameters of that type by performing
the copy at the call site and passing a reference.
</td> </tr>

</table>

<p>
<font color=blue>[990701 All]</font>
Daveed and Matt will attempt to pin down the copy requirements with the
Core committee, i.e. when a non-trivial copy constructor may be elided.
The relevant Standard requirement is 12.8/15,
and there is an open defect report related to this question.
For cases where the ctor may not be elided,
we expect to perform the copy at the call site,
and pass a reference.

<p>
<font color=blue>[990729 All]</font>
Matt will produce a clear proposal for when the ABI will elide the
constructor (and therefore pass the class object like a normal C struct),
based on the Standard's exceptions.

<p>
<font color=blue>[990805 All]</font>
There are no cases where a non-trivial copy constructor can be simply
elided for all instances of a particular parameter.
Therefore, we shall use the consistent convention that,
if a value parameter's (class) type has a non-trivial copy constructor,
the caller will allocate space for it, perform the copy,
and pass a reference.

<p>
Note that the standard does allow the caller,
if the value being passed is a temporary,
to construct the temporary directly into the parameter memory
and elide the copy constructor call.


<p>
<table border=on cellpadding=3>

<tr>
<th> # </th>
<th> Issue </th> <th> Class </th> <th> Status </th>
<th> Source </th> <th> Opened </th> <th> Closed </th>
</tr>

<tr> <td> C-8 </td>
<td> Returning classes with non-trival copy constructors </td>
<td> call </td>
<td> closed </td>
<td> All </td>
<td> 990625 </td>
<td> 990722 </td>
</tr>
<tr> <td colspan=7>
<b>Summary</b>:
How do we return classes with non-trivial copy constructors?
</td> </tr>
<tr> <td colspan=7>
<b>Resolution</b>:
The caller allocates space,
and passes a pointer as an implicit first parameter
(prior to the implicit <i>this</i> parameter).
</td> </tr>

</table>

<p> <hr> <p>
<h3> D.  Exception Handling Issues </h3>

<p> <hr> <p>
<h3> E.  Template Instantiation Model Issues </h3>

<p> <hr> <p>
<h3> F.  Name Mangling Issues </h3>

<p> <hr> <p>
<h3> G.  Miscellaneous Issues </h3>

<p> <hr> <p>
<h3> H.  Library Interface Issues </h3>

<p>
<hr>

<p>
Please send corrections to <a href=mailto:dehnert@xxxxxxx>Jim Dehnert</a>.

</BODY>
</HTML>
<HTML>

<HEAD>
<title>C++ ABI for IA-64: Data Layout</title>

<link rel=stylesheet href=small-table.css type="text/css">
<link rel=stylesheet href=code.css type="text/css">

<hr>

<font size=6><i><b>
<p>
C++ ABI for IA-64: Data Layout
</b></i></font>

<font size=-1>
<p>
<i>Revised 17 August 1999</i>

</center>

</HEAD>

<BODY>

<p> <hr> <p>
<h3> Revisions </h3>

<p>
<font color=blue>[990811]</font>
Described member pointer representations, virtual table layout.

<p>
<font color=blue>[990730]</font>
Selected first variant for empty base allocation; removed others.


<p> <hr> <p>
<h3> General </h3>

In what follows, we define the memory layout for C++ data objects.
Specifically, for each type, we specify the following information about
an object O of that type:
<ul>
<li> the <i>size</i> of an object, <i>sizeof</i>(O);
<li> the <i>alignment</i> of an object, <i>align</i>(O); and
<li> the <i>offset</i> within O, <i>offset</i>(C),
     of each data component C, i.e. base or member.
</ul>

<p> For purposes internal to the specification,
we also specify the <i>data size</i> of an object, <i>dsize</i>(O),
which intuitively is sizeof(O) minus the size of tail padding.

<p> <hr> <p>
<h3> Definitions </h3>

<p>
The descriptions below make use of the following definitions:

<dl>

<p>
<dt> <i>alignment</i> of a type T (or object X)</dt>
<dd>
A value A such that any object X of type T has an address satisfying
the constraint that &X modulo A == 0.

<p>
<dt> <i>empty class</i> </dt>
<dd>
A class with no non-static data members,
no virtual functions, no virtual base classes,
and no non-empty non-virtual base classes.

<p>
<dt> <i>nearly empty class</i> </dt>
<dd>
A class, the objects of which contain only a Vptr.

<p>
<dt> <i>polymorphic class</i> </dt>
<dd>
A class requiring a virtual table pointer
(because it or its bases have one or more virtual member functions or
virtual base classes).

<p>
<dt> <i>primary base class</i> </dt>
<dd>
For a polymorphic class,
the unique base class (if any) with which it shares the Vptr at offset 0.

</dl>

<p> <hr> <p>
<h3> POD Data Types </h3>

The size and alignment of C POD types is as specified by the base (C) ABI.
Type bool has size and alignment 1.
All of these types have data size equal to their size.
(We ignore tail padding for PODs because the Standard does not allow us
to use it for anything else.)


<p> <hr> <p>
<a name=member-pointers></a>
<h3> Member Pointers </h3>

<p>
A pointer to data member is an offset from the base
address of the class object containing it,
represented as a <code>ptrdiff_t</code>.
It has the size, data size, and alignment of a <code>ptrdiff_t</code>.

<p>
A pointer to member function is a pair <ptr, adj> as follows:

<dl>
<p>
<dt> <code>ptr</code>:
<dd> For a non-virtual function, this field is a simple function pointer.
     (Under current base IA-64 psABI conventions,
     that is a pointer to a GP/function address pair.)
     For a virtual function,
     it is 1 plus twice the Vtable offset of the function.
     The value zero is a NULL pointer.

<p>
<dt> <code>adj</code>:
<dd> The required adjustment to <i>this</i>,
     represented as a <code>ptrdiff_t</code>.
</dl>

<p>
It has the size, data size, and alignment
of a class containing those two members, in that order.
(For 64-bit IA-64, that will be 16, 16, and 8 bytes respectively.)



<p> <hr> <p>
<a name=class-types></a>
<h3> Non-POD Class Types </h3>

For non-POD class types C, assume that all component types
(i.e. base classes and non-static data member types)
have been laid out, defining size, data size, and alignment.
Layout (of type C) is done using the following procedure.

<ol type=I>
<p>
<li> <h5> Initialization </h5>
  <ol type=1>
  <p>
  <li> Initialize sizeof(C) to zero, align(C) to one, dsize(C) to zero.
  <p>
  <li> If C is a polymorphic type:
      <ol type=a>
      <p>
      <li> If C has a polymorphic base class,
	   attempt to choose a primary base class B.
	   It is the first non-virtual polymorphic base class, if any,
	   or else the first nearly empty virtual base class.
	   Allocate it at offset zero, and set
	   sizeof(C) to sizeof(B), align(C) to align(B), dsize(C) to dsize(B).
      <p>
      <li> Otherwise, allocate the vtable pointer for C at offset zero,
	   and set sizeof(C), align(C), and dsize(C) to the appropriate
	   values for a pointer (all 8 bytes for IA-64 64-bit ABI).
      </ol>
  </ol>

<p>
<li> <h5> Non-Virtual-Base Allocation </h5>
<p>
For each data component D (i.e. base or non-static data member)
except virtual bases,
first the non-virtual base classes in declaration order
and then the non-static data members in declaration order,
allocate as follows:

  <ol type=1>

  <p>
  <li> If D is not an empty base class,
	start at offset dsize(C),
	incremented if necessary to alignment align(type(D)).
	Place D at this offset unless doing so would result in two
	components (direct or indirect) of the same type having the
	same offset.
	If such a component type conflict occurs,
	increment the candidate offset by align(type(D)),
	and try again,
	repeating until success occurs
	(which will occur no later than sizeof(C) incremented to the
	required alignment).

	<p>
	Update sizeof(C) to max (sizeof(C), offset(D)+sizeof(D)).
	Update align(C) to max (align(C), align(D)).
	If D is a base class (not empty in this case),
	update dsize(C) to offset(D)+dsize(D).
	If D is a data member,
	update dsize(C) to max (offset(D)+dsize(D), offset(D)+1).

  <p>
  <li> If D is an empty base class,
	its allocation is similar to the first case above,
	except that additional candidate offsets are considered before
	starting at dsize(C).
	First, attempt to place D at offset zero.
	If unsuccessful (due to a component type conflict),
	proceed with attempts at dsize(C) as for non-empty bases.

	<p>
	Once offset(D) has been chosen,
	update sizeof(C) to max (sizeof(C), offset(D)+sizeof(D)).
	Note that align(D) is 1, so no update of align(C) is needed.
	Similarly, since D is an empty base class,
	no update of dsize(C) is needed.

  </ol>

<p>
<li> <h5> Virtual Base Allocation </h5>
<p>
Finally allocate any virtual base classes
(except one selected as the primary base class in I-2a, if any)
as we did non-virtual base classes in step II-1,
in declaration order.
Update sizeof(C) to max (sizeof(C), offset(D)+sizeof(D)).
If non-empty, also update align(C) and dsize(C) as in II-1.

<p>
<li> <h5> Finalization </h5>
<p>
Round sizeof(C) up to a non-zero multiple of align(C).

</ol>


<p> <hr> <p>
<a name=vtable></a>
<h3> Virtual Table Layout </h3>

<p>
<h4> General </h4>

<p>
A <i>virtual table</i> (<i>vtable</i>) is a table of information used
to dispatch virtual functions,
to access virtual base class subobjects,
and to access information for runtime type identification (RTTI).
Each class that has virtual member functions or virtual bases
has an associated set of vtables.
There may be multiple vtables for a particular class,
if it is used as a base class for other classes.
However, the vtable pointers within all the objects (instances)
of a particular most-derived class point to the same set of vtables.

<p>
A vtable consists of a sequence of offsets, data pointers,
and function pointers, as well as structures composed of such items.
We will describe below the sequence of such items.
Their offsets within the vtable are determined by that allocation
sequence and the natural ABI size and alignment,
just as a data struct would be.  In particular:
<ul>
<li> Offsets are of type <code>ptrdiff_t</code> unless otherwise stated.
<li> Data pointers have normal pointer size and alignment.
<li> Function pointers remain to be defined.
     One possibility is that they will be
     &lt;function address, GP address> pairs, with pointer alignment.
</ul>

<p>
In general, what we consider the address of a vtable
(i.e. the address contained in objects pointing to a vtable)
may not be the beginning of the vtable.
We call it the <i>address point</i> of the vtable.
The vtable may therefore contain components at either positive or
negative offsets from its address point.

<p>
<h4> Components </h4>

<p>
Each vtable consists of the following components:

<ul>
<p>
<li>
<i>Base offsets</i> are used to access
the virtual bases of an object,
or non-virtual bases when pointer adjustment is required
for some overriden virtual function.
Such an entry is a displacement to a virtual base subobject from the
location within the object of the vtable pointer that addresses this vtable.
These entries are only necessary if the class directly or indirectly
inherits from virtual base classes,
or if it overrides a virtual function defined in a base class and if
adjustment from the base to the derived class is needed.
The values can be positive or negative.

<p>
<li>
The <i>offset to top</i> holds the displacement to the top of the object
from the location within the object of the vtable pointer that addresses
this vtable,
as a <code>ptrdiff_t</code>.
A negative value indicates the vtable pointer is part of an embedded
base class subobject; otherwise it is zero.
The offset provides a way to find the top of the object from any base
subobject with a vtable pointer.
This is necessary for dynamic_cast<void*> in particular.

<p>
The virtual pointer points to the "offset to top" field.

<p>
<li>
The <i>typeinfo pointer</i> points to the typeinfo object used for RTTI.
All entries in each of the vtables for a given class point to the same
typeinfo object.

<p>
<li>
The <i>duplicate base information pointer</i> points to a table used to
perform runtime disambiguation of duplicate base classes for dynamic casts.
The entries in the vtables for a given class do not necessarily
all point to the same table of duplicate base information.

<p>
<li>
<i>Virtual function pointers</i> are used for virtual function dispatch.
Each pointer holds either the address of a virtual function of the class
(or the address of a secondary entry point that performs certain
adjustments before transferring control to a virtual function.)
In the case of shared library builds,
a virtual function pointer entry contains a pair of components
(each 64 bits in the 64-bit IA-64 ABI):
the value of the target GP value and the actual function address.
That is, rather than being a normal function pointer,
which points to such a two-component descriptor,
a virtual function pointer entry is the descriptor.

<p>
<li>
<i>Base vtables</i> are copies of the vtables for base classes of the
current class
(copies in the sense that they have the same layout,
though virtual function pointers may point to overriding functions).

</ul>

<p>
<h4> Virtual Table Order </h4>

<p>
A virtual table's components are laid out in the following order,
analogous to the corresponding object layout.

<ol>
<p>
<li>
If virtual base offsets are required,
they come first, with ordering as defined in categories 3 and 4 below.
<font color=red> <i>Question:</i>
Is the characterization of which bases need offsets above adequate?
<i>Note:</i> The non-virtual cases need to be reflected in the
descriptions below of categories 3 and 4.
</font>

<p>
<li>
The vtable address point points here,
i.e. this is the address of the vtable contained in an object's vptr.

<p>
<li>
The offset to top field is next (therefore at the vtable address),
if required (always if there is a virtual function declared in the class).

<p>
<li>
The typeinfo pointer field is next.
It is always present.

<p>
<li>
The duplicate base information pointer comes next, if required.

<p>
<li>
Virtual function pointers come next,
in order of declaration of the corresponding member function in the class.
They appear only if there is no suitable entry in one of the base vtables,
i.e. if the return type is overridden or if it is not declared in a base.
<font color=red> <i>Question:</i>
Is this a correct characterization?
</font>

<p>
<li>
The base vtables are last,
except for the primary base class vtable,
which is a subtable of the derived class vtable.
They are in order of base class declaration,
with the vtables for a virtual base class coming after
the vtable for the first base class defining it.
<font color=red> <i>Question:</i>
Can we just use the first vtable for the virtual base class embedded in
another of the base vtables?
</font>

</ol>

<p>
<h4> Virtual Table Construction </h4>

<p>
In this section, we describe how to construct the vtable for an class,
given vtables for all of its base classes.
To do so, we divide classes into several categories,
based on their base class structure.

<p>
<h5> Category 0: Trivial </h5>

Structure:
<ul>
<li> No inherited base classes.
<li> No virtual functions.
</ul>

<p>
Such a class has no associated vtable,
and its objects contain no vptr.

<p>
<h5> Category 1: Leaf </h5>

Structure:
<ul>
<li> No inherited base classes.
<li> Declares virtual functions.
</ul>

<p>
The vtable contains an RTTI field followed by virtual function pointers.
There is one function pointer entry for each
virtual function declared in the class.

<p>
<h5> Category 2: Non-Virtual Bases </h5>

Structure:
<ul>
<li> Only non-virtual base classes.
<li> Base classes are trivial or leaf (they have no base classes).
<li> No adjustment is required in any overridden virtual functions.
</ul>

<p>
If none of the base classes have vtables,
a vtable is constructed for the class
according to the Category 1 rules.

<p>
Otherwise, the class has a vtable for each base class that has a vtable.
The class's vtables are constructed from copies of the base class vtables.
The entries are the same, except:

<ul>
<p>
<li> The RTTI fields contain information for the class,
     rather than for the base class. 

<p>
<li> The function pointer entries for virtual functions inherited from
     the base class and overridden by this class are replaced with the
     addresses of the overriding functions
     (or the corresponding adjustor secondary entry points).

<p>
<li> At negative offsets,
     offsets to the base classes are generated if used by adjustor
     secondary entry points. 
</ul>

<p>
For a base class <code>Base</code>,
and a derived class <code>Derived</code> for which we are constructing
this set of vtables,
we shall refer to the vtable for <code>Base</code> as
<code>Base-in-Derived</code>.
The vptr of each base subobject of an object of the derived class will
point to the corresponding base vtable in this set.

<p>
The vtable copied from the primary base class is also called the
primary vtable;
it is addressed by the vtable pointer at the top of the object.
The other vtables of the class are called secondary vtables;
they are addressed by vtable pointers inside the object.

<p>
Following the function pointer entries that correspond to those of the
primary base class,
the primary vtable holds the following additional entries at its tail:
<ul>
<li> Entries for virtual functions introduced by this class.
<li> Entries for overridden virtual functions not already in the vtable.
     (These are also called replicated entries because they are already
     in the secondary vtables of the class.)
    <font color=red> <i>Question:</i>
    Are these really needed?
    </font>
</ul>

The primary vtable, therefore,
has the base class functions appearing before the derived class functions.
The primary vtable can be viewed as two vtables accessed
from a shared vtable pointer. 

<p>
<i>Note</i>:
Another benefit of replicating virtual function entries is that it
reduces the number of this pointer adjustments during virtual calls.
Without replication,
there would be more cases where the this pointer would have to be
adjusted to access a secondary vtable prior to the call.
These additional cases would be exactly those where the function
is overridden in the derived class,
implying an additional thunk adjustment back to the original pointer.
Thus replication saves two adjustments for each virtual call to an
overridden function introduced by a non-primary base class. 

<p>
<h5> Category 3: Virtual Bases Only </h5>

Structure:
<ul>
<li> Only virtual base classes.
<li> Base classes are not empty or nearly empty.
<li> Base classes are trivial or leaf (they have no base classes).
</ul>

<p>
The class has a vtable for each virtual base class that has a vtable.
These are all secondary vtables and are constructed from copies of the
base class vtables according to the same rules as in Category 2.
The vtable pointers of the virtual base subobjects within the object
address these vtables. 

<p>
The class also has a vtable that is not copied from the virtual base
class vtables.
This vtable is the primary vtable of the class and addressed by the
vtable pointer at the top of the object, which is not shared.
It holds the following function pointer entries: 

<ul>
<p>
<li> Entries for virtual functions introduced by this class.

<p>
<li> Entries for overridden virtual functions.
     (These are also called replicated entries,
     because they are already in the secondary vtables of the class.)
</ul>

<p>
The primary vtable also has virtual base offset entries
to allow finding the virtual base subobjects.
There is one virtual base offset entry for each virtual base class.
For a class that inherits only virtual bases,
the entries are in the reverse order in which the
virtual bases appear in the class declaration,
that is, the entry for the leftmost virtual
base is closest to the address point of the vtable. 


<p>
<h5> Category 4: Complex </h5>

Structure:
<ul>
<li> None of the above,
     i.e. directly or indirectly inherits both virtual and non-virtual
     base classes, or at least one nearly empty virtual base class.
</ul>

<p>
The rules for constructing vtables of the class are a combination of
the rules from Categories 2 and 3,
and for the most part can be determined inductively.
However the rules for placing virtual base offset entries in the
vtables requires elaboration. 

<p>
The primary vtable has virtual base offset entries for all virtual
bases directly or indirectly inherited by the class.
Each secondary vtable has entries only for virtual
bases visible to the corresponding base class.
The entries in the primary vtable are ordered so that entries for
virtual bases visible to the primary base class are placed closest
to the vtable address point, i.e. at higher addresses,
while entries for virtual bases only visible to this class are further
from the vtable address point, i.e. at lower addresses. 

<p>
For virtual bases only visible to this class,
the entries are in the reverse order in which the virtual bases are
encountered in a depth-first, left-to-right traversal of the
inheritance graph formed by the class definitions.
Note that this does not follow the
order that virtual bases are placed in the object. 



<i>
<font color=red>
<p>
<h4> Issues: </h4>
<ul>
<li> A-6:  RTTI representation.
<li> A-6:  Duplicate base structure representation.
<li> B-2:  Will contain one entry per return type for covariant returns.
</ul>
</font>
</i>


<p> <hr> <p>
<h3> External Names (a.k.a. Mangling) </h3>

<i>
&lt;To be specified.>

<p>
<hr>

<p>
Please send corrections to <a href=mailto:dehnert@xxxxxxx>Jim Dehnert</a>.

</BODY>
</HTML>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
   <TITLE>RTTI Implementation In ABI2</TITLE>
</HEAD>
<BODY>

<i>Note (Michael Lam 12 August 1999):</i>
Sun is filing a patent on the algorithms described here.

<hr>
<p>

<H1 ALIGN=CENTER>RTTI Implementation in ABI2</H1>

<p>The typeinfo object is implemented as:
<PRE>
    class type_info {
	// public interface ignored
    private:
	static_type_info* static_data;
    };
</PRE

<P>The static_type_info objects are shared with the exception implementation.
The static data has the following format.  In this description we
make heavy use of self-relative pointers for position independence.
We denote self-relative pointers by "$" instead of "*".  They are
represented in the structures as lvalues of type ptr_diff_t.
For example, we might have a field:
<PRE>
    base_block$ bases;	// base information.
</PRE>
<P>These are converted to real pointers using the following template.
<PRE>
    template <class T> to_real_ptr(ptr_diff_t& p)
    {
	return (T)((char*)p + *p);
    }
</PRE>
<P>Thus a self-relative pointer to a "base_block" is accessed by
<PRE>
    *to_rel_ptr<base_block*>(ti->bases);

    struct static_type_info {
	const char$ ty_name;		// print name for the type
	ptr_diff_t reserved;   		// Can be filled as described below
	class_base_descr$ base_table;	// base class information for cast
	uint32 type_hash[4];		// unique identifier
	uint32 flags;			// notes on the type
	uint32 cv_qualifiers;		// const-vol qualifiers
	uint32 pointer_count() const;	// pointer level count;
	uint32 voidstar_flag() const;	// non-zero if void*
	uint32 dotdotdot_flag() const;	// non-zero if "..." 

    };

    struct class_base_descr {
	uint32 type_hash[4];		// unique identifier
	size_t offset;			// offset in most-derived
    };
</PRE>
<DL>
<DT>ty_name:	<DD>Pointer to a null-terminated name for the type.
		In general this name should be a utf8 value

<DT>reserved:	<DD>A tool for extending the typeinfo object in an
		orthogonal direction. For example, this could be a
		self-relative pointer to a Java data block.  For C++ types,
		extension should probably be by derivation.

<DT>base_table:	<DD>For all classes this is a self-relative pointer to an array
		of class_base_descr entries.  Each entry contains the
		hash for that class and the offset of that class within
		the most derived class.  The most significant two bits
		of the offset are used as flags. The msb is set to 
		indicate the last entry in the array, and the next
		msb is set to indicate that the path from most derived
		to the entry is private.  The entries are in depth-first
		left-to-right order based on the inheritance dag, except
		that each subobject is represented exactly once.  The 
		most derived class is the last entry.  Its offset entry 
		will always have only the sign bit set, since it has a
		zero offset, and is never private or ambiguous.
		Pointers to classes will share the same base_table as
		the class itself.

<DT>type_hash:	<DD>A hash function representing the type.  This is
		obtained by applying the NIST Secure Hash Algorithm (SHA)
		to the mangled name for the representative type.  The
		representative type is chosen to make exception type
		matching easy, and is determined as follows:
		<UL>
		<LI>For pointers to class, the class.
		<LI>For all other pointers to objects, the pointer with
		    cv-qualification removed at all levels.
		<LI>For other types, the type itself
		<LI>For "..." the mangled name is the empty string
		</UL>

<DT>flags:	<DD>This contains bitflags used to describe a type.  If
		the type is not a pointer to an object, this word contains
		zero.  There are two flag values.
		<UL>
		    <TABLE>
		    <TR><TD>void*			<TD>0x80000000
		    <TR><TD>any type (...)		<TD>0x40000000
		    </TABLE>
		</UL>
		the value is 
		    <number of pointer levels> + flags.

		There are no references, as they are irrelevent in
		all contexts in which these objects are used.

<DT>cv_qualifiers:  <DD>A bitmask representing the cv qualifications for any
		pointer levels.  The number of pointer levels is part
		of the pointer_flags field.  Two bits are used for each
		level of pointers. 0x2 implies that the level points to
		constant, while 0x1 implies that it points to volatile.
		These bits are built up with the outermost pointer to
		the left, and the entire set is right justified.  For
		example 
		<UL>
		<TABLE>
			<TR><TD>const char*		<TD>-> 0x2<TD>(10)
			<TR><TD>const char**		<TD>-> 0x8<TD>(1000)
			<TR><TD>const char*const*	<TD>-> 0xA<TD>(1010)
			<TR><TD>const char*volatile*	<TD>-> 0x9<TD>(1001)
		</TABLE>
		</UL>
		This can only represent 16 levels of pointer, but IR
		can only represent 13, so this works.  If desired,
		with a more reasonable IR, we can extend this field
		by replacing it with a self-relative pointer to multiple
		words.  This would be triggered by the pointer_levels
		value in "flags".  It is not currently used.  

<DT>pointer_count() const:	<DD> The pointer level count.
		This returns the lower 16 bits of the flags

<DT>voidstar_flag() const:	<DD> Nonzero if thisis void*.  This just
		masks off the flag, it doesn't convert it to bool.

<DT>dotdotdot_flag() const;	<DD> non-zero if this is "...".  This just
		masks off the flag, it doesn't convert it to bool.
</DL>

<H3>Issues with RTTI blocks still open to change.</H3>

<P>Polymorphic classes have references to static_type_info blocks in their
virtual tables.  Virtual table entries are of type
<PRE>
    union vtab_entry { 
	void (*f)();	// function pointer
	ptr_diff_t o;	// offset adjustment
    };
</PRE>
If the virtual pointer in a class is denoted by "virt_ptr", then
<PRE>
    virt_ptr[0].o
</PRE>
is a self-relative pointer to static type data for the most-derived class,
and
<PRE>
    virt_ptr[1].o
</PRE>
is the offset of the subobject with the virtual pointer in the entire
class object.

<H3>Dynamic Casts</H3>

<P>Dynamic casts are divided into cases at compile time, and each case
generates different code.

<DL>
<DT><P><B>Up cast to a base class:</B>

<DD><P>Handled as a normal static cast.  No dynamic code is generated

<DT><P><B>Cast to void*</B>

<DD><P>This is defined as returning a pointer to the start of the entire
    object.  Code is generated inline.
<UL>
<PRE>
static_type* temp;
(temp = opnd,
(temp != NULL)
    ? (void*)(((char*)temp) - temp->virtualsym[1].o)
    : (void*) temp
) 
</PRE>
</UL>
<DT><P><B>Source class is a unique non-virtual base class of destination class</B>

<DD> This generates a call to the function
<PRE>
<UL>
void* __Crun::simple_down_cast(
	    void* opnd,			// original pointer
	    static_type_info* sclass,	// source class
	    static_type_info* dclass);	// destination class
</UL>
</PRE>
    In this case there can be only one subobject of the static source
    type, and the only piece of information needed is the offset within
    the entire object, which the routine picks up from the virtual table.

<P>    The algorithm is:
<OL>
<LI>	If the opnd is NULL, return NULL.

<LI>	Search the base class table looking for an entry with the proper
	static class at the offset of the static class.

<LI>	Search the base table from that point looking for a match
	with the destination class
	
<LI>	If the destination class is not found the cast fails, return NULL

<LI>	Otherwise, the cast succeeds, since other conditions have
	been checked statically.  Adjust the pointer using the two
	offsets. and return it.
</OL>
<DT><P><B>Source is a public base class of dest, but there is some virtual
    inheritance involved so that there could be more than one class
    derived from this subobject.</B>

<DD> This generates a call to the function
<UL>
<PRE>
void* __Crun::down_cast(
	    void* opnd,			// Original pointer
	    static_type_info* sclass,	// source class
	    static_type_info* dclass);	// destination class
</PRE>
</UL>
    In this case the dynamic table is searched to find subobjects of type
    "sclass" at the offset obtained from the virtual table.  Then the
    cast to "dclass" proceeds from that object.

<P>The algorithm is:
<OL>
<LI>	If the opnd is NULL, return NULL.

<LI>	Search the base table from first to last, looking for a match
	with the source class that has the same offset as the original
	subobject.

<LI>	If this search fails, we have an internal error.

<LI>	If the "private" bit is set in this base entry, the cast fails,
	return NULL

<LI>	From that point, search the base table toward the last, looking
	for a match with the destination class.
	
<LI>	If the destination class is not found, or if the "private" bit
	is set, the cast fails, return NULL

<LI>	Continue searching for the destination class.  If it is found,
	the cast fails, return NULL

<LI>	Otherwise, the cast succeeds, and the pointer is adjusted using
	the offset from the vtable and the offset of the destination
	class entry.
</OL>

<DT><P><B>There is no relationship between the types, so the cast must cross the
    hierarchy in the most-derived class</B>
<DD>
<UL>
<PRE>
void* __Crun::cross_cast(
	    void* opnd,			// original pointer
	    static_type_info* sclass,	// source class
	    static_type_info* dclass);	// destination class
</PRE>
</UL>
<P>    The algorithm is:
<oL>
<LI>	If the opnd is NULL, return NULL.

<LI>	Search the base table from first to last, looking for a match
	with the source class that has the same offset as the original
	subobject.

<LI>	If this search fails, we have an internal error.

<LI>	If the "private" bit is set in this base entry, the cast fails,
	return NULL

<LI>	Beginning again from the start, search the base table toward
	the last, looking for a match with the destination class.
	
<LI>	If the destination class is not found, or if the "private" bit
	is set, the cast fails, return NULL

<LI>	Continue searching for the destination class.  If it is found,
	the cast fails, return NULL

<LI>	Otherwise, the cast succeeds, and the pointer is adjusted using
	the offset from the vtable and the offset of the destination
	class entry.
</OL>
</DL>
<P>The reference casts are identical, except that they throw an exception
instead of returning NULL.  The corresponding functions are:
<UL>
<PRE>
void* __Crun::ref_simple_down_cast(
	    void* opnd,			// original pointer
	    static_type_info* dclass);	// destination class

void* __Crun::ref_down_cast(
	    void* opnd,			// Original pointer
	    static_type_info* sclass,	// source class
	    static_type_info* dclass);	// destination class

void* __Crun::ref_cross_cast(
	    void* opnd,			// original pointer
	    static_type_info* sclass,	// source class
	    static_type_info* dclass);	// destination class
</PRE>
</UL>
<H3>Typeid</H3>

<P>Objects of type "type_info" are required to be polymorphic, which means
that they have vtable pointers, and these pointers are not self-relative
or position-independent.  The practical consequence of this is that 
type_info objects cannot be allocated in readonly memory.  They could
be statically allocated, but this has the disadvantage that they then
go into global data, expanding that area and forcing the program toward
big PIC code, with attendent overheads.

<P>Since the use of type_info objects is probably going to be rare, and
in many cases will be associated with expensive operations like IO,
it seems better to allocate them dynamically as needed.
<PRE>
    class type_info {
    public:
	// Operators ignored

    private:
	const static_type_info* data;
    };
</PRE>
Type_info objects then will consist of two pointers, on to the virtual
table and one to the corresponding static_type_info object generated
by the compiler. There is no need for the objects to be unique, as all
comparisons are done on the type hash and pointer data.  It would probably
be well to allocate space in groups, and to use a small hash table based
on the address of the static information to keep allocation down.

<P>"typeid" can be applied either statically or dynamically.
<OL>
<LI>  Dynamic determination, must be a polymorphic class

    <P>Calls the function
<PRE>
	const type_info& __Crun::get_typeid(
		    void* opnd);		// The object pointer
</PRE>
    This function extracts the static_type_info from the virtual table
    and creates a type_info object.  If "opnd" is void it throws an
    exception.

<LI>  Static determination, could be any type

    <P>Calls the function
<PRE>
	const type_info& __Crun::make_typeid(
		    static_type_info* data);	// static data
</PRE>
    This function creates a type_info object with the supplied static data.
</OL>
<H3>Exception Interface</H3>
The exception matching and casting rules are not the same as dynamic cast,
so we need an interface to provide RTTI services for exceptions.
<DL>
<DT>
<pre>
bool __Cimpl::exception_matches(
		const __Crun::static_type_info* src,
		const __Crun::static_type_info* dest);
</pre>
<DD>True if the catch type represented by "dest" is a valid match for the
static exception type, represented by "src".
<DT>
<pre>
void* __Cimpl::exception_adjust(
		const __Crun::static_type_info* src,
		const __Crun::static_type_info* dest,
		void* obj);
</pre>
<DD>Assuming that we have found an exception match, make any necessary
offset adjustment required to cast from the source type to the
destination type.  This always casts up the hierarchy, doing the
equivalent of a static_cast.  Note when using this that if the
thrown type is a pointer this adjustment should be applied to the
thrown value itself, rather than to the pointer to the thrown object.
<DT>
<PRE>
bool __Cimpl::is_bad_exception(const __Crun::static_type_info* src);
</pre>
<DD> True if the argument is the static type info object for the
"bad_exception" type.  This is needed while handling unexpected() calls
</DL>

<H3>Generation Strategy</H3>

<P>Static type info blocks have a name formed by appending the mangled
name for the represented type to "__RTTI__".  The namespace in which
the blocks are placed will depend on where the block is generated,
not on the type represented.

<P>There are three algorithms for determining the location of static
information blocks.
<OL>
<LI>For a polymorphic class with a non-inline, non-pure virtual function,
    the virtual table and static type data for that class are generated
    as global definitions in the compilation unit containing the definition
    of that function.  The static type data will be generated in the
    innermost namespace enclosing the class.
    In the same compilation unit we will generate
    the static data for a pointer to the class and a pointer to const
    class.  These will share a single base class table, which is
    considered a static member of the class and will also be generated there.
    That is, for "class ns::foo", we will generate
<UL>
<TABLE>
<TR><TD>	ns::foo::_vtbl		<TD>The virtual table
<TR><TD>	ns::foo::__BASE_TABLE__	<TD>The base table for foo
<TR><TD>	ns::__RTTI__&lt;foo>	<TD>foo static data
<TR><TD>	ns::__RTTI__&lt;foo>	<TD>foo* static data
<TR><TD>	ns::__RTTI__&lt;const foo*>	<TD>const foo* static data
</TABLE>
</UL>
<LI>  For builtin and very common types the static data will be generated in
    the support library.  These will be generated in namespace "__Crun".
    Generation of library type_info data can be enabled with the pragma:
<PRE>
	#pragma generate_library(static_type_info)
</PRE>
    A tentative list of library type data is:
<UL>
<LI>	All builtin types
<LI>	void*
<LI>	char*
<LI>	const char*
<LI>	wchar_t*
<LI>	const wchar_t*
</UL>
   <P> NOTE:  This is not yet implemented.  Currently, these types are handled
    as in case 3.

<LI>For all other types, static type information is generated as a weak
    global variable in any compilation unit in which it is needed.
    Such blocks are generated in file_scope.  The
    symbol is made a weak global rather than a static to simplify
    generation of unique type_info objects.
</OL>
<H3>Debugger interface</H3>
<P>When compiled with debugging enabled, each generated RTTI
block will have a corresponding RTTI stab to map the type onto the symbol
name.  The following functions provide a relatively simple interface
to the rtti functionality

<DL>
<DT>
<PRE>
extern "C" const type_info* __exdbg_get_typeinfo(
			const static_type_info*); </PRE>
<DD>
Obtains a pointer to a type_info object corresponding to the pointer to
a static_type_info object.  There is no guarantee that there is only
one type_info object per type.
<DT>
<PRE>
extern "C" void* __exdbg_dynamic_cast(
			void* obj,
			const static_type_info* source,
			const static_type_info* dest); </PRE>
<DD>
Given a pointer to a polymorphic object, apply a dynamic cast to that
object.  "source" is the static_type_info for the static type of the
object and "dest" is the static_type_info for the desired type.  The
result will be an appropriately adjusted pointer if the cast succeeds
or NULL if the cast fails.  A NULL pointer will also return NULL rather
than throwing an exception
</DL>
</BODY>
</HTML>