Memory manangement routines for exception objects

llvm-svn: 135587
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: e2dcb75b2e4b86b4529e6727571813552718ac19
diff --git a/src/cxa_exception.cpp b/src/cxa_exception.cpp
new file mode 100644
index 0000000..93a4bd4
--- /dev/null
+++ b/src/cxa_exception.cpp
@@ -0,0 +1,107 @@
+//===------------------------- cxa_exception.cpp --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//  
+//  This file implements the "Exception Handling APIs"
+//  http://www.codesourcery.com/public/cxx-abi/abi-eh.html
+//  
+//===----------------------------------------------------------------------===//
+
+#include "cxxabi.h"
+
+#include <exception>        // for std::terminate
+#include <cstdlib>          // for malloc, free
+#include <string>           // for memset
+#include <pthread.h>
+
+#include "cxa_exception.hpp"
+#include "cxa_exception_storage.hpp"
+
+namespace __cxxabiv1 {
+
+//  Utility routines
+static __cxa_exception *exception_from_object ( void *p ) {
+    return ((__cxa_exception *) p ) - 1;
+    }
+    
+void * object_from_exception ( void *p ) {
+    return (void *) (((__cxa_exception *) p ) + 1 );
+    }
+
+static size_t object_size_from_exception_size ( size_t size ) {
+    return size + sizeof (__cxa_exception);
+    }
+
+#include "fallback_malloc.cpp"
+
+//  Allocate some memory from _somewhere_
+static void *do_malloc ( size_t size ) throw () {
+    void *ptr = std::malloc ( size );
+    if ( NULL == ptr )  // if malloc fails, fall back to emergency stash
+        ptr = fallback_malloc ( size );
+    return ptr;
+    }
+
+//  Didn't know you could "return <expression>" from a void function, did you?
+//  Well, you can, if the type of the expression is "void" also.
+static void do_free ( void *ptr ) throw () {
+    return is_fallback_ptr ( ptr ) ? fallback_free ( ptr ) : std::free ( ptr );
+    }
+
+static thread_local_storage<__cxa_eh_globals> __globals;
+// pthread_once_t __globals::flag_ = PTHREAD_ONCE_INIT;
+
+extern "C" {
+
+//  Allocate a __cxa_exception object, and zero-fill it.
+//  Reserve "thrown_size" bytes on the end for the user's exception
+//  object. Zero-fill the object. If memory can't be allocated, call
+//  std::terminate. Return a pointer to the memory to be used for the
+//  user's exception object.
+void * __cxa_allocate_exception (size_t thrown_size) throw() {
+    size_t actual_size = object_size_from_exception_size ( thrown_size );
+    void *ptr = do_malloc ( actual_size );
+    if ( NULL == ptr )
+        std::terminate ();
+    std::memset ( ptr, 0, actual_size );
+    return object_from_exception ( ptr );
+    }
+
+
+//  Free a __cxa_exception object allocated with __cxa_allocate_exception.
+void __cxa_free_exception (void * thrown_exception) throw() {
+    do_free ( exception_from_object ( thrown_exception ));
+    }
+
+
+//  This function shall allocate a __cxa_dependent_exception and
+//  return a pointer to it. (Really to the object, not past its' end).
+//  Otherwise, it will work like __cxa_allocate_exception.
+void * __cxa_allocate_dependent_exception () throw() {
+    size_t actual_size = sizeof ( __cxa_dependent_exception );
+    void *ptr = do_malloc ( actual_size );
+    if ( NULL == ptr )
+        std::terminate ();
+    std::memset ( ptr, 0, actual_size );
+//  bookkeeping here ?
+    return ptr;
+    }
+
+
+//  This function shall free a dependent_exception.
+//  It does not affect the reference count of the primary exception.
+void __cxa_free_dependent_exception (void * dependent_exception) throw() {
+//  I'm pretty sure there's no bookkeeping here
+    do_free ( dependent_exception );
+    }
+
+__cxa_eh_globals * __cxa_get_globals      () throw() { return __globals.get_tls (); }
+__cxa_eh_globals * __cxa_get_globals_fast () throw() { return __globals.get_tls_fast (); }
+
+}  // extern "C"
+
+}  // abi