OSDN Git Service

2004-05-22 Benjamin Kosnik <bkoz@redhat.com>
[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       }
100     try
101       {
102         __cxa_vec_ctor(base, element_count, element_size,
103                        constructor, destructor);
104       }
105     catch (...)
106       {
107         {
108           uncatch_exception ue;
109           dealloc(base - padding_size);
110         }
111         __throw_exception_again;
112       }
113     return base;
114   }
115   
116   extern "C" void *
117   __cxa_vec_new3(std::size_t element_count,
118                  std::size_t element_size,
119                  std::size_t padding_size,
120                  void (*constructor) (void *),
121                  void (*destructor) (void *),
122                  void *(*alloc) (std::size_t),
123                  void (*dealloc) (void *, std::size_t))
124   {
125     std::size_t size = element_count * element_size + padding_size;
126     char *base = static_cast<char *>(alloc (size));
127     if (!base)
128       return base;
129     
130     if (padding_size)
131       {
132         base += padding_size;
133         reinterpret_cast<std::size_t *>(base)[-1] = element_count;
134       }
135     try
136       {
137         __cxa_vec_ctor(base, element_count, element_size,
138                        constructor, destructor);
139       }
140     catch (...)
141       {
142         {
143           uncatch_exception ue;
144           dealloc(base - padding_size, size);
145         }
146         __throw_exception_again;
147       }
148     return base;
149   }
150   
151   // Construct array.
152   extern "C" void
153   __cxa_vec_ctor(void *array_address,
154                  std::size_t element_count,
155                  std::size_t element_size,
156                  void (*constructor) (void *),
157                  void (*destructor) (void *))
158   {
159     std::size_t ix = 0;
160     char *ptr = static_cast<char *>(array_address);
161     
162     try
163       {
164         if (constructor)
165           for (; ix != element_count; ix++, ptr += element_size)
166             constructor(ptr);
167       }
168     catch (...)
169       {
170         {
171           uncatch_exception ue;
172           __cxa_vec_cleanup(array_address, ix, element_size, destructor);
173         }
174         __throw_exception_again;
175       }
176   }
177   
178   // Construct an array by copying.
179   extern "C" void
180   __cxa_vec_cctor(void *dest_array,
181                   void *src_array,
182                   std::size_t element_count,
183                   std::size_t element_size,
184                   void (*constructor) (void *, void *),
185                   void (*destructor) (void *))
186   {
187     std::size_t ix = 0;
188     char *dest_ptr = static_cast<char *>(dest_array);
189     char *src_ptr = static_cast<char *>(src_array);
190     
191     try
192       {
193         if (constructor)
194           for (; ix != element_count; 
195                ix++, src_ptr += element_size, dest_ptr += element_size)
196             constructor(dest_ptr, src_ptr);
197       }
198     catch (...)
199       {
200         {
201           uncatch_exception ue;
202           __cxa_vec_cleanup(dest_array, ix, element_size, destructor);
203         }
204         __throw_exception_again;
205       }
206   }
207   
208   // Destruct array.
209   extern "C" void
210   __cxa_vec_dtor(void *array_address,
211                  std::size_t element_count,
212                  std::size_t element_size,
213                  void (*destructor) (void *))
214   {
215     if (destructor)
216       {
217         char *ptr = static_cast<char *>(array_address);
218         std::size_t ix = element_count;
219
220         ptr += element_count * element_size;
221
222         try
223           {
224             while (ix--)
225               {
226                 ptr -= element_size;
227                 destructor(ptr);
228               }
229           }
230         catch (...)
231           {
232             {
233               uncatch_exception ue;
234               __cxa_vec_cleanup(array_address, ix, element_size, destructor);
235             }
236             __throw_exception_again;
237           }
238       }
239   }
240
241   // Destruct array as a result of throwing an exception.
242   // [except.ctor]/3 If a destructor called during stack unwinding
243   // exits with an exception, terminate is called.
244   extern "C" void
245   __cxa_vec_cleanup(void *array_address,
246                     std::size_t element_count,
247                     std::size_t element_size,
248                     void (*destructor) (void *))
249   {
250     if (destructor)
251       {
252         char *ptr = static_cast <char *> (array_address);
253         std::size_t ix = element_count;
254
255         ptr += element_count * element_size;
256
257         try
258           {
259             while (ix--)
260               {
261                 ptr -= element_size;
262                 destructor(ptr);
263               }
264           }
265         catch (...)
266           {
267             std::terminate();
268           }
269       }
270   }
271
272   // Destruct and release array.
273   extern "C" void
274   __cxa_vec_delete(void *array_address,
275                    std::size_t element_size,
276                    std::size_t padding_size,
277                    void (*destructor) (void *))
278   {
279     __cxa_vec_delete2(array_address, element_size, padding_size,
280                        destructor,
281                        &operator delete []);
282   }
283
284   extern "C" void
285   __cxa_vec_delete2(void *array_address,
286                     std::size_t element_size,
287                     std::size_t padding_size,
288                     void (*destructor) (void *),
289                     void (*dealloc) (void *))
290   {
291     if (!array_address)
292       return;
293
294     char* base = static_cast<char *>(array_address);
295   
296     if (padding_size)
297       {
298         std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1];
299         base -= padding_size;
300         try
301           {
302             __cxa_vec_dtor(array_address, element_count, element_size,
303                            destructor);
304           }
305         catch (...)
306           {
307             {
308               uncatch_exception ue;
309               dealloc(base);
310             }
311             __throw_exception_again;
312           }
313       }
314     dealloc(base);
315   }
316
317   extern "C" void
318   __cxa_vec_delete3(void *array_address,
319                     std::size_t element_size,
320                     std::size_t padding_size,
321                      void (*destructor) (void *),
322                     void (*dealloc) (void *, std::size_t))
323   {
324     if (!array_address)
325       return;
326
327     char* base = static_cast <char *> (array_address);
328     std::size_t size = 0;
329
330     if (padding_size)
331       {
332         std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1];
333         base -= padding_size;
334         size = element_count * element_size + padding_size;
335         try
336           {
337             __cxa_vec_dtor(array_address, element_count, element_size,
338                            destructor);
339           }
340         catch (...)
341           {
342             {
343               uncatch_exception ue;
344               dealloc(base, size);
345             }
346             __throw_exception_again;
347           }
348       }
349     dealloc(base, size);
350   }
351 } // namespace __cxxabiv1
352