diff --git a/Docs/sphinx_documentation/source/Debugging.rst b/Docs/sphinx_documentation/source/Debugging.rst index 1517f3cd2db..89eee31c2bd 100644 --- a/Docs/sphinx_documentation/source/Debugging.rst +++ b/Docs/sphinx_documentation/source/Debugging.rst @@ -27,6 +27,7 @@ use of uninitialized values, AMReX also initializes ``FArrayBox``\ s in ``MulitFab``\ s and arrays allocated by ``bl_allocate`` to signaling NaNs when it is compiled with ``TEST=TRUE`` or ``DEBUG=TRUE`` in GNU make, or with ``-DCMAKE_BUILD_TYPE=Debug`` in CMake. One can also control the setting for ``FArrayBox`` using the runtime parameter, ``fab.init_snan``. +Note for Macs, M1 and M2 chips using Arm64 architecture are not able to trap division by zero. One can get more information than the backtrace of the call stack by instrumenting the code. Here is an example. diff --git a/Src/Base/AMReX.cpp b/Src/Base/AMReX.cpp index 6b07aaeefcf..6bb199f21b6 100644 --- a/Src/Base/AMReX.cpp +++ b/Src/Base/AMReX.cpp @@ -102,6 +102,7 @@ namespace system int handle_sigint; int handle_sigabrt; int handle_sigfpe; + int handle_sigill; int call_addr2line; int throw_exception; int regtest_reduction; @@ -127,6 +128,7 @@ namespace { SignalHandler prev_handler_sigint = SIG_ERR; // NOLINT(performance-no-int-to-ptr) SignalHandler prev_handler_sigabrt = SIG_ERR; // NOLINT(performance-no-int-to-ptr) SignalHandler prev_handler_sigfpe = SIG_ERR; // NOLINT(performance-no-int-to-ptr) + SignalHandler prev_handler_sigill = SIG_ERR; // NOLINT(performance-no-int-to-ptr) #if defined(__linux__) int prev_fpe_excepts = 0; int curr_fpe_excepts = 0; @@ -329,6 +331,7 @@ amrex::Initialize (int& argc, char**& argv, bool build_parm_parse, system::handle_sigint = 1; system::handle_sigabrt = 1; system::handle_sigfpe = 1; + system::handle_sigill = 1; system::call_addr2line = 1; system::throw_exception = 0; system::osout = &a_osout; @@ -509,6 +512,7 @@ amrex::Initialize (int& argc, char**& argv, bool build_parm_parse, pp.queryAdd("handle_sigint" , system::handle_sigint ); pp.queryAdd("handle_sigabrt", system::handle_sigabrt); pp.queryAdd("handle_sigfpe" , system::handle_sigfpe ); + pp.queryAdd("handle_sigill" , system::handle_sigill ); // We save the singal handlers and restore them in Finalize. if (system::handle_sigsegv) { @@ -566,6 +570,26 @@ amrex::Initialize (int& argc, char**& argv, bool build_parm_parse, } #endif } + + prev_handler_sigill = SIG_ERR; // NOLINT(performance-no-int-to-ptr) + if (system::handle_sigill) + { +#if defined(__APPLE__) && defined(__aarch64__) + int invalid = 0, divbyzero=0, overflow=0; + pp.queryAdd("fpe_trap_invalid", invalid); + pp.queryAdd("fpe_trap_zero", divbyzero); + pp.queryAdd("fpe_trap_overflow", overflow); + + fenv_t env; + fegetenv(&env); + if (invalid) env.__fpcr |= __fpcr_trap_invalid; + if (divbyzero) env.__fpcr |= __fpcr_trap_divbyzero; + if (overflow) env.__fpcr |= __fpcr_trap_overflow; + fesetenv(&env); + // SIGILL ref: https://developer.apple.com/forums/thread/689159 +#endif + prev_handler_sigill = std::signal(SIGILL, BLBackTrace::handler); + } } #ifdef AMREX_USE_HYPRE @@ -762,6 +786,7 @@ amrex::Finalize (amrex::AMReX* pamrex) if (prev_handler_sigint != SIG_ERR) std::signal(SIGINT , prev_handler_sigint); // NOLINT(performance-no-int-to-ptr) if (prev_handler_sigabrt != SIG_ERR) std::signal(SIGABRT, prev_handler_sigabrt); // NOLINT(performance-no-int-to-ptr) if (prev_handler_sigfpe != SIG_ERR) std::signal(SIGFPE , prev_handler_sigfpe); // NOLINT(performance-no-int-to-ptr) + if (prev_handler_sigill != SIG_ERR) std::signal(SIGILL , prev_handler_sigill); // NOLINT(performance-no-int-to-ptr) #if defined(__linux__) #if !defined(__PGI) || (__PGIC__ >= 16) if (curr_fpe_excepts != 0) { diff --git a/Src/Base/AMReX_BLBackTrace.cpp b/Src/Base/AMReX_BLBackTrace.cpp index 75d9dbb2722..dcae47e2aa5 100644 --- a/Src/Base/AMReX_BLBackTrace.cpp +++ b/Src/Base/AMReX_BLBackTrace.cpp @@ -58,6 +58,9 @@ BLBackTrace::handler(int s) case SIGFPE: amrex::ErrorStream() << "Erroneous arithmetic operation\n"; break; + case SIGILL: + amrex::ErrorStream() << "SIGILL Invalid, privileged, or ill-formed instruction\n"; + break; case SIGTERM: amrex::ErrorStream() << "SIGTERM\n"; break; diff --git a/Tools/CMake/AMReXFlagsTargets.cmake b/Tools/CMake/AMReXFlagsTargets.cmake index 92d3e63fbd8..9e3073cd53f 100644 --- a/Tools/CMake/AMReXFlagsTargets.cmake +++ b/Tools/CMake/AMReXFlagsTargets.cmake @@ -131,6 +131,7 @@ target_compile_options ( Flags_FPE $<${_cxx_cray}:-K trap=fp> $<${_fortran_clang}:> $<${_cxx_clang}:-ftrapv> + $<${_cxx_appleclang}:-ftrapv> ) #