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