Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // New abi Support -*- C++ -*-
  2.  
  3. // Copyright (C) 2000-2015 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 3, 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. // Under Section 7 of GPL version 3, you are granted additional
  18. // permissions described in the GCC Runtime Library Exception, version
  19. // 3.1, as published by the Free Software Foundation.
  20.  
  21. // You should have received a copy of the GNU General Public License and
  22. // a copy of the GCC Runtime Library Exception along with this program;
  23. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  24. // <http://www.gnu.org/licenses/>.
  25.  
  26. // Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>
  27.  
  28. #include <cxxabi.h>
  29. #include <new>
  30. #include <exception>
  31. #include <bits/exception_defines.h>
  32. #include "unwind-cxx.h"
  33.  
  34. namespace __cxxabiv1
  35. {
  36.   namespace
  37.   {
  38.     struct uncatch_exception
  39.     {
  40.       uncatch_exception();
  41.       ~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); }
  42.      
  43.       __cxa_exception* p;
  44.  
  45.     private:
  46.       uncatch_exception&
  47.       operator=(const uncatch_exception&);
  48.  
  49.       uncatch_exception(const uncatch_exception&);
  50.     };
  51.  
  52.     uncatch_exception::uncatch_exception() : p(0)
  53.     {
  54.       __cxa_eh_globals *globals = __cxa_get_globals_fast ();
  55.  
  56.       p = globals->caughtExceptions;
  57.       p->handlerCount -= 1;
  58.       globals->caughtExceptions = p->nextException;
  59.       globals->uncaughtExceptions += 1;
  60.     }
  61.  
  62.     // Compute the total size with overflow checking.
  63.     std::size_t compute_size(std::size_t element_count,
  64.                              std::size_t element_size,
  65.                              std::size_t padding_size)
  66.     {
  67.       if (element_size && element_count > std::size_t(-1) / element_size)
  68.         _GLIBCXX_THROW_OR_ABORT(std::bad_alloc());
  69.       std::size_t size = element_count * element_size;
  70.       if (size + padding_size < size)
  71.         _GLIBCXX_THROW_OR_ABORT(std::bad_alloc());
  72.       return size + padding_size;
  73.     }
  74.   }
  75.  
  76.   // Allocate and construct array.
  77.   extern "C" void *
  78.   __cxa_vec_new(std::size_t element_count,
  79.                 std::size_t element_size,
  80.                 std::size_t padding_size,
  81.                 __cxa_cdtor_type constructor,
  82.                 __cxa_cdtor_type destructor)
  83.   {
  84.     return __cxa_vec_new2(element_count, element_size, padding_size,
  85.                            constructor, destructor,
  86.                            &operator new[], &operator delete []);
  87.   }
  88.  
  89.   extern "C" void *
  90.   __cxa_vec_new2(std::size_t element_count,
  91.                  std::size_t element_size,
  92.                  std::size_t padding_size,
  93.                  __cxa_cdtor_type constructor,
  94.                  __cxa_cdtor_type destructor,
  95.                  void *(*alloc) (std::size_t),
  96.                  void (*dealloc) (void *))
  97.   {
  98.     std::size_t size
  99.       = compute_size(element_count, element_size, padding_size);
  100.     char *base = static_cast <char *> (alloc (size));
  101.     if (!base)
  102.       return base;
  103.  
  104.     if (padding_size)
  105.       {
  106.         base += padding_size;
  107.         reinterpret_cast <std::size_t *> (base)[-1] = element_count;
  108. #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
  109.         reinterpret_cast <std::size_t *> (base)[-2] = element_size;
  110. #endif
  111.       }
  112.     __try
  113.       {
  114.         __cxa_vec_ctor(base, element_count, element_size,
  115.                        constructor, destructor);
  116.       }
  117.     __catch(...)
  118.       {
  119.         {
  120.           uncatch_exception ue;
  121.           // Core issue 901 will probably be resolved such that a
  122.           // deleted operator delete means not freeing memory here.
  123.           if (dealloc)
  124.             dealloc(base - padding_size);
  125.         }
  126.         __throw_exception_again;
  127.       }
  128.     return base;
  129.   }
  130.  
  131.   extern "C" void *
  132.   __cxa_vec_new3(std::size_t element_count,
  133.                  std::size_t element_size,
  134.                  std::size_t padding_size,
  135.                  __cxa_cdtor_type constructor,
  136.                  __cxa_cdtor_type destructor,
  137.                  void *(*alloc) (std::size_t),
  138.                  void (*dealloc) (void *, std::size_t))
  139.   {
  140.     std::size_t size
  141.       = compute_size(element_count, element_size, padding_size);
  142.     char *base = static_cast<char *>(alloc (size));
  143.     if (!base)
  144.       return base;
  145.    
  146.     if (padding_size)
  147.       {
  148.         base += padding_size;
  149.         reinterpret_cast<std::size_t *>(base)[-1] = element_count;
  150. #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
  151.         reinterpret_cast <std::size_t *> (base)[-2] = element_size;
  152. #endif
  153.       }
  154.     __try
  155.       {
  156.         __cxa_vec_ctor(base, element_count, element_size,
  157.                        constructor, destructor);
  158.       }
  159.     __catch(...)
  160.       {
  161.         {
  162.           uncatch_exception ue;
  163.           if (dealloc)
  164.             dealloc(base - padding_size, size);
  165.         }
  166.         __throw_exception_again;
  167.       }
  168.     return base;
  169.   }
  170.  
  171.   // Construct array.
  172.   extern "C" __cxa_vec_ctor_return_type
  173.   __cxa_vec_ctor(void *array_address,
  174.                  std::size_t element_count,
  175.                  std::size_t element_size,
  176.                  __cxa_cdtor_type constructor,
  177.                  __cxa_cdtor_type destructor)
  178.   {
  179.     std::size_t ix = 0;
  180.     char *ptr = static_cast<char *>(array_address);
  181.    
  182.     __try
  183.       {
  184.         if (constructor)
  185.           for (; ix != element_count; ix++, ptr += element_size)
  186.             constructor(ptr);
  187.       }
  188.     __catch(...)
  189.       {
  190.         {
  191.           uncatch_exception ue;
  192.           __cxa_vec_cleanup(array_address, ix, element_size, destructor);
  193.         }
  194.         __throw_exception_again;
  195.       }
  196.     _GLIBCXX_CXA_VEC_CTOR_RETURN (array_address);
  197.   }
  198.  
  199.   // Construct an array by copying.
  200.   extern "C" __cxa_vec_ctor_return_type
  201.   __cxa_vec_cctor(void *dest_array,
  202.                   void *src_array,
  203.                   std::size_t element_count,
  204.                   std::size_t element_size,
  205.                   __cxa_cdtor_return_type (*constructor) (void *, void *),
  206.                   __cxa_cdtor_type destructor)
  207.   {
  208.     std::size_t ix = 0;
  209.     char *dest_ptr = static_cast<char *>(dest_array);
  210.     char *src_ptr = static_cast<char *>(src_array);
  211.    
  212.     __try
  213.       {
  214.         if (constructor)
  215.           for (; ix != element_count;
  216.                ix++, src_ptr += element_size, dest_ptr += element_size)
  217.             constructor(dest_ptr, src_ptr);
  218.       }
  219.     __catch(...)
  220.       {
  221.         {
  222.           uncatch_exception ue;
  223.           __cxa_vec_cleanup(dest_array, ix, element_size, destructor);
  224.         }
  225.         __throw_exception_again;
  226.       }
  227.     _GLIBCXX_CXA_VEC_CTOR_RETURN (dest_array);
  228.   }
  229.  
  230.   // Destruct array.
  231.   extern "C" void
  232.   __cxa_vec_dtor(void *array_address,
  233.                  std::size_t element_count,
  234.                  std::size_t element_size,
  235.                  __cxa_cdtor_type destructor)
  236.   {
  237.     if (destructor)
  238.       {
  239.         char *ptr = static_cast<char *>(array_address);
  240.         std::size_t ix = element_count;
  241.  
  242.         ptr += element_count * element_size;
  243.  
  244.         __try
  245.           {
  246.             while (ix--)
  247.               {
  248.                 ptr -= element_size;
  249.                 destructor(ptr);
  250.               }
  251.           }
  252.         __catch(...)
  253.           {
  254.             {
  255.               uncatch_exception ue;
  256.               __cxa_vec_cleanup(array_address, ix, element_size, destructor);
  257.             }
  258.             __throw_exception_again;
  259.           }
  260.       }
  261.   }
  262.  
  263.   // Destruct array as a result of throwing an exception.
  264.   // [except.ctor]/3 If a destructor called during stack unwinding
  265.   // exits with an exception, terminate is called.
  266.   extern "C" void
  267.   __cxa_vec_cleanup(void *array_address,
  268.                     std::size_t element_count,
  269.                     std::size_t element_size,
  270.                     __cxa_cdtor_type destructor) throw()
  271.   {
  272.     if (destructor)
  273.       {
  274.         char *ptr = static_cast <char *> (array_address);
  275.         std::size_t ix = element_count;
  276.  
  277.         ptr += element_count * element_size;
  278.  
  279.         __try
  280.           {
  281.             while (ix--)
  282.               {
  283.                 ptr -= element_size;
  284.                 destructor(ptr);
  285.               }
  286.           }
  287.         __catch(...)
  288.           {
  289.             std::terminate();
  290.           }
  291.       }
  292.   }
  293.  
  294.   // Destruct and release array.
  295.   extern "C" void
  296.   __cxa_vec_delete(void *array_address,
  297.                    std::size_t element_size,
  298.                    std::size_t padding_size,
  299.                    __cxa_cdtor_type destructor)
  300.   {
  301.     __cxa_vec_delete2(array_address, element_size, padding_size,
  302.                        destructor,
  303.                        &operator delete []);
  304.   }
  305.  
  306.   extern "C" void
  307.   __cxa_vec_delete2(void *array_address,
  308.                     std::size_t element_size,
  309.                     std::size_t padding_size,
  310.                     __cxa_cdtor_type destructor,
  311.                     void (*dealloc) (void *))
  312.   {
  313.     if (!array_address)
  314.       return;
  315.  
  316.     char* base = static_cast<char *>(array_address);
  317.  
  318.     if (padding_size)
  319.       {
  320.         std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1];
  321.         base -= padding_size;
  322.         __try
  323.           {
  324.             __cxa_vec_dtor(array_address, element_count, element_size,
  325.                            destructor);
  326.           }
  327.         __catch(...)
  328.           {
  329.             {
  330.               uncatch_exception ue;
  331.               dealloc(base);
  332.             }
  333.             __throw_exception_again;
  334.           }
  335.       }
  336.     dealloc(base);
  337.   }
  338.  
  339.   extern "C" void
  340.   __cxa_vec_delete3(void *array_address,
  341.                     std::size_t element_size,
  342.                     std::size_t padding_size,
  343.                      __cxa_cdtor_type destructor,
  344.                     void (*dealloc) (void *, std::size_t))
  345.   {
  346.     if (!array_address)
  347.       return;
  348.  
  349.     char* base = static_cast <char *> (array_address);
  350.     std::size_t size = 0;
  351.  
  352.     if (padding_size)
  353.       {
  354.         std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1];
  355.         base -= padding_size;
  356.         size = element_count * element_size + padding_size;
  357.         __try
  358.           {
  359.             __cxa_vec_dtor(array_address, element_count, element_size,
  360.                            destructor);
  361.           }
  362.         __catch(...)
  363.           {
  364.             {
  365.               uncatch_exception ue;
  366.               dealloc(base, size);
  367.             }
  368.             __throw_exception_again;
  369.           }
  370.       }
  371.     dealloc(base, size);
  372.   }
  373. } // namespace __cxxabiv1
  374.  
  375. #if defined(__arm__) && defined(__ARM_EABI__)
  376.  
  377. // The ARM C++ ABI requires that the library provide these additional
  378. // helper functions.  There are placed in this file, despite being
  379. // architecture-specifier, so that the compiler can inline the __cxa
  380. // functions into these functions as appropriate.
  381.  
  382. namespace __aeabiv1
  383. {
  384.   extern "C" void *
  385.   __aeabi_vec_ctor_nocookie_nodtor (void *array_address,
  386.                                     abi::__cxa_cdtor_type constructor,
  387.                                     std::size_t element_size,
  388.                                     std::size_t element_count)
  389.   {
  390.     return abi::__cxa_vec_ctor (array_address, element_count, element_size,
  391.                                 constructor, /*destructor=*/NULL);
  392.   }
  393.  
  394.   extern "C" void *
  395.   __aeabi_vec_ctor_cookie_nodtor (void *array_address,
  396.                                   abi::__cxa_cdtor_type constructor,
  397.                                   std::size_t element_size,
  398.                                   std::size_t element_count)
  399.   {
  400.     if (array_address == NULL)
  401.       return NULL;
  402.  
  403.     array_address = reinterpret_cast<std::size_t *>(array_address) + 2;
  404.     reinterpret_cast<std::size_t *>(array_address)[-2] = element_size;
  405.     reinterpret_cast<std::size_t *>(array_address)[-1] = element_count;
  406.     return abi::__cxa_vec_ctor (array_address,
  407.                                 element_count, element_size,
  408.                                 constructor, /*destructor=*/NULL);
  409.   }
  410.  
  411.   extern "C" void *
  412.   __aeabi_vec_cctor_nocookie_nodtor (void *dest_array,
  413.                                      void *src_array,
  414.                                      std::size_t element_size,
  415.                                      std::size_t element_count,
  416.                                      void *(*constructor) (void *, void *))
  417.   {
  418.     return abi::__cxa_vec_cctor (dest_array, src_array,
  419.                                  element_count, element_size,
  420.                                  constructor, NULL);
  421.   }
  422.  
  423.   extern "C" void *
  424.   __aeabi_vec_new_cookie_noctor (std::size_t element_size,
  425.                                  std::size_t element_count)
  426.   {
  427.     return abi::__cxa_vec_new(element_count, element_size,
  428.                               2 * sizeof (std::size_t),
  429.                               /*constructor=*/NULL, /*destructor=*/NULL);
  430.   }
  431.  
  432.   extern "C" void *
  433.   __aeabi_vec_new_nocookie (std::size_t element_size,
  434.                             std::size_t element_count,
  435.                             abi::__cxa_cdtor_type constructor)
  436.   {
  437.     return abi::__cxa_vec_new (element_count, element_size, 0, constructor,
  438.                                NULL);
  439.   }
  440.  
  441.   extern "C" void *
  442.   __aeabi_vec_new_cookie_nodtor (std::size_t element_size,
  443.                                  std::size_t element_count,
  444.                                  abi::__cxa_cdtor_type constructor)
  445.   {
  446.     return abi::__cxa_vec_new(element_count, element_size,
  447.                               2 * sizeof (std::size_t),
  448.                               constructor, NULL);
  449.   }
  450.  
  451.   extern "C" void *
  452.   __aeabi_vec_new_cookie(std::size_t element_size,
  453.                          std::size_t element_count,
  454.                          abi::__cxa_cdtor_type constructor,
  455.                          abi::__cxa_cdtor_type destructor)
  456.   {
  457.     return abi::__cxa_vec_new (element_count, element_size,
  458.                                2 * sizeof (std::size_t),
  459.                                constructor, destructor);
  460.   }
  461.  
  462.  
  463.   extern "C" void *
  464.   __aeabi_vec_dtor (void *array_address,
  465.                     abi::__cxa_cdtor_type destructor,
  466.                     std::size_t element_size,
  467.                     std::size_t element_count)
  468.   {
  469.     abi::__cxa_vec_dtor (array_address, element_count, element_size,
  470.                          destructor);
  471.     return reinterpret_cast<std::size_t*> (array_address) - 2;
  472.   }
  473.  
  474.   extern "C" void *
  475.   __aeabi_vec_dtor_cookie (void *array_address,
  476.                            abi::__cxa_cdtor_type destructor)
  477.   {
  478.     if (!array_address)
  479.       return NULL;
  480.  
  481.     abi::__cxa_vec_dtor (array_address,
  482.                          reinterpret_cast<std::size_t *>(array_address)[-1],
  483.                          reinterpret_cast<std::size_t *>(array_address)[-2],
  484.                          destructor);
  485.     return reinterpret_cast<std::size_t*> (array_address) - 2;
  486.   }
  487.  
  488.  
  489.   extern "C" void
  490.   __aeabi_vec_delete (void *array_address,
  491.                       abi::__cxa_cdtor_type destructor)
  492.   {
  493.     if (!array_address)
  494.       return;
  495.  
  496.     abi::__cxa_vec_delete (array_address,
  497.                            reinterpret_cast<std::size_t *>(array_address)[-2],
  498.                            2 * sizeof (std::size_t),
  499.                            destructor);
  500.   }
  501.  
  502.   extern "C" void
  503.   __aeabi_vec_delete3 (void *array_address,
  504.                        abi::__cxa_cdtor_type destructor,
  505.                        void (*dealloc) (void *, std::size_t))
  506.   {
  507.     if (!array_address)
  508.       return;
  509.  
  510.     abi::__cxa_vec_delete3 (array_address,
  511.                             reinterpret_cast<std::size_t *>(array_address)[-2],
  512.                             2 * sizeof (std::size_t),
  513.                             destructor, dealloc);
  514.   }
  515.  
  516.   extern "C" void
  517.   __aeabi_vec_delete3_nodtor (void *array_address,
  518.                               void (*dealloc) (void *, std::size_t))
  519.   {
  520.     if (!array_address)
  521.       return;
  522.  
  523.     abi::__cxa_vec_delete3 (array_address,
  524.                             reinterpret_cast<std::size_t *>(array_address)[-2],
  525.                             2 * sizeof (std::size_t),
  526.                             /*destructor=*/NULL, dealloc);
  527.   }
  528. } // namespace __aeabiv1
  529.  
  530. #endif // defined(__arm__) && defined(__ARM_EABI__)
  531.