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