Import gcc-4.7.2 to new vendor branch
[dragonfly.git] / contrib / gcc-4.7 / libstdc++-v3 / libsupc++ / vec.cc
1 // New abi Support -*- C++ -*-
2
3 // Copyright (C) 2000, 2001, 2003, 2004, 2009, 2011
4 // Free Software Foundation, Inc.
5 //  
6 // This file is part of GCC.
7 //
8 // GCC is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3, or (at your option)
11 // any later version.
12
13 // GCC is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17
18 // Under Section 7 of GPL version 3, you are granted additional
19 // permissions described in the GCC Runtime Library Exception, version
20 // 3.1, as published by the Free Software Foundation.
21
22 // You should have received a copy of the GNU General Public License and
23 // a copy of the GCC Runtime Library Exception along with this program;
24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 // <http://www.gnu.org/licenses/>.
26
27 // Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>
28
29 #include <cxxabi.h>
30 #include <new>
31 #include <exception>
32 #include <bits/exception_defines.h>
33 #include "unwind-cxx.h"
34
35 namespace __cxxabiv1
36 {
37   namespace 
38   {
39     struct uncatch_exception 
40     {
41       uncatch_exception();
42       ~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); }
43       
44       __cxa_exception* p;
45
46     private:
47       uncatch_exception&
48       operator=(const uncatch_exception&);
49
50       uncatch_exception(const uncatch_exception&);
51     };
52
53     uncatch_exception::uncatch_exception() : p(0)
54     {
55       __cxa_eh_globals *globals = __cxa_get_globals_fast ();
56
57       p = globals->caughtExceptions;
58       p->handlerCount -= 1;
59       globals->caughtExceptions = p->nextException;
60       globals->uncaughtExceptions += 1;
61     }
62   }
63
64   // Allocate and construct array.
65   extern "C" void *
66   __cxa_vec_new(std::size_t element_count,
67                 std::size_t element_size,
68                 std::size_t padding_size,
69                 __cxa_cdtor_type constructor,
70                 __cxa_cdtor_type destructor)
71   {
72     return __cxa_vec_new2(element_count, element_size, padding_size,
73                            constructor, destructor,
74                            &operator new[], &operator delete []);
75   }
76
77   extern "C" void *
78   __cxa_vec_new2(std::size_t element_count,
79                  std::size_t element_size,
80                  std::size_t padding_size,
81                  __cxa_cdtor_type constructor,
82                  __cxa_cdtor_type destructor,
83                  void *(*alloc) (std::size_t),
84                  void (*dealloc) (void *))
85   {
86     std::size_t size = element_count * element_size + padding_size;
87     char *base = static_cast <char *> (alloc (size));
88     if (!base)
89       return base;
90
91     if (padding_size)
92       {
93         base += padding_size;
94         reinterpret_cast <std::size_t *> (base)[-1] = element_count;
95 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
96         reinterpret_cast <std::size_t *> (base)[-2] = element_size;
97 #endif
98       }
99     __try
100       {
101         __cxa_vec_ctor(base, element_count, element_size,
102                        constructor, destructor);
103       }
104     __catch(...)
105       {
106         {
107           uncatch_exception ue;
108           // Core issue 901 will probably be resolved such that a
109           // deleted operator delete means not freeing memory here.
110           if (dealloc)
111             dealloc(base - padding_size);
112         }
113         __throw_exception_again;
114       }
115     return base;
116   }
117   
118   extern "C" void *
119   __cxa_vec_new3(std::size_t element_count,
120                  std::size_t element_size,
121                  std::size_t padding_size,
122                  __cxa_cdtor_type constructor,
123                  __cxa_cdtor_type destructor,
124                  void *(*alloc) (std::size_t),
125                  void (*dealloc) (void *, std::size_t))
126   {
127     std::size_t size = element_count * element_size + padding_size;
128     char *base = static_cast<char *>(alloc (size));
129     if (!base)
130       return base;
131     
132     if (padding_size)
133       {
134         base += padding_size;
135         reinterpret_cast<std::size_t *>(base)[-1] = element_count;
136 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
137         reinterpret_cast <std::size_t *> (base)[-2] = element_size;
138 #endif
139       }
140     __try
141       {
142         __cxa_vec_ctor(base, element_count, element_size,
143                        constructor, destructor);
144       }
145     __catch(...)
146       {
147         {
148           uncatch_exception ue;
149           if (dealloc)
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) throw()
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     if (!array_address)
465       return NULL;
466
467     abi::__cxa_vec_dtor (array_address, 
468                          reinterpret_cast<std::size_t *>(array_address)[-1],
469                          reinterpret_cast<std::size_t *>(array_address)[-2],
470                          destructor);
471     return reinterpret_cast<std::size_t*> (array_address) - 2;
472   }
473   
474   
475   extern "C" void
476   __aeabi_vec_delete (void *array_address, 
477                       abi::__cxa_cdtor_type destructor)
478   {
479     if (!array_address)
480       return;
481
482     abi::__cxa_vec_delete (array_address,
483                            reinterpret_cast<std::size_t *>(array_address)[-2],
484                            2 * sizeof (std::size_t),
485                            destructor);
486   }
487
488   extern "C" void
489   __aeabi_vec_delete3 (void *array_address, 
490                        abi::__cxa_cdtor_type destructor,
491                        void (*dealloc) (void *, std::size_t))
492   {
493     if (!array_address)
494       return;
495
496     abi::__cxa_vec_delete3 (array_address,
497                             reinterpret_cast<std::size_t *>(array_address)[-2],
498                             2 * sizeof (std::size_t),
499                             destructor, dealloc);
500   }
501
502   extern "C" void
503   __aeabi_vec_delete3_nodtor (void *array_address,
504                               void (*dealloc) (void *, std::size_t))
505   {
506     if (!array_address)
507       return;
508
509     abi::__cxa_vec_delete3 (array_address,
510                             reinterpret_cast<std::size_t *>(array_address)[-2],
511                             2 * sizeof (std::size_t),
512                             /*destructor=*/NULL, dealloc);
513   }
514 } // namespace __aeabiv1
515
516 #endif // defined(__arm__) && defined(__ARM_EABI__)