gcc41 removal: Part 1 of 2: makefiles
[dragonfly.git] / contrib / gcc-4.1 / libstdc++-v3 / libsupc++ / vec.cc
1 // New abi Support -*- C++ -*-
2
3 // Copyright (C) 2000, 2001, 2003, 2004 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, 51 Franklin Street, Fifth Floor,
20 // Boston, MA 02110-1301, 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     private:
51       uncatch_exception&
52       operator=(const uncatch_exception&);
53
54       uncatch_exception(const uncatch_exception&);
55     };
56
57     uncatch_exception::uncatch_exception() : p(0)
58     {
59       __cxa_eh_globals *globals = __cxa_get_globals_fast ();
60
61       p = globals->caughtExceptions;
62       p->handlerCount -= 1;
63       globals->caughtExceptions = p->nextException;
64       globals->uncaughtExceptions += 1;
65     }
66   }
67
68   // Allocate and construct array.
69   extern "C" void *
70   __cxa_vec_new(std::size_t element_count,
71                 std::size_t element_size,
72                 std::size_t padding_size,
73                 __cxa_cdtor_type constructor,
74                 __cxa_cdtor_type destructor)
75   {
76     return __cxa_vec_new2(element_count, element_size, padding_size,
77                            constructor, destructor,
78                            &operator new[], &operator delete []);
79   }
80
81   extern "C" void *
82   __cxa_vec_new2(std::size_t element_count,
83                  std::size_t element_size,
84                  std::size_t padding_size,
85                  __cxa_cdtor_type constructor,
86                  __cxa_cdtor_type destructor,
87                  void *(*alloc) (std::size_t),
88                  void (*dealloc) (void *))
89   {
90     std::size_t size = element_count * element_size + padding_size;
91     char *base = static_cast <char *> (alloc (size));
92     if (!base)
93       return base;
94
95     if (padding_size)
96       {
97         base += padding_size;
98         reinterpret_cast <std::size_t *> (base)[-1] = element_count;
99 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
100         reinterpret_cast <std::size_t *> (base)[-2] = element_size;
101 #endif
102       }
103     try
104       {
105         __cxa_vec_ctor(base, element_count, element_size,
106                        constructor, destructor);
107       }
108     catch (...)
109       {
110         {
111           uncatch_exception ue;
112           dealloc(base - padding_size);
113         }
114         __throw_exception_again;
115       }
116     return base;
117   }
118   
119   extern "C" void *
120   __cxa_vec_new3(std::size_t element_count,
121                  std::size_t element_size,
122                  std::size_t padding_size,
123                  __cxa_cdtor_type constructor,
124                  __cxa_cdtor_type destructor,
125                  void *(*alloc) (std::size_t),
126                  void (*dealloc) (void *, std::size_t))
127   {
128     std::size_t size = element_count * element_size + padding_size;
129     char *base = static_cast<char *>(alloc (size));
130     if (!base)
131       return base;
132     
133     if (padding_size)
134       {
135         base += padding_size;
136         reinterpret_cast<std::size_t *>(base)[-1] = element_count;
137 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
138         reinterpret_cast <std::size_t *> (base)[-2] = element_size;
139 #endif
140       }
141     try
142       {
143         __cxa_vec_ctor(base, element_count, element_size,
144                        constructor, destructor);
145       }
146     catch (...)
147       {
148         {
149           uncatch_exception ue;
150           dealloc(base - padding_size, size);
151         }
152         __throw_exception_again;
153       }
154     return base;
155   }
156   
157   // Construct array.
158   extern "C" __cxa_vec_ctor_return_type
159   __cxa_vec_ctor(void *array_address,
160                  std::size_t element_count,
161                  std::size_t element_size,
162                  __cxa_cdtor_type constructor,
163                  __cxa_cdtor_type destructor)
164   {
165     std::size_t ix = 0;
166     char *ptr = static_cast<char *>(array_address);
167     
168     try
169       {
170         if (constructor)
171           for (; ix != element_count; ix++, ptr += element_size)
172             constructor(ptr);
173       }
174     catch (...)
175       {
176         {
177           uncatch_exception ue;
178           __cxa_vec_cleanup(array_address, ix, element_size, destructor);
179         }
180         __throw_exception_again;
181       }
182     _GLIBCXX_CXA_VEC_CTOR_RETURN (array_address);
183   }
184   
185   // Construct an array by copying.
186   extern "C" __cxa_vec_ctor_return_type
187   __cxa_vec_cctor(void *dest_array,
188                   void *src_array,
189                   std::size_t element_count,
190                   std::size_t element_size,
191                   __cxa_cdtor_return_type (*constructor) (void *, void *),
192                   __cxa_cdtor_type destructor)
193   {
194     std::size_t ix = 0;
195     char *dest_ptr = static_cast<char *>(dest_array);
196     char *src_ptr = static_cast<char *>(src_array);
197     
198     try
199       {
200         if (constructor)
201           for (; ix != element_count; 
202                ix++, src_ptr += element_size, dest_ptr += element_size)
203             constructor(dest_ptr, src_ptr);
204       }
205     catch (...)
206       {
207         {
208           uncatch_exception ue;
209           __cxa_vec_cleanup(dest_array, ix, element_size, destructor);
210         }
211         __throw_exception_again;
212       }
213     _GLIBCXX_CXA_VEC_CTOR_RETURN (dest_array);
214   }
215   
216   // Destruct array.
217   extern "C" void
218   __cxa_vec_dtor(void *array_address,
219                  std::size_t element_count,
220                  std::size_t element_size,
221                  __cxa_cdtor_type destructor)
222   {
223     if (destructor)
224       {
225         char *ptr = static_cast<char *>(array_address);
226         std::size_t ix = element_count;
227
228         ptr += element_count * element_size;
229
230         try
231           {
232             while (ix--)
233               {
234                 ptr -= element_size;
235                 destructor(ptr);
236               }
237           }
238         catch (...)
239           {
240             {
241               uncatch_exception ue;
242               __cxa_vec_cleanup(array_address, ix, element_size, destructor);
243             }
244             __throw_exception_again;
245           }
246       }
247   }
248
249   // Destruct array as a result of throwing an exception.
250   // [except.ctor]/3 If a destructor called during stack unwinding
251   // exits with an exception, terminate is called.
252   extern "C" void
253   __cxa_vec_cleanup(void *array_address,
254                     std::size_t element_count,
255                     std::size_t element_size,
256                     __cxa_cdtor_type destructor)
257   {
258     if (destructor)
259       {
260         char *ptr = static_cast <char *> (array_address);
261         std::size_t ix = element_count;
262
263         ptr += element_count * element_size;
264
265         try
266           {
267             while (ix--)
268               {
269                 ptr -= element_size;
270                 destructor(ptr);
271               }
272           }
273         catch (...)
274           {
275             std::terminate();
276           }
277       }
278   }
279
280   // Destruct and release array.
281   extern "C" void
282   __cxa_vec_delete(void *array_address,
283                    std::size_t element_size,
284                    std::size_t padding_size,
285                    __cxa_cdtor_type destructor)
286   {
287     __cxa_vec_delete2(array_address, element_size, padding_size,
288                        destructor,
289                        &operator delete []);
290   }
291
292   extern "C" void
293   __cxa_vec_delete2(void *array_address,
294                     std::size_t element_size,
295                     std::size_t padding_size,
296                     __cxa_cdtor_type destructor,
297                     void (*dealloc) (void *))
298   {
299     if (!array_address)
300       return;
301
302     char* base = static_cast<char *>(array_address);
303   
304     if (padding_size)
305       {
306         std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1];
307         base -= padding_size;
308         try
309           {
310             __cxa_vec_dtor(array_address, element_count, element_size,
311                            destructor);
312           }
313         catch (...)
314           {
315             {
316               uncatch_exception ue;
317               dealloc(base);
318             }
319             __throw_exception_again;
320           }
321       }
322     dealloc(base);
323   }
324
325   extern "C" void
326   __cxa_vec_delete3(void *array_address,
327                     std::size_t element_size,
328                     std::size_t padding_size,
329                      __cxa_cdtor_type destructor,
330                     void (*dealloc) (void *, std::size_t))
331   {
332     if (!array_address)
333       return;
334
335     char* base = static_cast <char *> (array_address);
336     std::size_t size = 0;
337
338     if (padding_size)
339       {
340         std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1];
341         base -= padding_size;
342         size = element_count * element_size + padding_size;
343         try
344           {
345             __cxa_vec_dtor(array_address, element_count, element_size,
346                            destructor);
347           }
348         catch (...)
349           {
350             {
351               uncatch_exception ue;
352               dealloc(base, size);
353             }
354             __throw_exception_again;
355           }
356       }
357     dealloc(base, size);
358   }
359 } // namespace __cxxabiv1
360
361 #if defined(__arm__) && defined(__ARM_EABI__)
362
363 // The ARM C++ ABI requires that the library provide these additional
364 // helper functions.  There are placed in this file, despite being
365 // architecture-specifier, so that the compiler can inline the __cxa
366 // functions into these functions as appropriate.
367
368 namespace __aeabiv1
369 {
370   extern "C" void *
371   __aeabi_vec_ctor_nocookie_nodtor (void *array_address,
372                                     abi::__cxa_cdtor_type constructor,
373                                     std::size_t element_size,
374                                     std::size_t element_count)
375   {
376     return abi::__cxa_vec_ctor (array_address, element_count, element_size,
377                                 constructor, /*destructor=*/NULL);
378   }
379
380   extern "C" void *
381   __aeabi_vec_ctor_cookie_nodtor (void *array_address,
382                                   abi::__cxa_cdtor_type constructor,
383                                   std::size_t element_size,
384                                   std::size_t element_count)
385   {
386     if (array_address == NULL)
387       return NULL;
388
389     array_address = reinterpret_cast<std::size_t *>(array_address) + 2;
390     reinterpret_cast<std::size_t *>(array_address)[-2] = element_size;
391     reinterpret_cast<std::size_t *>(array_address)[-1] = element_count;
392     return abi::__cxa_vec_ctor (array_address,
393                                 element_count, element_size, 
394                                 constructor, /*destructor=*/NULL);
395   }
396   
397   extern "C" void *
398   __aeabi_vec_cctor_nocookie_nodtor (void *dest_array,
399                                      void *src_array, 
400                                      std::size_t element_size, 
401                                      std::size_t element_count,
402                                      void *(*constructor) (void *, void *))
403   {
404     return abi::__cxa_vec_cctor (dest_array, src_array,
405                                  element_count, element_size,
406                                  constructor, NULL);
407   }
408
409   extern "C" void *
410   __aeabi_vec_new_cookie_noctor (std::size_t element_size, 
411                                  std::size_t element_count)
412   {
413     return abi::__cxa_vec_new(element_count, element_size, 
414                               2 * sizeof (std::size_t),
415                               /*constructor=*/NULL, /*destructor=*/NULL);
416   }
417
418   extern "C" void *
419   __aeabi_vec_new_nocookie (std::size_t element_size, 
420                             std::size_t element_count,
421                             abi::__cxa_cdtor_type constructor)
422   {
423     return abi::__cxa_vec_new (element_count, element_size, 0, constructor, 
424                                NULL);
425   }
426
427   extern "C" void *
428   __aeabi_vec_new_cookie_nodtor (std::size_t element_size, 
429                                  std::size_t element_count,
430                                  abi::__cxa_cdtor_type constructor)
431   {
432     return abi::__cxa_vec_new(element_count, element_size, 
433                               2 * sizeof (std::size_t),
434                               constructor, NULL);
435   }
436
437   extern "C" void *
438   __aeabi_vec_new_cookie(std::size_t element_size, 
439                          std::size_t element_count,
440                          abi::__cxa_cdtor_type constructor,
441                          abi::__cxa_cdtor_type destructor)
442   {
443     return abi::__cxa_vec_new (element_count, element_size, 
444                                2 * sizeof (std::size_t),
445                                constructor, destructor);
446   }
447
448   
449   extern "C" void *
450   __aeabi_vec_dtor (void *array_address, 
451                     abi::__cxa_cdtor_type destructor,
452                     std::size_t element_size, 
453                     std::size_t element_count)
454   {
455     abi::__cxa_vec_dtor (array_address, element_count, element_size, 
456                          destructor);
457     return reinterpret_cast<std::size_t*> (array_address) - 2;
458   }
459
460   extern "C" void *
461   __aeabi_vec_dtor_cookie (void *array_address, 
462                            abi::__cxa_cdtor_type destructor)
463   {
464     abi::__cxa_vec_dtor (array_address, 
465                          reinterpret_cast<std::size_t *>(array_address)[-1],
466                          reinterpret_cast<std::size_t *>(array_address)[-2],
467                          destructor);
468     return reinterpret_cast<std::size_t*> (array_address) - 2;
469   }
470   
471   
472   extern "C" void
473   __aeabi_vec_delete (void *array_address, 
474                       abi::__cxa_cdtor_type destructor)
475   {
476     abi::__cxa_vec_delete (array_address,
477                            reinterpret_cast<std::size_t *>(array_address)[-2],
478                            2 * sizeof (std::size_t),
479                            destructor);
480   }
481
482   extern "C" void
483   __aeabi_vec_delete3 (void *array_address, 
484                        abi::__cxa_cdtor_type destructor,
485                        void (*dealloc) (void *, std::size_t))
486   {
487     abi::__cxa_vec_delete3 (array_address,
488                             reinterpret_cast<std::size_t *>(array_address)[-2],
489                             2 * sizeof (std::size_t),
490                             destructor, dealloc);
491   }
492
493   extern "C" void
494   __aeabi_vec_delete3_nodtor (void *array_address,
495                               void (*dealloc) (void *, std::size_t))
496   {
497     abi::__cxa_vec_delete3 (array_address,
498                             reinterpret_cast<std::size_t *>(array_address)[-2],
499                             2 * sizeof (std::size_t),
500                             /*destructor=*/NULL, dealloc);
501   }
502   
503   extern "C" int
504   __aeabi_atexit (void *object, 
505                   void (*destructor) (void *),
506                   void *dso_handle)
507   {
508     return abi::__cxa_atexit(destructor, object, dso_handle);
509   }
510 } // namespace __aeabiv1
511
512 #endif // defined(__arm__) && defined(__ARM_EABI__)