OSDN Git Service

* config/cpu/arm/cxxabi_tweaks.h: Define __cxa_vec_ctor_return and
[pf3gnuchains/gcc-fork.git] / 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, 59 Temple Place - Suite 330,
20 // Boston, MA 02111-1307, 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                 void (*constructor) (void *),
74                 void (*destructor) (void *))
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                  void (*constructor) (void *),
86                  void (*destructor) (void *),
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                  void (*constructor) (void *),
124                  void (*destructor) (void *),
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                  void (*constructor) (void *),
163                  void (*destructor) (void *))
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                   void (*constructor) (void *, void *),
192                   void (*destructor) (void *))
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                  void (*destructor) (void *))
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                     void (*destructor) (void *))
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                    void (*destructor) (void *))
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                     void (*destructor) (void *),
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                      void (*destructor) (void *),
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