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