xref: /openbsd-src/gnu/gcc/libstdc++-v3/libsupc++/vec.cc (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
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();
~uncatch_exception__cxxabiv1::__anoncf5cc0610111::uncatch_exception46       ~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 
uncatch_exception()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 *
__cxa_vec_new(std::size_t element_count,std::size_t element_size,std::size_t padding_size,__cxa_cdtor_type constructor,__cxa_cdtor_type destructor)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 *
__cxa_vec_new2(std::size_t element_count,std::size_t element_size,std::size_t padding_size,__cxa_cdtor_type constructor,__cxa_cdtor_type destructor,void * (* alloc)(std::size_t),void (* dealloc)(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 *
__cxa_vec_new3(std::size_t element_count,std::size_t element_size,std::size_t padding_size,__cxa_cdtor_type constructor,__cxa_cdtor_type destructor,void * (* alloc)(std::size_t),void (* dealloc)(void *,std::size_t))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
__cxa_vec_ctor(void * array_address,std::size_t element_count,std::size_t element_size,__cxa_cdtor_type constructor,__cxa_cdtor_type destructor)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
__cxa_vec_cctor(void * dest_array,void * src_array,std::size_t element_count,std::size_t element_size,__cxa_cdtor_return_type (* constructor)(void *,void *),__cxa_cdtor_type destructor)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
__cxa_vec_dtor(void * array_address,std::size_t element_count,std::size_t element_size,__cxa_cdtor_type destructor)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
__cxa_vec_cleanup(void * array_address,std::size_t element_count,std::size_t element_size,__cxa_cdtor_type destructor)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
__cxa_vec_delete(void * array_address,std::size_t element_size,std::size_t padding_size,__cxa_cdtor_type destructor)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
__cxa_vec_delete2(void * array_address,std::size_t element_size,std::size_t padding_size,__cxa_cdtor_type destructor,void (* dealloc)(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
__cxa_vec_delete3(void * array_address,std::size_t element_size,std::size_t padding_size,__cxa_cdtor_type destructor,void (* dealloc)(void *,std::size_t))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 *
__aeabi_vec_ctor_nocookie_nodtor(void * array_address,abi::__cxa_cdtor_type constructor,std::size_t element_size,std::size_t element_count)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 *
__aeabi_vec_ctor_cookie_nodtor(void * array_address,abi::__cxa_cdtor_type constructor,std::size_t element_size,std::size_t element_count)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 *
__aeabi_vec_cctor_nocookie_nodtor(void * dest_array,void * src_array,std::size_t element_size,std::size_t element_count,void * (* constructor)(void *,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 *
__aeabi_vec_new_cookie_noctor(std::size_t element_size,std::size_t element_count)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 *
__aeabi_vec_new_nocookie(std::size_t element_size,std::size_t element_count,abi::__cxa_cdtor_type constructor)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 *
__aeabi_vec_new_cookie_nodtor(std::size_t element_size,std::size_t element_count,abi::__cxa_cdtor_type constructor)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 *
__aeabi_vec_new_cookie(std::size_t element_size,std::size_t element_count,abi::__cxa_cdtor_type constructor,abi::__cxa_cdtor_type destructor)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 *
__aeabi_vec_dtor(void * array_address,abi::__cxa_cdtor_type destructor,std::size_t element_size,std::size_t element_count)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 *
__aeabi_vec_dtor_cookie(void * array_address,abi::__cxa_cdtor_type destructor)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
__aeabi_vec_delete(void * array_address,abi::__cxa_cdtor_type destructor)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
__aeabi_vec_delete3(void * array_address,abi::__cxa_cdtor_type destructor,void (* dealloc)(void *,std::size_t))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
__aeabi_vec_delete3_nodtor(void * array_address,void (* dealloc)(void *,std::size_t))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
__aeabi_atexit(void * object,void (* destructor)(void *),void * dso_handle)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__)
513