OSDN Git Service

* configure.ac: Set ABI_TWEAKS_SRCDIR.
[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" void
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   }
183   
184   // Construct an array by copying.
185   extern "C" void
186   __cxa_vec_cctor(void *dest_array,
187                   void *src_array,
188                   std::size_t element_count,
189                   std::size_t element_size,
190                   void (*constructor) (void *, void *),
191                   void (*destructor) (void *))
192   {
193     std::size_t ix = 0;
194     char *dest_ptr = static_cast<char *>(dest_array);
195     char *src_ptr = static_cast<char *>(src_array);
196     
197     try
198       {
199         if (constructor)
200           for (; ix != element_count; 
201                ix++, src_ptr += element_size, dest_ptr += element_size)
202             constructor(dest_ptr, src_ptr);
203       }
204     catch (...)
205       {
206         {
207           uncatch_exception ue;
208           __cxa_vec_cleanup(dest_array, ix, element_size, destructor);
209         }
210         __throw_exception_again;
211       }
212   }
213   
214   // Destruct array.
215   extern "C" void
216   __cxa_vec_dtor(void *array_address,
217                  std::size_t element_count,
218                  std::size_t element_size,
219                  void (*destructor) (void *))
220   {
221     if (destructor)
222       {
223         char *ptr = static_cast<char *>(array_address);
224         std::size_t ix = element_count;
225
226         ptr += element_count * element_size;
227
228         try
229           {
230             while (ix--)
231               {
232                 ptr -= element_size;
233                 destructor(ptr);
234               }
235           }
236         catch (...)
237           {
238             {
239               uncatch_exception ue;
240               __cxa_vec_cleanup(array_address, ix, element_size, destructor);
241             }
242             __throw_exception_again;
243           }
244       }
245   }
246
247   // Destruct array as a result of throwing an exception.
248   // [except.ctor]/3 If a destructor called during stack unwinding
249   // exits with an exception, terminate is called.
250   extern "C" void
251   __cxa_vec_cleanup(void *array_address,
252                     std::size_t element_count,
253                     std::size_t element_size,
254                     void (*destructor) (void *))
255   {
256     if (destructor)
257       {
258         char *ptr = static_cast <char *> (array_address);
259         std::size_t ix = element_count;
260
261         ptr += element_count * element_size;
262
263         try
264           {
265             while (ix--)
266               {
267                 ptr -= element_size;
268                 destructor(ptr);
269               }
270           }
271         catch (...)
272           {
273             std::terminate();
274           }
275       }
276   }
277
278   // Destruct and release array.
279   extern "C" void
280   __cxa_vec_delete(void *array_address,
281                    std::size_t element_size,
282                    std::size_t padding_size,
283                    void (*destructor) (void *))
284   {
285     __cxa_vec_delete2(array_address, element_size, padding_size,
286                        destructor,
287                        &operator delete []);
288   }
289
290   extern "C" void
291   __cxa_vec_delete2(void *array_address,
292                     std::size_t element_size,
293                     std::size_t padding_size,
294                     void (*destructor) (void *),
295                     void (*dealloc) (void *))
296   {
297     if (!array_address)
298       return;
299
300     char* base = static_cast<char *>(array_address);
301   
302     if (padding_size)
303       {
304         std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1];
305         base -= padding_size;
306         try
307           {
308             __cxa_vec_dtor(array_address, element_count, element_size,
309                            destructor);
310           }
311         catch (...)
312           {
313             {
314               uncatch_exception ue;
315               dealloc(base);
316             }
317             __throw_exception_again;
318           }
319       }
320     dealloc(base);
321   }
322
323   extern "C" void
324   __cxa_vec_delete3(void *array_address,
325                     std::size_t element_size,
326                     std::size_t padding_size,
327                      void (*destructor) (void *),
328                     void (*dealloc) (void *, std::size_t))
329   {
330     if (!array_address)
331       return;
332
333     char* base = static_cast <char *> (array_address);
334     std::size_t size = 0;
335
336     if (padding_size)
337       {
338         std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1];
339         base -= padding_size;
340         size = element_count * element_size + padding_size;
341         try
342           {
343             __cxa_vec_dtor(array_address, element_count, element_size,
344                            destructor);
345           }
346         catch (...)
347           {
348             {
349               uncatch_exception ue;
350               dealloc(base, size);
351             }
352             __throw_exception_again;
353           }
354       }
355     dealloc(base, size);
356   }
357 } // namespace __cxxabiv1
358