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, <[email protected]> 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 353