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" 14f100ec25SGuillaume 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) { 246f8dfeeeSSiva Chandra #if defined(LIBC_TARGET_ARCH_IS_ANY_ARM) || defined(LIBC_TARGET_ARCH_IS_RISCV64) 25ae8e1b8fSSiva Chandra Reddy // Few Arm 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. 32*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT); 33*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fputil::enable_except(FE_DIVBYZERO); 34*b6bc9d72SGuillaume Chatelet if (LIBC_NAMESPACE::fputil::get_except() == 0) 35c5cfbe40SSiva Chandra Reddy return; 366f8dfeeeSSiva Chandra #endif // Architectures where exception trapping is not supported 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) { 53*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT); 54*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fputil::enable_except(e); 55*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::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; 63*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::feraiseexcept(others), 0); 64*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::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. 72*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fputil::enable_except(e); 73*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::feraiseexcept(e); 74c24c18bbSSiva Chandra Reddy }); 75c24c18bbSSiva Chandra Reddy 76c24c18bbSSiva Chandra Reddy // Cleanup. 77*b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT); 78*b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::feclearexcept(FE_ALL_EXCEPT), 0); 79ab3cbe4bSSiva Chandra Reddy } 80ab3cbe4bSSiva Chandra Reddy } 81