1e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//===-------------------------- cxa_vector.cpp ---------------------------===//
2e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
3e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//                     The LLVM Compiler Infrastructure
4e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
5e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// This file is dual licensed under the MIT and the University of Illinois Open
6e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Source Licenses. See LICENSE.TXT for details.
7e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
8e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
9e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//  This file implements the "Array Construction and Destruction APIs"
10c82e02dd25b36e5d05cd3644499a553709c9395dJonathan Roelofs//  http://mentorembedded.github.io/cxx-abi/abi.html#array-ctor
11e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
12e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//===----------------------------------------------------------------------===//
13e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
14e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow#include "cxxabi.h"
15e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
16e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow#include <exception>        // for std::terminate
17e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
18e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clownamespace __cxxabiv1 {
19e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
20e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow#pragma mark --Helper routines and classes --
21e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
22e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clownamespace {
23e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    inline static size_t __get_element_count ( void *p ) {
24e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        return static_cast <size_t *> (p)[-1];
25e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        }
26e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
27e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    inline static void __set_element_count ( void *p, size_t element_count ) {
28e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        static_cast <size_t *> (p)[-1] = element_count;
29e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        }
30e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
31e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
32e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//  A pair of classes to simplify exception handling and control flow.
33e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//  They get passed a block of memory in the constructor, and unless the
34e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//  'release' method is called, they deallocate the memory in the destructor.
356d00feffc82d4f8c0201242291a0e93b492e1dd4Howard Hinnant//  Preferred usage is to allocate some memory, attach it to one of these objects,
36e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//  and then, when all the operations to set up the memory block have succeeded,
37e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//  call 'release'. If any of the setup operations fail, or an exception is
38e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//  thrown, then the block is automatically deallocated.
39e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
40e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//  The only difference between these two classes is the signature for the
41e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//  deallocation function (to match new2/new3 and delete2/delete3.
42e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    class st_heap_block2 {
43e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    public:
44e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        typedef void (*dealloc_f)(void *);
45e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
46e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_heap_block2 ( dealloc_f dealloc, void *ptr )
47e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            : dealloc_ ( dealloc ), ptr_ ( ptr ), enabled_ ( true ) {}
48e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        ~st_heap_block2 () { if ( enabled_ ) dealloc_ ( ptr_ ) ; }
49e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void release () { enabled_ = false; }
50e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
51e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    private:
52e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        dealloc_f dealloc_;
53e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void *ptr_;
54e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        bool enabled_;
55e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    };
56e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
57e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    class st_heap_block3 {
58e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    public:
59e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        typedef void (*dealloc_f)(void *, size_t);
60e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
61e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_heap_block3 ( dealloc_f dealloc, void *ptr, size_t size )
62e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            : dealloc_ ( dealloc ), ptr_ ( ptr ), size_ ( size ), enabled_ ( true ) {}
63e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        ~st_heap_block3 () { if ( enabled_ ) dealloc_ ( ptr_, size_ ) ; }
64e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void release () { enabled_ = false; }
65e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
66e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    private:
67e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        dealloc_f dealloc_;
68e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void *ptr_;
69e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t size_;
70e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        bool enabled_;
71e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    };
72e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
73e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    class st_cxa_cleanup {
74e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    public:
75e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        typedef void (*destruct_f)(void *);
76e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
77e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_cxa_cleanup ( void *ptr, size_t &idx, size_t element_size, destruct_f destructor )
78e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            : ptr_ ( ptr ), idx_ ( idx ), element_size_ ( element_size ),
79e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow                destructor_ ( destructor ), enabled_ ( true ) {}
80e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        ~st_cxa_cleanup () {
81e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            if ( enabled_ )
82e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow                __cxa_vec_cleanup ( ptr_, idx_, element_size_, destructor_ );
83e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            }
84e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
85e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void release () { enabled_ = false; }
86e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
87e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    private:
88e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void *ptr_;
89e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t &idx_;
90e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t element_size_;
91e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        destruct_f destructor_;
92e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        bool enabled_;
93e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    };
94e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
95e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    class st_terminate {
96e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    public:
97e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_terminate ( bool enabled = true ) : enabled_ ( enabled ) {}
98e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        ~st_terminate () { if ( enabled_ ) std::terminate (); }
99e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void release () { enabled_ = false; }
100e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    private:
101e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        bool enabled_ ;
102e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    };
103e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
104e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
105e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow#pragma mark --Externally visible routines--
106e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
107e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowextern "C" {
108e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
109e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Equivalent to
110e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
111e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//   __cxa_vec_new2(element_count, element_size, padding_size, constructor,
112e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//                  destructor, &::operator new[], &::operator delete[])
113e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid* __cxa_vec_new(
114e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    size_t element_count, size_t element_size, size_t padding_size,
115e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void (*constructor)(void*), void (*destructor)(void*) ) {
116e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
117e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    return __cxa_vec_new2 ( element_count, element_size, padding_size,
118e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        constructor, destructor, &::operator new [], &::operator delete [] );
119e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
120e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
121e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
122e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
123e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Given the number and size of elements for an array and the non-negative
124e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// size of prefix padding for a cookie, allocate space (using alloc) for
125e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// the array preceded by the specified padding, initialize the cookie if
126e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// the padding is non-zero, and call the given constructor on each element.
127e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Return the address of the array proper, after the padding.
128e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
129e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// If alloc throws an exception, rethrow the exception. If alloc returns
130e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// NULL, return NULL. If the constructor throws an exception, call
131e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// destructor for any already constructed elements, and rethrow the
132e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// exception. If the destructor throws an exception, call std::terminate.
133e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
134e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// The constructor may be NULL, in which case it must not be called. If the
135e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// padding_size is zero, the destructor may be NULL; in that case it must
136e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// not be called.
137e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
138e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Neither alloc nor dealloc may be NULL.
139e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid* __cxa_vec_new2(
140e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    size_t element_count, size_t element_size, size_t padding_size,
141e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void  (*constructor)(void*), void  (*destructor)(void*),
142e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void* (*alloc)(size_t), void  (*dealloc)(void*) ) {
143e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
144e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    const size_t heap_size = element_count * element_size + padding_size;
145e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    char * const heap_block = static_cast<char *> ( alloc ( heap_size ));
146e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    char *vec_base = heap_block;
147e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
148e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    if ( NULL != vec_base ) {
149e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_heap_block2 heap ( dealloc, heap_block );
150e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
151e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    //  put the padding before the array elements
152e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        if ( 0 != padding_size ) {
153e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            vec_base += padding_size;
154e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            __set_element_count ( vec_base, element_count );
155e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        }
156e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
157e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    //  Construct the elements
158e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        __cxa_vec_ctor ( vec_base, element_count, element_size, constructor, destructor );
159e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        heap.release ();    // We're good!
160e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    }
161e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
162e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    return vec_base;
163e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
164e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
165e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
166e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Same as __cxa_vec_new2 except that the deallocation function takes both
167e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// the object address and its size.
168e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid* __cxa_vec_new3(
169e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    size_t element_count, size_t element_size, size_t padding_size,
170e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void  (*constructor)(void*), void  (*destructor)(void*),
171e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void* (*alloc)(size_t), void  (*dealloc)(void*, size_t) ) {
172e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
173e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    const size_t heap_size = element_count * element_size + padding_size;
174e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    char * const heap_block = static_cast<char *> ( alloc ( heap_size ));
175e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    char *vec_base = heap_block;
176e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
177e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    if ( NULL != vec_base ) {
178e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_heap_block3 heap ( dealloc, heap_block, heap_size );
179e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
180e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    //  put the padding before the array elements
181e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        if ( 0 != padding_size ) {
182e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            vec_base += padding_size;
183e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            __set_element_count ( vec_base, element_count );
184e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        }
185e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
186e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    //  Construct the elements
187e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        __cxa_vec_ctor ( vec_base, element_count, element_size, constructor, destructor );
188e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        heap.release ();    // We're good!
189e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    }
190e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
191e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    return vec_base;
192e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
193e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
194e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
195e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Given the (data) addresses of a destination and a source array, an
196e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// element count and an element size, call the given copy constructor to
197e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// copy each element from the source array to the destination array. The
198e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// copy constructor's arguments are the destination address and source
199e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// address, respectively. If an exception occurs, call the given destructor
200e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// (if non-NULL) on each copied element and rethrow. If the destructor
201e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// throws an exception, call terminate(). The constructor and or destructor
202e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// pointers may be NULL. If either is NULL, no action is taken when it
203e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// would have been called.
204e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
205e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid __cxa_vec_cctor( void*  dest_array, void*  src_array,
206e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    size_t element_count, size_t element_size,
207e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void  (*constructor) (void*, void*), void  (*destructor)(void*) ) {
208e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
209e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    if ( NULL != constructor ) {
210e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t idx = 0;
211e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        char *src_ptr  = static_cast<char *>(src_array);
212e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        char *dest_ptr = static_cast<char *>(dest_array);
213e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_cxa_cleanup cleanup ( dest_array, idx, element_size, destructor );
214e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
215e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        for ( idx = 0; idx < element_count;
216e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow                    ++idx, src_ptr += element_size, dest_ptr += element_size )
217e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            constructor ( dest_ptr, src_ptr );
218e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        cleanup.release ();     // We're good!
219e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    }
220e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
221e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
222e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
223e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Given the (data) address of an array, not including any cookie padding,
224e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// and the number and size of its elements, call the given constructor on
225e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// each element. If the constructor throws an exception, call the given
226e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// destructor for any already-constructed elements, and rethrow the
227e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// exception. If the destructor throws an exception, call terminate(). The
228e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// constructor and/or destructor pointers may be NULL. If either is NULL,
229e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// no action is taken when it would have been called.
230e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid __cxa_vec_ctor(
231e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    void*  array_address, size_t element_count, size_t element_size,
232e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow       void (*constructor)(void*), void (*destructor)(void*) ) {
233e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
234e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    if ( NULL != constructor ) {
235e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t idx;
236e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        char *ptr = static_cast <char *> ( array_address );
237e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_cxa_cleanup cleanup ( array_address, idx, element_size, destructor );
238e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
239e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    //  Construct the elements
240e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        for ( idx = 0; idx < element_count; ++idx, ptr += element_size )
241e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            constructor ( ptr );
242e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        cleanup.release ();     // We're good!
243e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    }
244e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
245e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
246e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Given the (data) address of an array, the number of elements, and the
247e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// size of its elements, call the given destructor on each element. If the
248e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// destructor throws an exception, rethrow after destroying the remaining
249e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// elements if possible. If the destructor throws a second exception, call
250e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// terminate(). The destructor pointer may be NULL, in which case this
251e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// routine does nothing.
252e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid __cxa_vec_dtor(
253e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    void*  array_address, size_t element_count, size_t element_size,
254e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow       void (*destructor)(void*) ) {
255e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
256e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    if ( NULL != destructor ) {
257e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        char *ptr = static_cast <char *> (array_address);
258e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t idx = element_count;
259e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_cxa_cleanup cleanup ( array_address, idx, element_size, destructor );
260e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        {
26100cc7d2c79c179b54893ad215679bfae904578f5Howard Hinnant            st_terminate exception_guard (__cxa_uncaught_exception ());
262e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            ptr +=  element_count * element_size;   // one past the last element
263e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
264e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            while ( idx-- > 0 ) {
265e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow                ptr -= element_size;
266e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow                destructor ( ptr );
267e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            }
268e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            exception_guard.release (); //  We're good !
269e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        }
270e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        cleanup.release ();     // We're still good!
271e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    }
272e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
273e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
274e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Given the (data) address of an array, the number of elements, and the
275e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// size of its elements, call the given destructor on each element. If the
276e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// destructor throws an exception, call terminate(). The destructor pointer
277e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// may be NULL, in which case this routine does nothing.
278e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid __cxa_vec_cleanup( void* array_address, size_t element_count,
279e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t element_size, void  (*destructor)(void*) ) {
280e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
281e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    if ( NULL != destructor ) {
282e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        char *ptr = static_cast <char *> (array_address);
283e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t idx = element_count;
284e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_terminate exception_guard;
285e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
286e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        ptr += element_count * element_size;    // one past the last element
287e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        while ( idx-- > 0 ) {
288e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            ptr -= element_size;
289e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            destructor ( ptr );
290e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            }
291e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        exception_guard.release ();     // We're done!
292e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    }
293e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
294e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
295e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
296e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// If the array_address is NULL, return immediately. Otherwise, given the
297e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// (data) address of an array, the non-negative size of prefix padding for
298e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// the cookie, and the size of its elements, call the given destructor on
299e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// each element, using the cookie to determine the number of elements, and
300e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// then delete the space by calling ::operator delete[](void *). If the
301e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// destructor throws an exception, rethrow after (a) destroying the
302e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// remaining elements, and (b) deallocating the storage. If the destructor
303e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// throws a second exception, call terminate(). If padding_size is 0, the
304e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// destructor pointer must be NULL. If the destructor pointer is NULL, no
305e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// destructor call is to be made.
306e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow//
307e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// The intent of this function is to permit an implementation to call this
308e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// function when confronted with an expression of the form delete[] p in
309e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// the source code, provided that the default deallocation function can be
310e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// used. Therefore, the semantics of this function are consistent with
311e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// those required by the standard. The requirement that the deallocation
312e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// function be called even if the destructor throws an exception derives
313e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// from the resolution to DR 353 to the C++ standard, which was adopted in
314e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// April, 2003.
315e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid __cxa_vec_delete( void* array_address,
316e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t element_size, size_t padding_size, void  (*destructor)(void*) ) {
317e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
318e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    __cxa_vec_delete2 ( array_address, element_size, padding_size,
319e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow               destructor, &::operator delete [] );
320e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
321e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
322e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
323e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Same as __cxa_vec_delete, except that the given function is used for
324e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// deallocation instead of the default delete function. If dealloc throws
325e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// an exception, the result is undefined. The dealloc pointer may not be
326e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// NULL.
327e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid __cxa_vec_delete2( void* array_address,
328e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t element_size, size_t padding_size,
329e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void  (*destructor)(void*), void  (*dealloc)(void*) ) {
330e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
331e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    if ( NULL != array_address ) {
332e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        char *vec_base   = static_cast <char *> (array_address);
333e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        char *heap_block = vec_base - padding_size;
334e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_heap_block2 heap ( dealloc, heap_block );
335e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
336e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        if ( 0 != padding_size && NULL != destructor ) // call the destructors
337e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            __cxa_vec_dtor ( array_address, __get_element_count ( vec_base ),
338e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow                                    element_size, destructor );
339e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    }
340e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
341e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
342e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
343e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// Same as __cxa_vec_delete, except that the given function is used for
344e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// deallocation instead of the default delete function. The deallocation
345e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// function takes both the object address and its size. If dealloc throws
346e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// an exception, the result is undefined. The dealloc pointer may not be
347e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow// NULL.
348e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clowvoid __cxa_vec_delete3( void* array_address,
349e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        size_t element_size, size_t padding_size,
350e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        void  (*destructor)(void*), void  (*dealloc) (void*, size_t)) {
351e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
352e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    if ( NULL != array_address ) {
353e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        char *vec_base   = static_cast <char *> (array_address);
354e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        char *heap_block = vec_base - padding_size;
355e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        const size_t element_count = padding_size ? __get_element_count ( vec_base ) : 0;
356e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        const size_t heap_block_size = element_size * element_count + padding_size;
357e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        st_heap_block3 heap ( dealloc, heap_block, heap_block_size );
358e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
359e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow        if ( 0 != padding_size && NULL != destructor ) // call the destructors
360e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow            __cxa_vec_dtor ( array_address, element_count, element_size, destructor );
361e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow    }
362e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}
363e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
364e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
365e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}  // extern "C"
366e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow
367e52bde43f8528bfb81501eeffc4a17b44fdf3bfcMarshall Clow}  // abi
368