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, 51 Franklin Street, Fifth Floor, 20// Boston, MA 02110-1301, 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 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 __cxa_cdtor_type constructor, 74 __cxa_cdtor_type destructor) 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 __cxa_cdtor_type constructor, 86 __cxa_cdtor_type destructor, 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 __cxa_cdtor_type constructor, 124 __cxa_cdtor_type destructor, 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" __cxa_vec_ctor_return_type 159 __cxa_vec_ctor(void *array_address, 160 std::size_t element_count, 161 std::size_t element_size, 162 __cxa_cdtor_type constructor, 163 __cxa_cdtor_type destructor) 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 _GLIBCXX_CXA_VEC_CTOR_RETURN (array_address); 183 } 184 185 // Construct an array by copying. 186 extern "C" __cxa_vec_ctor_return_type 187 __cxa_vec_cctor(void *dest_array, 188 void *src_array, 189 std::size_t element_count, 190 std::size_t element_size, 191 __cxa_cdtor_return_type (*constructor) (void *, void *), 192 __cxa_cdtor_type destructor) 193 { 194 std::size_t ix = 0; 195 char *dest_ptr = static_cast<char *>(dest_array); 196 char *src_ptr = static_cast<char *>(src_array); 197 198 try 199 { 200 if (constructor) 201 for (; ix != element_count; 202 ix++, src_ptr += element_size, dest_ptr += element_size) 203 constructor(dest_ptr, src_ptr); 204 } 205 catch (...) 206 { 207 { 208 uncatch_exception ue; 209 __cxa_vec_cleanup(dest_array, ix, element_size, destructor); 210 } 211 __throw_exception_again; 212 } 213 _GLIBCXX_CXA_VEC_CTOR_RETURN (dest_array); 214 } 215 216 // Destruct array. 217 extern "C" void 218 __cxa_vec_dtor(void *array_address, 219 std::size_t element_count, 220 std::size_t element_size, 221 __cxa_cdtor_type destructor) 222 { 223 if (destructor) 224 { 225 char *ptr = static_cast<char *>(array_address); 226 std::size_t ix = element_count; 227 228 ptr += element_count * element_size; 229 230 try 231 { 232 while (ix--) 233 { 234 ptr -= element_size; 235 destructor(ptr); 236 } 237 } 238 catch (...) 239 { 240 { 241 uncatch_exception ue; 242 __cxa_vec_cleanup(array_address, ix, element_size, destructor); 243 } 244 __throw_exception_again; 245 } 246 } 247 } 248 249 // Destruct array as a result of throwing an exception. 250 // [except.ctor]/3 If a destructor called during stack unwinding 251 // exits with an exception, terminate is called. 252 extern "C" void 253 __cxa_vec_cleanup(void *array_address, 254 std::size_t element_count, 255 std::size_t element_size, 256 __cxa_cdtor_type destructor) 257 { 258 if (destructor) 259 { 260 char *ptr = static_cast <char *> (array_address); 261 std::size_t ix = element_count; 262 263 ptr += element_count * element_size; 264 265 try 266 { 267 while (ix--) 268 { 269 ptr -= element_size; 270 destructor(ptr); 271 } 272 } 273 catch (...) 274 { 275 std::terminate(); 276 } 277 } 278 } 279 280 // Destruct and release array. 281 extern "C" void 282 __cxa_vec_delete(void *array_address, 283 std::size_t element_size, 284 std::size_t padding_size, 285 __cxa_cdtor_type destructor) 286 { 287 __cxa_vec_delete2(array_address, element_size, padding_size, 288 destructor, 289 &operator delete []); 290 } 291 292 extern "C" void 293 __cxa_vec_delete2(void *array_address, 294 std::size_t element_size, 295 std::size_t padding_size, 296 __cxa_cdtor_type destructor, 297 void (*dealloc) (void *)) 298 { 299 if (!array_address) 300 return; 301 302 char* base = static_cast<char *>(array_address); 303 304 if (padding_size) 305 { 306 std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1]; 307 base -= padding_size; 308 try 309 { 310 __cxa_vec_dtor(array_address, element_count, element_size, 311 destructor); 312 } 313 catch (...) 314 { 315 { 316 uncatch_exception ue; 317 dealloc(base); 318 } 319 __throw_exception_again; 320 } 321 } 322 dealloc(base); 323 } 324 325 extern "C" void 326 __cxa_vec_delete3(void *array_address, 327 std::size_t element_size, 328 std::size_t padding_size, 329 __cxa_cdtor_type destructor, 330 void (*dealloc) (void *, std::size_t)) 331 { 332 if (!array_address) 333 return; 334 335 char* base = static_cast <char *> (array_address); 336 std::size_t size = 0; 337 338 if (padding_size) 339 { 340 std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1]; 341 base -= padding_size; 342 size = element_count * element_size + padding_size; 343 try 344 { 345 __cxa_vec_dtor(array_address, element_count, element_size, 346 destructor); 347 } 348 catch (...) 349 { 350 { 351 uncatch_exception ue; 352 dealloc(base, size); 353 } 354 __throw_exception_again; 355 } 356 } 357 dealloc(base, size); 358 } 359} // namespace __cxxabiv1 360 361#if defined(__arm__) && defined(__ARM_EABI__) 362 363// The ARM C++ ABI requires that the library provide these additional 364// helper functions. There are placed in this file, despite being 365// architecture-specifier, so that the compiler can inline the __cxa 366// functions into these functions as appropriate. 367 368namespace __aeabiv1 369{ 370 extern "C" void * 371 __aeabi_vec_ctor_nocookie_nodtor (void *array_address, 372 abi::__cxa_cdtor_type constructor, 373 std::size_t element_size, 374 std::size_t element_count) 375 { 376 return abi::__cxa_vec_ctor (array_address, element_count, element_size, 377 constructor, /*destructor=*/NULL); 378 } 379 380 extern "C" void * 381 __aeabi_vec_ctor_cookie_nodtor (void *array_address, 382 abi::__cxa_cdtor_type constructor, 383 std::size_t element_size, 384 std::size_t element_count) 385 { 386 if (array_address == NULL) 387 return NULL; 388 389 array_address = reinterpret_cast<std::size_t *>(array_address) + 2; 390 reinterpret_cast<std::size_t *>(array_address)[-2] = element_size; 391 reinterpret_cast<std::size_t *>(array_address)[-1] = element_count; 392 return abi::__cxa_vec_ctor (array_address, 393 element_count, element_size, 394 constructor, /*destructor=*/NULL); 395 } 396 397 extern "C" void * 398 __aeabi_vec_cctor_nocookie_nodtor (void *dest_array, 399 void *src_array, 400 std::size_t element_size, 401 std::size_t element_count, 402 void *(*constructor) (void *, void *)) 403 { 404 return abi::__cxa_vec_cctor (dest_array, src_array, 405 element_count, element_size, 406 constructor, NULL); 407 } 408 409 extern "C" void * 410 __aeabi_vec_new_cookie_noctor (std::size_t element_size, 411 std::size_t element_count) 412 { 413 return abi::__cxa_vec_new(element_count, element_size, 414 2 * sizeof (std::size_t), 415 /*constructor=*/NULL, /*destructor=*/NULL); 416 } 417 418 extern "C" void * 419 __aeabi_vec_new_nocookie (std::size_t element_size, 420 std::size_t element_count, 421 abi::__cxa_cdtor_type constructor) 422 { 423 return abi::__cxa_vec_new (element_count, element_size, 0, constructor, 424 NULL); 425 } 426 427 extern "C" void * 428 __aeabi_vec_new_cookie_nodtor (std::size_t element_size, 429 std::size_t element_count, 430 abi::__cxa_cdtor_type constructor) 431 { 432 return abi::__cxa_vec_new(element_count, element_size, 433 2 * sizeof (std::size_t), 434 constructor, NULL); 435 } 436 437 extern "C" void * 438 __aeabi_vec_new_cookie(std::size_t element_size, 439 std::size_t element_count, 440 abi::__cxa_cdtor_type constructor, 441 abi::__cxa_cdtor_type destructor) 442 { 443 return abi::__cxa_vec_new (element_count, element_size, 444 2 * sizeof (std::size_t), 445 constructor, destructor); 446 } 447 448 449 extern "C" void * 450 __aeabi_vec_dtor (void *array_address, 451 abi::__cxa_cdtor_type destructor, 452 std::size_t element_size, 453 std::size_t element_count) 454 { 455 abi::__cxa_vec_dtor (array_address, element_count, element_size, 456 destructor); 457 return reinterpret_cast<std::size_t*> (array_address) - 2; 458 } 459 460 extern "C" void * 461 __aeabi_vec_dtor_cookie (void *array_address, 462 abi::__cxa_cdtor_type destructor) 463 { 464 abi::__cxa_vec_dtor (array_address, 465 reinterpret_cast<std::size_t *>(array_address)[-1], 466 reinterpret_cast<std::size_t *>(array_address)[-2], 467 destructor); 468 return reinterpret_cast<std::size_t*> (array_address) - 2; 469 } 470 471 472 extern "C" void 473 __aeabi_vec_delete (void *array_address, 474 abi::__cxa_cdtor_type destructor) 475 { 476 abi::__cxa_vec_delete (array_address, 477 reinterpret_cast<std::size_t *>(array_address)[-2], 478 2 * sizeof (std::size_t), 479 destructor); 480 } 481 482 extern "C" void 483 __aeabi_vec_delete3 (void *array_address, 484 abi::__cxa_cdtor_type destructor, 485 void (*dealloc) (void *, std::size_t)) 486 { 487 abi::__cxa_vec_delete3 (array_address, 488 reinterpret_cast<std::size_t *>(array_address)[-2], 489 2 * sizeof (std::size_t), 490 destructor, dealloc); 491 } 492 493 extern "C" void 494 __aeabi_vec_delete3_nodtor (void *array_address, 495 void (*dealloc) (void *, std::size_t)) 496 { 497 abi::__cxa_vec_delete3 (array_address, 498 reinterpret_cast<std::size_t *>(array_address)[-2], 499 2 * sizeof (std::size_t), 500 /*destructor=*/NULL, dealloc); 501 } 502 503 extern "C" int 504 __aeabi_atexit (void *object, 505 void (*destructor) (void *), 506 void *dso_handle) 507 { 508 return abi::__cxa_atexit(destructor, object, dso_handle); 509 } 510} // namespace __aeabiv1 511 512#endif // defined(__arm__) && defined(__ARM_EABI__) 513