OSDN Git Service

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