EricWF updated this revision to Diff 34128.
EricWF added a comment.

Address @joerg's comment and use `posix_memalign` when available. This patch 
does not fix the case where `posix_memalign` is unavailable but that should be 
rare and can come in another patch.

Thi patch also defers all changes to `fallback_malloc` to 
http://reviews.llvm.org/D12669.


http://reviews.llvm.org/D12512

Files:
  CMakeLists.txt
  cmake/config-ix.cmake
  src/cxa_exception.cpp
  test/test_cxa_allocate_exception.pass.cpp

Index: test/test_cxa_allocate_exception.pass.cpp
===================================================================
--- /dev/null
+++ test/test_cxa_allocate_exception.pass.cpp
@@ -0,0 +1,65 @@
+//===--------------------- test_fallback_malloc.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.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03
+
+// void* __cxa_allocate_exception(size_t);
+// void  __cxa_free_exception(void*);
+// void* __cxa_allocate_dependent_exception();
+// void  __cxa_free_dependent_exception();
+
+// __cxa_exception is specified with __attribute__((aligned)) for GNU unwind.
+// This means that during 32 bit builds __cxa_exception is "over aligned". This
+// test checks that __cxa_allocate_exception return correctly overaligned memory.
+// See PR24604 - https://llvm.org/bugs/show_bug.cgi?id=24604
+
+#include "../src/cxa_exception.hpp"
+#include <cstddef> // for std::max_align_t
+#include <cassert>
+
+#if defined(__GNUC__) && !defined(_LP64)
+#define SHOULD_BE_OVERALIGNED 1
+#endif
+
+using namespace __cxxabiv1;
+
+const std::size_t max_alignment = alignof(std::max_align_t);
+const std::size_t required_alignment = alignof(__cxa_exception);
+const bool requires_over_alignment = max_alignment < required_alignment;
+
+static_assert(alignof(__cxa_exception) == alignof(__cxa_dependent_exception),
+              "They should have the same alignment requirements");
+
+#if defined(__GNUC__) && !defined(_LP64)
+static_assert(alignof(__cxa_exception) > alignof(std::max_align_t),
+              "On 32 bit platforms __cxa_exception is expected to be over aligned.");
+#endif
+
+void test_cxa_allocate_exception() {
+    for (int i=0; i < 4096; ++i) {
+        void* ptr = __cxa_allocate_exception(i);
+        assert(ptr);
+        assert(reinterpret_cast<std::size_t>(ptr) % required_alignment == 0);
+        __cxa_free_exception(ptr);
+    }
+}
+
+void test_cxa_allocate_dependent_exception() {
+    for (int i=0; i < 100; ++i) {
+        void* ptr = __cxa_allocate_dependent_exception();
+        assert(ptr);
+        assert(reinterpret_cast<std::size_t>(ptr) % required_alignment == 0);
+        __cxa_free_dependent_exception(ptr);
+    }
+}
+
+int main() {
+    test_cxa_allocate_exception();
+    test_cxa_allocate_dependent_exception();
+}
Index: src/cxa_exception.cpp
===================================================================
--- src/cxa_exception.cpp
+++ src/cxa_exception.cpp
@@ -118,13 +118,22 @@
 
 //  Allocate some memory from _somewhere_
 static void *do_malloc(size_t size) {
-    void *ptr = std::malloc(size);
+    void* ptr = nullptr;
+#ifndef LIBCXXABI_HAS_NO_POSIX_MEMALIGN
+    (void)posix_memalign(&ptr, alignof(__cxa_exception), size);
+#else
+    // FIXME: The output of malloc needs to be manually aligned to a 16 byte
+    // on 32 bit targets.
+    ptr = std::malloc(size);
+#endif
     if (NULL == ptr) // if malloc fails, fall back to emergency stash
         ptr = fallback_malloc(size);
     return ptr;
 }
 
 static void do_free(void *ptr) {
+    // NOTE: std::free can free pointers allocated with both std::malloc
+    // and posix_memalign.
     is_fallback_ptr(ptr) ? fallback_free(ptr) : std::free(ptr);
 }
 
Index: cmake/config-ix.cmake
===================================================================
--- cmake/config-ix.cmake
+++ cmake/config-ix.cmake
@@ -1,6 +1,7 @@
 include(CheckLibraryExists)
 include(CheckCCompilerFlag)
 include(CheckCXXCompilerFlag)
+include(CheckSymbolExists)
 
 # Check compiler flags
 check_c_compiler_flag(-funwind-tables         LIBCXXABI_HAS_FUNWIND_TABLES)
@@ -45,3 +46,6 @@
 check_library_exists(gcc_eh _Unwind_GetRegionStart "" LIBCXXABI_HAS_GCC_EH_LIB)
 check_library_exists(c __cxa_thread_atexit_impl ""
   LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
+
+# Check symbols
+check_symbol_exists(posix_memalign stdlib.h LIBCXXABI_HAS_POSIX_MEMALIGN)
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -275,6 +275,10 @@
   add_definitions(-DLIBCXXABI_HAS_NO_THREADS=1)
 endif()
 
+if (NOT LIBCXXABI_HAS_POSIX_MEMALIGN)
+  add_definitions(-DLIBCXXABI_HAS_NO_POSIX_MEMALIGN=1)
+endif()
+
 # This is the _ONLY_ place where add_definitions is called.
 if (MSVC)
   add_definitions(-D_CRT_SECURE_NO_WARNINGS)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to