197403Sobrien// New abi Support -*- C++ -*- 297403Sobrien 3132720Skan// Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc. 497403Sobrien// 5132720Skan// This file is part of GCC. 697403Sobrien// 7132720Skan// GCC is free software; you can redistribute it and/or modify 897403Sobrien// it under the terms of the GNU General Public License as published by 997403Sobrien// the Free Software Foundation; either version 2, or (at your option) 1097403Sobrien// any later version. 1197403Sobrien 12132720Skan// GCC is distributed in the hope that it will be useful, 1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1597403Sobrien// GNU General Public License for more details. 1697403Sobrien 1797403Sobrien// You should have received a copy of the GNU General Public License 18132720Skan// along with GCC; see the file COPYING. If not, write to 19169691Skan// the Free Software Foundation, 51 Franklin Street, Fifth Floor, 20169691Skan// Boston, MA 02110-1301, USA. 2197403Sobrien 2297403Sobrien// As a special exception, you may use this file as part of a free software 2397403Sobrien// library without restriction. Specifically, if other files instantiate 2497403Sobrien// templates or use macros or inline functions from this file, or you compile 2597403Sobrien// this file and link it with other files to produce an executable, this 2697403Sobrien// file does not by itself cause the resulting executable to be covered by 2797403Sobrien// the GNU General Public License. This exception does not however 2897403Sobrien// invalidate any other reasons why the executable file might be covered by 2997403Sobrien// the GNU General Public License. 3097403Sobrien 3197403Sobrien// Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com> 3297403Sobrien 3397403Sobrien#include <cxxabi.h> 3497403Sobrien#include <new> 3597403Sobrien#include <exception> 3697403Sobrien#include <exception_defines.h> 3797403Sobrien#include "unwind-cxx.h" 3897403Sobrien 3997403Sobriennamespace __cxxabiv1 4097403Sobrien{ 4197403Sobrien namespace 4297403Sobrien { 4397403Sobrien struct uncatch_exception 4497403Sobrien { 45132720Skan uncatch_exception(); 4697403Sobrien ~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); } 4797403Sobrien 48132720Skan __cxa_exception* p; 49132720Skan 50132720Skan private: 51132720Skan uncatch_exception& 52132720Skan operator=(const uncatch_exception&); 53132720Skan 54132720Skan uncatch_exception(const uncatch_exception&); 5597403Sobrien }; 5697403Sobrien 57132720Skan uncatch_exception::uncatch_exception() : p(0) 5897403Sobrien { 5997403Sobrien __cxa_eh_globals *globals = __cxa_get_globals_fast (); 6097403Sobrien 6197403Sobrien p = globals->caughtExceptions; 6297403Sobrien p->handlerCount -= 1; 6397403Sobrien globals->caughtExceptions = p->nextException; 6497403Sobrien globals->uncaughtExceptions += 1; 6597403Sobrien } 6697403Sobrien } 6797403Sobrien 6897403Sobrien // Allocate and construct array. 6997403Sobrien extern "C" void * 7097403Sobrien __cxa_vec_new(std::size_t element_count, 7197403Sobrien std::size_t element_size, 7297403Sobrien std::size_t padding_size, 73169691Skan __cxa_cdtor_type constructor, 74169691Skan __cxa_cdtor_type destructor) 7597403Sobrien { 7697403Sobrien return __cxa_vec_new2(element_count, element_size, padding_size, 7797403Sobrien constructor, destructor, 7897403Sobrien &operator new[], &operator delete []); 7997403Sobrien } 8097403Sobrien 8197403Sobrien extern "C" void * 8297403Sobrien __cxa_vec_new2(std::size_t element_count, 8397403Sobrien std::size_t element_size, 8497403Sobrien std::size_t padding_size, 85169691Skan __cxa_cdtor_type constructor, 86169691Skan __cxa_cdtor_type destructor, 8797403Sobrien void *(*alloc) (std::size_t), 8897403Sobrien void (*dealloc) (void *)) 8997403Sobrien { 9097403Sobrien std::size_t size = element_count * element_size + padding_size; 9197403Sobrien char *base = static_cast <char *> (alloc (size)); 92132720Skan if (!base) 93132720Skan return base; 94132720Skan 9597403Sobrien if (padding_size) 9697403Sobrien { 9797403Sobrien base += padding_size; 9897403Sobrien reinterpret_cast <std::size_t *> (base)[-1] = element_count; 99169691Skan#ifdef _GLIBCXX_ELTSIZE_IN_COOKIE 100169691Skan reinterpret_cast <std::size_t *> (base)[-2] = element_size; 101169691Skan#endif 10297403Sobrien } 10397403Sobrien try 10497403Sobrien { 10597403Sobrien __cxa_vec_ctor(base, element_count, element_size, 10697403Sobrien constructor, destructor); 10797403Sobrien } 10897403Sobrien catch (...) 10997403Sobrien { 11097403Sobrien { 11197403Sobrien uncatch_exception ue; 11297403Sobrien dealloc(base - padding_size); 11397403Sobrien } 11497403Sobrien __throw_exception_again; 11597403Sobrien } 11697403Sobrien return base; 11797403Sobrien } 11897403Sobrien 11997403Sobrien extern "C" void * 12097403Sobrien __cxa_vec_new3(std::size_t element_count, 12197403Sobrien std::size_t element_size, 12297403Sobrien std::size_t padding_size, 123169691Skan __cxa_cdtor_type constructor, 124169691Skan __cxa_cdtor_type destructor, 12597403Sobrien void *(*alloc) (std::size_t), 12697403Sobrien void (*dealloc) (void *, std::size_t)) 12797403Sobrien { 12897403Sobrien std::size_t size = element_count * element_size + padding_size; 12997403Sobrien char *base = static_cast<char *>(alloc (size)); 130132720Skan if (!base) 131132720Skan return base; 13297403Sobrien 13397403Sobrien if (padding_size) 13497403Sobrien { 13597403Sobrien base += padding_size; 13697403Sobrien reinterpret_cast<std::size_t *>(base)[-1] = element_count; 137169691Skan#ifdef _GLIBCXX_ELTSIZE_IN_COOKIE 138169691Skan reinterpret_cast <std::size_t *> (base)[-2] = element_size; 139169691Skan#endif 14097403Sobrien } 14197403Sobrien try 14297403Sobrien { 14397403Sobrien __cxa_vec_ctor(base, element_count, element_size, 14497403Sobrien constructor, destructor); 14597403Sobrien } 14697403Sobrien catch (...) 14797403Sobrien { 14897403Sobrien { 14997403Sobrien uncatch_exception ue; 15097403Sobrien dealloc(base - padding_size, size); 15197403Sobrien } 15297403Sobrien __throw_exception_again; 15397403Sobrien } 15497403Sobrien return base; 15597403Sobrien } 15697403Sobrien 15797403Sobrien // Construct array. 158169691Skan extern "C" __cxa_vec_ctor_return_type 15997403Sobrien __cxa_vec_ctor(void *array_address, 16097403Sobrien std::size_t element_count, 16197403Sobrien std::size_t element_size, 162169691Skan __cxa_cdtor_type constructor, 163169691Skan __cxa_cdtor_type destructor) 16497403Sobrien { 16597403Sobrien std::size_t ix = 0; 16697403Sobrien char *ptr = static_cast<char *>(array_address); 16797403Sobrien 16897403Sobrien try 16997403Sobrien { 17097403Sobrien if (constructor) 17197403Sobrien for (; ix != element_count; ix++, ptr += element_size) 17297403Sobrien constructor(ptr); 17397403Sobrien } 17497403Sobrien catch (...) 17597403Sobrien { 17697403Sobrien { 17797403Sobrien uncatch_exception ue; 17897403Sobrien __cxa_vec_cleanup(array_address, ix, element_size, destructor); 17997403Sobrien } 18097403Sobrien __throw_exception_again; 18197403Sobrien } 182169691Skan _GLIBCXX_CXA_VEC_CTOR_RETURN (array_address); 18397403Sobrien } 18497403Sobrien 18597403Sobrien // Construct an array by copying. 186169691Skan extern "C" __cxa_vec_ctor_return_type 18797403Sobrien __cxa_vec_cctor(void *dest_array, 18897403Sobrien void *src_array, 18997403Sobrien std::size_t element_count, 19097403Sobrien std::size_t element_size, 191169691Skan __cxa_cdtor_return_type (*constructor) (void *, void *), 192169691Skan __cxa_cdtor_type destructor) 19397403Sobrien { 19497403Sobrien std::size_t ix = 0; 19597403Sobrien char *dest_ptr = static_cast<char *>(dest_array); 19697403Sobrien char *src_ptr = static_cast<char *>(src_array); 19797403Sobrien 19897403Sobrien try 19997403Sobrien { 20097403Sobrien if (constructor) 20197403Sobrien for (; ix != element_count; 20297403Sobrien ix++, src_ptr += element_size, dest_ptr += element_size) 20397403Sobrien constructor(dest_ptr, src_ptr); 20497403Sobrien } 20597403Sobrien catch (...) 20697403Sobrien { 20797403Sobrien { 20897403Sobrien uncatch_exception ue; 20997403Sobrien __cxa_vec_cleanup(dest_array, ix, element_size, destructor); 21097403Sobrien } 21197403Sobrien __throw_exception_again; 21297403Sobrien } 213169691Skan _GLIBCXX_CXA_VEC_CTOR_RETURN (dest_array); 21497403Sobrien } 21597403Sobrien 21697403Sobrien // Destruct array. 21797403Sobrien extern "C" void 21897403Sobrien __cxa_vec_dtor(void *array_address, 21997403Sobrien std::size_t element_count, 22097403Sobrien std::size_t element_size, 221169691Skan __cxa_cdtor_type destructor) 22297403Sobrien { 22397403Sobrien if (destructor) 22497403Sobrien { 22597403Sobrien char *ptr = static_cast<char *>(array_address); 22697403Sobrien std::size_t ix = element_count; 22797403Sobrien 22897403Sobrien ptr += element_count * element_size; 22997403Sobrien 23097403Sobrien try 23197403Sobrien { 23297403Sobrien while (ix--) 23397403Sobrien { 23497403Sobrien ptr -= element_size; 23597403Sobrien destructor(ptr); 23697403Sobrien } 23797403Sobrien } 23897403Sobrien catch (...) 23997403Sobrien { 24097403Sobrien { 24197403Sobrien uncatch_exception ue; 24297403Sobrien __cxa_vec_cleanup(array_address, ix, element_size, destructor); 24397403Sobrien } 24497403Sobrien __throw_exception_again; 24597403Sobrien } 24697403Sobrien } 24797403Sobrien } 24897403Sobrien 24997403Sobrien // Destruct array as a result of throwing an exception. 25097403Sobrien // [except.ctor]/3 If a destructor called during stack unwinding 25197403Sobrien // exits with an exception, terminate is called. 25297403Sobrien extern "C" void 25397403Sobrien __cxa_vec_cleanup(void *array_address, 25497403Sobrien std::size_t element_count, 25597403Sobrien std::size_t element_size, 256169691Skan __cxa_cdtor_type destructor) 25797403Sobrien { 25897403Sobrien if (destructor) 25997403Sobrien { 26097403Sobrien char *ptr = static_cast <char *> (array_address); 26197403Sobrien std::size_t ix = element_count; 26297403Sobrien 26397403Sobrien ptr += element_count * element_size; 26497403Sobrien 26597403Sobrien try 26697403Sobrien { 26797403Sobrien while (ix--) 26897403Sobrien { 26997403Sobrien ptr -= element_size; 27097403Sobrien destructor(ptr); 27197403Sobrien } 27297403Sobrien } 27397403Sobrien catch (...) 27497403Sobrien { 27597403Sobrien std::terminate(); 27697403Sobrien } 27797403Sobrien } 27897403Sobrien } 27997403Sobrien 28097403Sobrien // Destruct and release array. 28197403Sobrien extern "C" void 28297403Sobrien __cxa_vec_delete(void *array_address, 28397403Sobrien std::size_t element_size, 28497403Sobrien std::size_t padding_size, 285169691Skan __cxa_cdtor_type destructor) 28697403Sobrien { 28797403Sobrien __cxa_vec_delete2(array_address, element_size, padding_size, 28897403Sobrien destructor, 28997403Sobrien &operator delete []); 29097403Sobrien } 29197403Sobrien 29297403Sobrien extern "C" void 29397403Sobrien __cxa_vec_delete2(void *array_address, 29497403Sobrien std::size_t element_size, 29597403Sobrien std::size_t padding_size, 296169691Skan __cxa_cdtor_type destructor, 29797403Sobrien void (*dealloc) (void *)) 29897403Sobrien { 299132720Skan if (!array_address) 300132720Skan return; 301132720Skan 302132720Skan char* base = static_cast<char *>(array_address); 30397403Sobrien 30497403Sobrien if (padding_size) 30597403Sobrien { 30697403Sobrien std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1]; 30797403Sobrien base -= padding_size; 30897403Sobrien try 30997403Sobrien { 31097403Sobrien __cxa_vec_dtor(array_address, element_count, element_size, 31197403Sobrien destructor); 31297403Sobrien } 31397403Sobrien catch (...) 31497403Sobrien { 31597403Sobrien { 31697403Sobrien uncatch_exception ue; 31797403Sobrien dealloc(base); 31897403Sobrien } 31997403Sobrien __throw_exception_again; 32097403Sobrien } 32197403Sobrien } 32297403Sobrien dealloc(base); 32397403Sobrien } 32497403Sobrien 32597403Sobrien extern "C" void 32697403Sobrien __cxa_vec_delete3(void *array_address, 32797403Sobrien std::size_t element_size, 32897403Sobrien std::size_t padding_size, 329169691Skan __cxa_cdtor_type destructor, 33097403Sobrien void (*dealloc) (void *, std::size_t)) 33197403Sobrien { 332132720Skan if (!array_address) 333132720Skan return; 334132720Skan 335132720Skan char* base = static_cast <char *> (array_address); 33697403Sobrien std::size_t size = 0; 337132720Skan 33897403Sobrien if (padding_size) 33997403Sobrien { 34097403Sobrien std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1]; 34197403Sobrien base -= padding_size; 34297403Sobrien size = element_count * element_size + padding_size; 34397403Sobrien try 34497403Sobrien { 34597403Sobrien __cxa_vec_dtor(array_address, element_count, element_size, 34697403Sobrien destructor); 34797403Sobrien } 34897403Sobrien catch (...) 34997403Sobrien { 35097403Sobrien { 35197403Sobrien uncatch_exception ue; 35297403Sobrien dealloc(base, size); 35397403Sobrien } 35497403Sobrien __throw_exception_again; 35597403Sobrien } 35697403Sobrien } 35797403Sobrien dealloc(base, size); 35897403Sobrien } 35997403Sobrien} // namespace __cxxabiv1 36097403Sobrien 361169691Skan#if defined(__arm__) && defined(__ARM_EABI__) 362169691Skan 363169691Skan// The ARM C++ ABI requires that the library provide these additional 364169691Skan// helper functions. There are placed in this file, despite being 365169691Skan// architecture-specifier, so that the compiler can inline the __cxa 366169691Skan// functions into these functions as appropriate. 367169691Skan 368169691Skannamespace __aeabiv1 369169691Skan{ 370169691Skan extern "C" void * 371169691Skan __aeabi_vec_ctor_nocookie_nodtor (void *array_address, 372169691Skan abi::__cxa_cdtor_type constructor, 373169691Skan std::size_t element_size, 374169691Skan std::size_t element_count) 375169691Skan { 376169691Skan return abi::__cxa_vec_ctor (array_address, element_count, element_size, 377169691Skan constructor, /*destructor=*/NULL); 378169691Skan } 379169691Skan 380169691Skan extern "C" void * 381169691Skan __aeabi_vec_ctor_cookie_nodtor (void *array_address, 382169691Skan abi::__cxa_cdtor_type constructor, 383169691Skan std::size_t element_size, 384169691Skan std::size_t element_count) 385169691Skan { 386169691Skan if (array_address == NULL) 387169691Skan return NULL; 388169691Skan 389169691Skan array_address = reinterpret_cast<std::size_t *>(array_address) + 2; 390169691Skan reinterpret_cast<std::size_t *>(array_address)[-2] = element_size; 391169691Skan reinterpret_cast<std::size_t *>(array_address)[-1] = element_count; 392169691Skan return abi::__cxa_vec_ctor (array_address, 393169691Skan element_count, element_size, 394169691Skan constructor, /*destructor=*/NULL); 395169691Skan } 396169691Skan 397169691Skan extern "C" void * 398169691Skan __aeabi_vec_cctor_nocookie_nodtor (void *dest_array, 399169691Skan void *src_array, 400169691Skan std::size_t element_size, 401169691Skan std::size_t element_count, 402169691Skan void *(*constructor) (void *, void *)) 403169691Skan { 404169691Skan return abi::__cxa_vec_cctor (dest_array, src_array, 405169691Skan element_count, element_size, 406169691Skan constructor, NULL); 407169691Skan } 408169691Skan 409169691Skan extern "C" void * 410169691Skan __aeabi_vec_new_cookie_noctor (std::size_t element_size, 411169691Skan std::size_t element_count) 412169691Skan { 413169691Skan return abi::__cxa_vec_new(element_count, element_size, 414169691Skan 2 * sizeof (std::size_t), 415169691Skan /*constructor=*/NULL, /*destructor=*/NULL); 416169691Skan } 417169691Skan 418169691Skan extern "C" void * 419169691Skan __aeabi_vec_new_nocookie (std::size_t element_size, 420169691Skan std::size_t element_count, 421169691Skan abi::__cxa_cdtor_type constructor) 422169691Skan { 423169691Skan return abi::__cxa_vec_new (element_count, element_size, 0, constructor, 424169691Skan NULL); 425169691Skan } 426169691Skan 427169691Skan extern "C" void * 428169691Skan __aeabi_vec_new_cookie_nodtor (std::size_t element_size, 429169691Skan std::size_t element_count, 430169691Skan abi::__cxa_cdtor_type constructor) 431169691Skan { 432169691Skan return abi::__cxa_vec_new(element_count, element_size, 433169691Skan 2 * sizeof (std::size_t), 434169691Skan constructor, NULL); 435169691Skan } 436169691Skan 437169691Skan extern "C" void * 438169691Skan __aeabi_vec_new_cookie(std::size_t element_size, 439169691Skan std::size_t element_count, 440169691Skan abi::__cxa_cdtor_type constructor, 441169691Skan abi::__cxa_cdtor_type destructor) 442169691Skan { 443169691Skan return abi::__cxa_vec_new (element_count, element_size, 444169691Skan 2 * sizeof (std::size_t), 445169691Skan constructor, destructor); 446169691Skan } 447169691Skan 448169691Skan 449169691Skan extern "C" void * 450169691Skan __aeabi_vec_dtor (void *array_address, 451169691Skan abi::__cxa_cdtor_type destructor, 452169691Skan std::size_t element_size, 453169691Skan std::size_t element_count) 454169691Skan { 455169691Skan abi::__cxa_vec_dtor (array_address, element_count, element_size, 456169691Skan destructor); 457169691Skan return reinterpret_cast<std::size_t*> (array_address) - 2; 458169691Skan } 459169691Skan 460169691Skan extern "C" void * 461169691Skan __aeabi_vec_dtor_cookie (void *array_address, 462169691Skan abi::__cxa_cdtor_type destructor) 463169691Skan { 464169691Skan abi::__cxa_vec_dtor (array_address, 465169691Skan reinterpret_cast<std::size_t *>(array_address)[-1], 466169691Skan reinterpret_cast<std::size_t *>(array_address)[-2], 467169691Skan destructor); 468169691Skan return reinterpret_cast<std::size_t*> (array_address) - 2; 469169691Skan } 470169691Skan 471169691Skan 472169691Skan extern "C" void 473169691Skan __aeabi_vec_delete (void *array_address, 474169691Skan abi::__cxa_cdtor_type destructor) 475169691Skan { 476169691Skan abi::__cxa_vec_delete (array_address, 477169691Skan reinterpret_cast<std::size_t *>(array_address)[-2], 478169691Skan 2 * sizeof (std::size_t), 479169691Skan destructor); 480169691Skan } 481169691Skan 482169691Skan extern "C" void 483169691Skan __aeabi_vec_delete3 (void *array_address, 484169691Skan abi::__cxa_cdtor_type destructor, 485169691Skan void (*dealloc) (void *, std::size_t)) 486169691Skan { 487169691Skan abi::__cxa_vec_delete3 (array_address, 488169691Skan reinterpret_cast<std::size_t *>(array_address)[-2], 489169691Skan 2 * sizeof (std::size_t), 490169691Skan destructor, dealloc); 491169691Skan } 492169691Skan 493169691Skan extern "C" void 494169691Skan __aeabi_vec_delete3_nodtor (void *array_address, 495169691Skan void (*dealloc) (void *, std::size_t)) 496169691Skan { 497169691Skan abi::__cxa_vec_delete3 (array_address, 498169691Skan reinterpret_cast<std::size_t *>(array_address)[-2], 499169691Skan 2 * sizeof (std::size_t), 500169691Skan /*destructor=*/NULL, dealloc); 501169691Skan } 502169691Skan 503169691Skan extern "C" int 504169691Skan __aeabi_atexit (void *object, 505169691Skan void (*destructor) (void *), 506169691Skan void *dso_handle) 507169691Skan { 508169691Skan return abi::__cxa_atexit(destructor, object, dso_handle); 509169691Skan } 510169691Skan} // namespace __aeabiv1 511169691Skan 512169691Skan#endif // defined(__arm__) && defined(__ARM_EABI__) 513