OSDN Git Service

2003-05-24 Nathanael Nerode <neroden@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / libsupc++ / vec.cc
1 // New abi Support -*- C++ -*-
2
3 // Copyright (C) 2000, 2001 Free Software Foundation, Inc.
4 //  
5 // This file is part of GCC.
6 //
7 // GCC is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11
12 // GCC is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License
18 // along with GCC; see the file COPYING.  If not, write to
19 // the Free Software Foundation, 59 Temple Place - Suite 330,
20 // Boston, MA 02111-1307, USA. 
21
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction.  Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License.  This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30
31 // Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>
32
33 #include <cxxabi.h>
34 #include <new>
35 #include <exception>
36 #include <exception_defines.h>
37 #include "unwind-cxx.h"
38
39 namespace __cxxabiv1
40 {
41   namespace 
42   {
43     struct uncatch_exception 
44     {
45       uncatch_exception ();
46       ~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); }
47       
48       __cxa_exception *p;
49     };
50
51     uncatch_exception::uncatch_exception ()
52     {
53       __cxa_eh_globals *globals = __cxa_get_globals_fast ();
54
55       p = globals->caughtExceptions;
56       p->handlerCount -= 1;
57       globals->caughtExceptions = p->nextException;
58       globals->uncaughtExceptions += 1;
59     }
60   }
61
62   // Allocate and construct array.
63   extern "C" void *
64   __cxa_vec_new(std::size_t element_count,
65                 std::size_t element_size,
66                 std::size_t padding_size,
67                 void (*constructor) (void *),
68                 void (*destructor) (void *))
69   {
70     return __cxa_vec_new2(element_count, element_size, padding_size,
71                            constructor, destructor,
72                            &operator new[], &operator delete []);
73   }
74
75   extern "C" void *
76   __cxa_vec_new2(std::size_t element_count,
77                  std::size_t element_size,
78                  std::size_t padding_size,
79                  void (*constructor) (void *),
80                  void (*destructor) (void *),
81                  void *(*alloc) (std::size_t),
82                  void (*dealloc) (void *))
83   {
84     std::size_t size = element_count * element_size + padding_size;
85     char *base = static_cast <char *> (alloc (size));
86     
87     if (padding_size)
88       {
89         base += padding_size;
90         reinterpret_cast <std::size_t *> (base)[-1] = element_count;
91       }
92     try
93       {
94         __cxa_vec_ctor(base, element_count, element_size,
95                        constructor, destructor);
96       }
97     catch (...)
98       {
99         {
100           uncatch_exception ue;
101           dealloc(base - padding_size);
102         }
103         __throw_exception_again;
104       }
105     return base;
106   }
107   
108   extern "C" void *
109   __cxa_vec_new3(std::size_t element_count,
110                  std::size_t element_size,
111                  std::size_t padding_size,
112                  void (*constructor) (void *),
113                  void (*destructor) (void *),
114                  void *(*alloc) (std::size_t),
115                  void (*dealloc) (void *, std::size_t))
116   {
117     std::size_t size = element_count * element_size + padding_size;
118     char *base = static_cast<char *>(alloc (size));
119     
120     if (padding_size)
121       {
122         base += padding_size;
123         reinterpret_cast<std::size_t *>(base)[-1] = element_count;
124       }
125     try
126       {
127         __cxa_vec_ctor(base, element_count, element_size,
128                        constructor, destructor);
129       }
130     catch (...)
131       {
132         {
133           uncatch_exception ue;
134           dealloc(base - padding_size, size);
135         }
136         __throw_exception_again;
137       }
138     return base;
139   }
140   
141   // Construct array.
142   extern "C" void
143   __cxa_vec_ctor(void *array_address,
144                  std::size_t element_count,
145                  std::size_t element_size,
146                  void (*constructor) (void *),
147                  void (*destructor) (void *))
148   {
149     std::size_t ix = 0;
150     char *ptr = static_cast<char *>(array_address);
151     
152     try
153       {
154         if (constructor)
155           for (; ix != element_count; ix++, ptr += element_size)
156             constructor(ptr);
157       }
158     catch (...)
159       {
160         {
161           uncatch_exception ue;
162           __cxa_vec_cleanup(array_address, ix, element_size, destructor);
163         }
164         __throw_exception_again;
165       }
166   }
167   
168   // Construct an array by copying.
169   extern "C" void
170   __cxa_vec_cctor(void *dest_array,
171                   void *src_array,
172                   std::size_t element_count,
173                   std::size_t element_size,
174                   void (*constructor) (void *, void *),
175                   void (*destructor) (void *))
176   {
177     std::size_t ix = 0;
178     char *dest_ptr = static_cast<char *>(dest_array);
179     char *src_ptr = static_cast<char *>(src_array);
180     
181     try
182       {
183         if (constructor)
184           for (; ix != element_count; 
185                ix++, src_ptr += element_size, dest_ptr += element_size)
186             constructor(dest_ptr, src_ptr);
187       }
188     catch (...)
189       {
190         {
191           uncatch_exception ue;
192           __cxa_vec_cleanup(dest_array, ix, element_size, destructor);
193         }
194         __throw_exception_again;
195       }
196   }
197   
198   // Destruct array.
199   extern "C" void
200   __cxa_vec_dtor(void *array_address,
201                  std::size_t element_count,
202                  std::size_t element_size,
203                  void (*destructor) (void *))
204   {
205     if (destructor)
206       {
207         char *ptr = static_cast<char *>(array_address);
208         std::size_t ix = element_count;
209
210         ptr += element_count * element_size;
211
212         try
213           {
214             while (ix--)
215               {
216                 ptr -= element_size;
217                 destructor(ptr);
218               }
219           }
220         catch (...)
221           {
222             {
223               uncatch_exception ue;
224               __cxa_vec_cleanup(array_address, ix, element_size, destructor);
225             }
226             __throw_exception_again;
227           }
228       }
229   }
230
231   // Destruct array as a result of throwing an exception.
232   // [except.ctor]/3 If a destructor called during stack unwinding
233   // exits with an exception, terminate is called.
234   extern "C" void
235   __cxa_vec_cleanup(void *array_address,
236                     std::size_t element_count,
237                     std::size_t element_size,
238                     void (*destructor) (void *))
239   {
240     if (destructor)
241       {
242         char *ptr = static_cast <char *> (array_address);
243         std::size_t ix = element_count;
244
245         ptr += element_count * element_size;
246
247         try
248           {
249             while (ix--)
250               {
251                 ptr -= element_size;
252                 destructor(ptr);
253               }
254           }
255         catch (...)
256           {
257             std::terminate();
258           }
259       }
260   }
261
262   // Destruct and release array.
263   extern "C" void
264   __cxa_vec_delete(void *array_address,
265                    std::size_t element_size,
266                    std::size_t padding_size,
267                    void (*destructor) (void *))
268   {
269     __cxa_vec_delete2(array_address, element_size, padding_size,
270                        destructor,
271                        &operator delete []);
272   }
273
274   extern "C" void
275   __cxa_vec_delete2(void *array_address,
276                     std::size_t element_size,
277                     std::size_t padding_size,
278                     void (*destructor) (void *),
279                     void (*dealloc) (void *))
280   {
281     char *base = static_cast<char *>(array_address);
282   
283     if (padding_size)
284       {
285         std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1];
286         base -= padding_size;
287         try
288           {
289             __cxa_vec_dtor(array_address, element_count, element_size,
290                            destructor);
291           }
292         catch (...)
293           {
294             {
295               uncatch_exception ue;
296               dealloc(base);
297             }
298             __throw_exception_again;
299           }
300       }
301     dealloc(base);
302   }
303
304   extern "C" void
305   __cxa_vec_delete3(void *array_address,
306                     std::size_t element_size,
307                     std::size_t padding_size,
308                      void (*destructor) (void *),
309                     void (*dealloc) (void *, std::size_t))
310   {
311     char *base = static_cast <char *> (array_address);
312     std::size_t size = 0;
313     
314     if (padding_size)
315       {
316         std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1];
317         base -= padding_size;
318         size = element_count * element_size + padding_size;
319         try
320           {
321             __cxa_vec_dtor(array_address, element_count, element_size,
322                            destructor);
323           }
324         catch (...)
325           {
326             {
327               uncatch_exception ue;
328               dealloc(base, size);
329             }
330             __throw_exception_again;
331           }
332       }
333     dealloc(base, size);
334   }
335 } // namespace __cxxabiv1
336