ABI Document Update
Mark Mitchell
mark at codesourcery.com
Fri Sep 6 20:56:59 UTC 2002
I updated the ABI document, as indicated by this patch.
The changes include:
1. Clarifying that, when name-mangling, there can be ternary
operators. (Namely, the conditional operator. We had already
specified "qu", but not extended the mangling grammar.)
2. Clarifying the meaning of "low-order byte" as applicable to
guard variables.
3. Removing some of the old change indications; they've all been
there fore at least a year.
None of these are substantive changes; just clarifications. Still,
please look at the patch and make sure that you agree.
--
Mark Mitchell mark at codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
Index: abi.html
===================================================================
RCS file: /usr/local/Repository/cxx-abi/abi.html,v
retrieving revision 1.28
diff -c -p -r1.28 abi.html
*** abi.html 2002/08/29 18:05:51 1.28
--- abi.html 2002/09/06 20:51:43
***************
*** 15,24 ****
C++ ABI for Itanium (Draft)
</b></i></font>
- <font size=-1>
- <p>
- <i>Revised 20 March 2001</i>
-
</center>
</HEAD>
--- 15,20 ----
*************** Update sizeof(C) to max (sizeof(C), offs
*** 842,857 ****
If non-empty, also update align(C) and dsize(C) as in II-2.
<p>
! The primary base class has already been allocated in I-2b.
! Any indirect primary base class E of the current class C,
! <span class="change">i.e. one</span>
! that has been chosen as the primary base class of some other base class
! (direct or indirect, virtual or non-virtual) of C,
! will be allocated as part of that other base class,
! and is not allocated here.
! If E is a primary base class of more than one other base,
! the instance used as its allocation in C shall be the first such
! in the inheritance graph order.
<i>
<p>
--- 838,851 ----
If non-empty, also update align(C) and dsize(C) as in II-2.
<p>
! The primary base class has already been allocated in I-2b. Any
! indirect primary base class E of the current class C, i.e. one that
! has been chosen as the primary base class of some other base class
! (direct or indirect, virtual or non-virtual) of C, will be allocated
! as part of that other base class, and is not allocated here. If E is
! a primary base class of more than one other base, the instance used as
! its allocation in C shall be the first such in the inheritance graph
! order.
<i>
<p>
*************** the execution of proper base class const
*** 1490,1505 ****
These virtual tables are for specific cases of virtual inheritance.
<p>
! During the construction of a class object,
! the object assumes the type of each of its proper 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.
! <span class="change">RTTI queries,
! dynamic casts and virtual calls of the object under construction statically
! converted to bases of the base under construction will dynamically
! resolve to the type of the base under construction.</span>
Normally, this behavior is accomplished by setting,
in the base class constructor,
--- 1484,1498 ----
These virtual tables are for specific cases of virtual inheritance.
<p>
! During the construction of a class object, the object assumes the type
! of each of its proper 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. RTTI
! queries, dynamic casts and virtual calls of the object under
! construction statically converted to bases of the base under
! construction will dynamically resolve to the type of the base under
! construction.
Normally, this behavior is accomplished by setting,
in the base class constructor,
*************** proper base class constructor can find i
*** 1538,1551 ****
Construction virtual tables are used in a similar way during the
execution of proper base class destructors.
- <div class="change">
<p>
<img src="warning.gif" alt="NOTE">
<i>
! When a complete object constructor is constructing a virtual base, it must
! determine the base's location statically, rather than using vbase offsets
! in the virtual table, since the possibly shared virtual pointer may
! point to a construction virtual table of an unrelated base class.
For instance, in
<pre><code>
--- 1531,1543 ----
Construction virtual tables are used in a similar way during the
execution of proper base class destructors.
<p>
<img src="warning.gif" alt="NOTE">
<i>
! When a complete object constructor is constructing a virtual base, it
! must be wary of using the vbase offsets in the virtual table, since
! the possibly shared virtual pointer may point to a construction
! virtual table of an unrelated base class.
For instance, in
<pre><code>
*************** constructor is about to construct U, tha
*** 1559,1565 ****
a virtual table for T, and therefore cannot be used to locate U.
</i>
</p>
- </div>
<p>
<h4> 2.6.2 VTT Order</h4>
--- 1551,1556 ----
*************** non-virtual subobjects encountered in ea
*** 1603,1651 ****
<p>
<li>
<i>Secondary virtual pointers</i>:
! For each subobject X with either (a) virtual bases
! or (b) <span class="change"><strike>virtual function declarations overridden
! along a virtual path</strike> reachable along a virtual path from D</span>,
! the address of the secondary virtual table for X-in-D.
! These include virtual and non-virtual, direct and indirect subobjects,
! with the exception of primary non-virtual bases.
! The order of the virtual pointers is
! inheritance graph preorder.
<i>
Though primary non-virtual bases do not get secondary virtual pointers,
they do not otherwise affect the ordering.
</i>
- <div class="change">
- <p><strike>
- When constructing a sub-VTT for a subclass B of D in part 2 above,
- the relevant condition (b) for the inclusion of a secondary virtual
- pointer in the sub-VTT for B is the existence of a virtual function
- declaration overridden along a virtual path between the declaration and B,
- since otherwise the complete object virtual table for B is used
- to initialize the B subobject.
- </strike></p>
- </div>
-
<p>
<img src=warning.gif alt="<b>NOTE</b>:">
<i>
"Along a virtual path" refers to the path in the inheritance graph
- <span class="change">
- <strike>between the class that declares the overridden virtual function
- and the class derived from it that declares the overriding virtual
- function</strike>
between X and D.
- </span>
This is considered a virtual path if one of the class derivations it
! represents is
! <span class="change">
! <strike>from a virtual base.</strike>
! a virtual base of D.
! </span>
</i>
- <div class="change">
<p>
<img src=warning.gif alt="<b>NOTE</b>:">
<i>
--- 1594,1618 ----
<p>
<li>
<i>Secondary virtual pointers</i>:
! For each subobject X with either (a) virtual bases or (b) reachable
! along a virtual path from D, the address of the secondary virtual
! table for X-in-D. These include virtual and non-virtual, direct and
! indirect subobjects, with the exception of primary non-virtual bases.
! The order of the virtual pointers is inheritance graph preorder.
<i>
Though primary non-virtual bases do not get secondary virtual pointers,
they do not otherwise affect the ordering.
</i>
<p>
<img src=warning.gif alt="<b>NOTE</b>:">
<i>
"Along a virtual path" refers to the path in the inheritance graph
between X and D.
This is considered a virtual path if one of the class derivations it
! represents is a virtual base of D.
</i>
<p>
<img src=warning.gif alt="<b>NOTE</b>:">
<i>
*************** table pointer. Should that primary virtu
*** 1657,1663 ****
instance within the most derived object, the secondary virtual pointer
will be different.
</i>
- </div>
<p>
<img src=warning.gif alt="<b>NOTE</b>:">
--- 1624,1629 ----
*************** particular construction virtual table ex
*** 1735,1741 ****
<p>
For example, suppose we have the following hierarchy:
</i>
- <div class="change">
<code><pre>
class A1 { int i; };
class A2 { int i; virtual void f(); };
--- 1701,1706 ----
*************** For example, suppose we have the followi
*** 1756,1762 ****
// C1 is primary base, C2 is secondary base, C3 is non-polymorphic
</pre></code>
- </div>
<i>
Then the VTT for D would appear in the following order,
--- 1721,1726 ----
*************** where indenting indicates the sub-VTT st
*** 1764,1770 ****
and asterisks (*) indicate that construction virtual tables instead of
complete object virtual tables are required.
</i>
- <div class="change">
<code><pre>
// 1. Primary virtual pointer:
[0] D has virtual bases (complete object vptr)
--- 1728,1733 ----
*************** complete object virtual tables are requi
*** 1798,1810 ****
// (V3 has no virtual bases)
</pre></code>
- </div>
<p>
<i>
If A2 is a virtual base of V1,
! the VTT will contain <span class="change"><strike>14</strike> more</span>
! more elements
(exercise left to the astute reader).
</i>
--- 1761,1771 ----
// (V3 has no virtual bases)
</pre></code>
<p>
<i>
If A2 is a virtual base of V1,
! the VTT will contain more elements
(exercise left to the astute reader).
</i>
*************** parameter.
*** 2697,2725 ****
<p>
<h4> 3.1.3 Empty Parameters </h4>
- <div class="change">
- <p>
- <strike>
- A parameter of an empty class type will normally occupy a position
- in the parameter sequence as though it were a single-byte integer.
- There is one exception:
- </p>
- <ul>
-
- <p>
- <li>
- If the type has a non-trivial copy constructor,
- it must be passed by reference as described in Section 3.1.1 above.
-
- </ul>
- </strike>
-
<p>
Empty classes will be passed no differently from ordinary classes. If
passed in registers the NaT bit must not be set on all registers that
make up the class.
</p>
- </div>
<p>
The contents of the single byte parameter slot are unspecified,
--- 2658,2668 ----
*************** A test program for this can be found in
*** 3135,3148 ****
<h4> 3.3.2 One-time Construction API </h4>
<p>
! As described in <a href=#guards>Section 2.8</a>,
! function-scope static objects have associated guard variables used
! to support the requirement that they be initialized exactly once,
! the first time the scope declaring them is entered.
! An implementation that does not anticipate supporting multi-threading
! may simply check the low-order byte of that guard variable,
! initializing if and only if its value is zero,
! and then setting it to a non-zero value.
<p>
However, an implementation intending to support
--- 3078,3091 ----
<h4> 3.3.2 One-time Construction API </h4>
<p>
! As described in <a href=#guards>Section 2.8</a>, function-scope static
! objects have associated guard variables used to support the
! requirement that they be initialized exactly once, the first time the
! scope declaring them is entered. An implementation that does not
! anticipate supporting multi-threading may simply check the first byte
! (i.e., the byte with lowest address) of that guard variable,
! initializing if and only if its value is zero, and then setting it to
! a non-zero value.
<p>
However, an implementation intending to support
*************** and should use the following API to achi
*** 3153,3162 ****
such implementations.
<code><pre>
if ( <i>obj_guard.first_byte</i> == false ) {
! if ( __cxa_guard_acquire (<i>obj_guard</i>) ) {
<i>... initialize the object ...</i>;
<i>... queue object destructor with __cxa_atexit() ...</i>;
! __cxa_guard_release (<i>obj_guard</i>);
}
}
--- 3096,3105 ----
such implementations.
<code><pre>
if ( <i>obj_guard.first_byte</i> == false ) {
! if ( __cxa_guard_acquire (<i>&obj_guard</i>) ) {
<i>... initialize the object ...</i>;
<i>... queue object destructor with __cxa_atexit() ...</i>;
! __cxa_guard_release (<i>&obj_guard</i>);
}
}
*************** The destructor pointer may be NULL,
*** 3366,3372 ****
in which case this routine does nothing.
</dd>
- <div class="change">
<dt><code><pre>
extern "C" void __cxa_vec_cleanup (
void *array_address,
--- 3309,3314 ----
*************** If the destructor throws an exception, c
*** 3383,3389 ****
The destructor pointer may be NULL,
in which case this routine does nothing.
</dd>
- </div>
<dt><code><pre>
extern "C" void __cxa_vec_delete (
--- 3325,3330 ----
*************** are encoded with a void parameter specif
*** 4297,4304 ****
Therefore function types always encode at least one parameter type,
and function manglings can always be distinguished from data manglings
by the presence of the type.
! Member functions do not encode the <span class="change"><strike>type of their implicit <code>this</code> parameter</strike> types of
! implicit parameters, either <code>this</code> or the VTT parameter.</span>
<p>
A "Y" prefix for the bare function type encodes extern "C".
--- 4238,4245 ----
Therefore function types always encode at least one parameter type,
and function manglings can always be distinguished from data manglings
by the presence of the type.
! Member functions do not encode the types of
! implicit parameters, either <code>this</code> or the VTT parameter.
<p>
A "Y" prefix for the bare function type encodes extern "C".
*************** it represents the source token stream.
*** 4460,4465 ****
--- 4401,4407 ----
<pre><font color=blue><code>
<expression> ::= <<i>unary</i> operator-name> <expression>
::= <<i>binary</i> operator-name> <expression> <expression>
+ ::= <<i>trinary</i> operator-name> <expression> <expression> <expression>
::= st <type>
::= <expr-primary>
<expr-primary> ::= <template-param>
*************** with the virtual table mangled name as t
*** 4828,4839 ****
<i>
Note that if the key function is not declared inline in the class definition,
but its definition later is always declared inline,
! it will be emitted in every object containing the definition.
! <span class="change">Note also that if we had thought of it in time, we
! could also have used a pure virtual destructor as the key function, as it
! must be defined even though it is pure.</span>
! </i>
<p>
<a name=vague-rtti></a>
--- 4770,4784 ----
<i>
Note that if the key function is not declared inline in the class definition,
but its definition later is always declared inline,
! it will be emitted in every object containing the definition.</i>
! <p>
! <img src=warning.gif alt="<b>NOTE</b>:">
! <i>In the abstract, a pure virtual destructor could be used as the key
! function, as it must be defined even though it is pure. However, the
! ABI committee did not realize this fact until after the specification
! of key function was complete; therefore a pure virtual destructor
! cannot be the key function.</i>
<p>
<a name=vague-rtti></a>
*************** an implementation using it must emit it
*** 4891,4944 ****
in a COMDAT group identified by the constructor name.
<p>
- <div class=change>
- <strike>
- <a name=vague-vfunc></a>
- <h4> 5.2.6 Virtual Function Override Thunks </h4>
-
- <p>
- Normally, a virtual function override thunk becomes necessary when an
- overriding virtual function is declared.
- In such cases, it is emitted with the overriding virtual function,
- and needs to have vague linkage if and only if the base function does,
- so it should be included in the base function's COMDAT group.
-
- <p>
- However, it is possible to determine that an override thunk is needed
- after the base function is declared.
- For instance, consider this example:
-
- <code><pre>
- struct A { virtual void f(); };
- struct B : virtual public A { int i; };
- struct C : virtual public A { int j; };
- struct D : public B, public C {};
-
- </pre></code>
-
- <p>
- When B and C are declared, A is a primary base in each case,
- so although vcall offsets are allocated in the A-in-B and A-in-C vtables,
- no 'this' adjustment is required and no thunk is generated.
- However, inside D objects, A is no longer a primary base of C,
- and calls to C::f() must adjust 'this' from C* to B::A*,
- so a thunk is required.
-
- <p>
- In such cases, where the need for a thunk is identified
- after the base function is declared,
- the thunk is emitted in a COMDAT group,
- identified by the (mangled) thunk name.
- It must be emitted in the object containing the key function definition
- for any class that causes it to be needed (D in the above example),
- or in all objects referencing it if there is no key function.
- Observe that different class hierarchies with the same virtual base may
- require override thunks for the same base function,
- which will coincide iff the adjustment offsets do.
- </strike>
- </div>
-
- <p>
<a name=vague-itemplate></a>
<h4> 5.2.7 Instantiated Templates</h4>
--- 4836,4841 ----
*************** unwind table location.
*** 4999,5004 ****
--- 4896,4906 ----
<p> <hr> <p>
<p>
+ <font color=blue>[020906]</font>
+ Add trinary expression variant. Remove use of "low-order"
+ to describe bytes in guard variables.
+
+ <p>
<font color=blue>[020827]</font>
Clarify definition of nearly empty class, dsize, nvsize, nvalign.
*************** Selected first variant for empty base al
*** 5258,5264 ****
<hr>
<p>
! Please send corrections to <a href="mailto:samuel at codesourcery.com">Alex Samuel</a>.
</BODY>
</HTML>
--- 5160,5166 ----
<hr>
<p>
! Please send corrections to the <a href="mailto:cxx-abi-dev at codesourcery.com">C++ ABI mailing list</a>.
</BODY>
</HTML>
More information about the cxx-abi-dev
mailing list