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