1ab3cbe4bSSiva Chandra Reddy //===-- Unittests for feraiseexcept with exceptions enabled ---------------===// 2ab3cbe4bSSiva Chandra Reddy // 3ab3cbe4bSSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ab3cbe4bSSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 5ab3cbe4bSSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ab3cbe4bSSiva Chandra Reddy // 7ab3cbe4bSSiva Chandra Reddy //===----------------------------------------------------------------------===// 8ab3cbe4bSSiva Chandra Reddy 9ab3cbe4bSSiva Chandra Reddy #include "src/fenv/feclearexcept.h" 10ab3cbe4bSSiva Chandra Reddy #include "src/fenv/feraiseexcept.h" 11ab3cbe4bSSiva Chandra Reddy #include "src/fenv/fetestexcept.h" 12ab3cbe4bSSiva Chandra Reddy 1376ec69a9STue Ly #include "src/__support/FPUtil/FEnvImpl.h" 14*f100ec25SGuillaume Chatelet #include "src/__support/macros/properties/architectures.h" 15af1315c2SSiva Chandra Reddy #include "test/UnitTest/FPExceptMatcher.h" 16af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h" 17ab3cbe4bSSiva Chandra Reddy 18ab3cbe4bSSiva Chandra Reddy #include <fenv.h> 19ab3cbe4bSSiva Chandra Reddy #include <signal.h> 20ab3cbe4bSSiva Chandra Reddy 21ab3cbe4bSSiva Chandra Reddy // This test enables an exception and verifies that raising that exception 22ab3cbe4bSSiva Chandra Reddy // triggers SIGFPE. 231df0dbfcSMichael Jones TEST(LlvmLibcExceptionStatusTest, RaiseAndCrash) { 24a2569a76SGuillaume Chatelet #if defined(LIBC_TARGET_ARCH_IS_AARCH64) 25c5cfbe40SSiva Chandra Reddy // Few aarch64 HW implementations do not trap exceptions. We skip this test 26c5cfbe40SSiva Chandra Reddy // completely on such HW. 27c5cfbe40SSiva Chandra Reddy // 28c5cfbe40SSiva Chandra Reddy // Whether HW supports trapping exceptions or not is deduced by enabling an 29c5cfbe40SSiva Chandra Reddy // exception and reading back to see if the exception got enabled. If the 30c5cfbe40SSiva Chandra Reddy // exception did not get enabled, then it means that the HW does not support 31c5cfbe40SSiva Chandra Reddy // trapping exceptions. 321c92911eSMichael Jones __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT); 331c92911eSMichael Jones __llvm_libc::fputil::enable_except(FE_DIVBYZERO); 341c92911eSMichael Jones if (__llvm_libc::fputil::get_except() == 0) 35c5cfbe40SSiva Chandra Reddy return; 36a2569a76SGuillaume Chatelet #endif // defined(LIBC_TARGET_ARCH_IS_AARCH64) 37c5cfbe40SSiva Chandra Reddy 38ab3cbe4bSSiva Chandra Reddy // TODO: Install a floating point exception handler and verify that the 39ab3cbe4bSSiva Chandra Reddy // the expected exception was raised. One will have to longjmp back from 40ab3cbe4bSSiva Chandra Reddy // that exception handler, so such a testing can be done after we have 41ab3cbe4bSSiva Chandra Reddy // longjmp implemented. 42ab3cbe4bSSiva Chandra Reddy 43ab3cbe4bSSiva Chandra Reddy int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW, 44ab3cbe4bSSiva Chandra Reddy FE_UNDERFLOW}; 45ab3cbe4bSSiva Chandra Reddy 46cb2e2d50SMichael Jones // We '|' the individual exception flags instead of using FE_ALL_EXCEPT 47cb2e2d50SMichael Jones // as it can include non-standard extensions. Note that we should be able 48cb2e2d50SMichael Jones // to compile this file with headers from other libcs as well. 4925226f3eSMichael Jones constexpr int ALL_EXCEPTS = 50cb2e2d50SMichael Jones FE_DIVBYZERO | FE_INVALID | FE_INEXACT | FE_OVERFLOW | FE_UNDERFLOW; 51cb2e2d50SMichael Jones 52ab3cbe4bSSiva Chandra Reddy for (int e : excepts) { 531c92911eSMichael Jones __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT); 541c92911eSMichael Jones __llvm_libc::fputil::enable_except(e); 55ab3cbe4bSSiva Chandra Reddy ASSERT_EQ(__llvm_libc::feclearexcept(FE_ALL_EXCEPT), 0); 56ab3cbe4bSSiva Chandra Reddy // Raising all exceptions except |e| should not call the 57ab3cbe4bSSiva Chandra Reddy // SIGFPE handler. They should set the exception flag though, 58ff384700SSiva Chandra Reddy // so we verify that. Since other exceptions like FE_DIVBYZERO 59ff384700SSiva Chandra Reddy // can raise FE_INEXACT as well, we don't verify the other 60ff384700SSiva Chandra Reddy // exception flags when FE_INEXACT is enabled. 61ff384700SSiva Chandra Reddy if (e != FE_INEXACT) { 6225226f3eSMichael Jones int others = ALL_EXCEPTS & ~e; 63ab3cbe4bSSiva Chandra Reddy ASSERT_EQ(__llvm_libc::feraiseexcept(others), 0); 64ab3cbe4bSSiva Chandra Reddy ASSERT_EQ(__llvm_libc::fetestexcept(others), others); 65ff384700SSiva Chandra Reddy } 66ab3cbe4bSSiva Chandra Reddy 67c24c18bbSSiva Chandra Reddy ASSERT_RAISES_FP_EXCEPT([=] { 68c24c18bbSSiva Chandra Reddy // In test frameworks like Fuchsia's zxtest, this translates to 69c24c18bbSSiva Chandra Reddy // a death test which runs this closure in a different thread. So, 70c24c18bbSSiva Chandra Reddy // we enable the exception again inside this closure so that the 71c24c18bbSSiva Chandra Reddy // exception gets enabled for the thread running this closure. 721c92911eSMichael Jones __llvm_libc::fputil::enable_except(e); 73c24c18bbSSiva Chandra Reddy __llvm_libc::feraiseexcept(e); 74c24c18bbSSiva Chandra Reddy }); 75c24c18bbSSiva Chandra Reddy 76c24c18bbSSiva Chandra Reddy // Cleanup. 771c92911eSMichael Jones __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT); 78c24c18bbSSiva Chandra Reddy ASSERT_EQ(__llvm_libc::feclearexcept(FE_ALL_EXCEPT), 0); 79ab3cbe4bSSiva Chandra Reddy } 80ab3cbe4bSSiva Chandra Reddy } 81