1 //===-- Unittests for feenableexcept  -------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "src/__support/architectures.h"
10 #include "src/fenv/fedisableexcept.h"
11 #include "src/fenv/feenableexcept.h"
12 #include "src/fenv/fegetexcept.h"
13 
14 #include "utils/UnitTest/Test.h"
15 
16 #include <fenv.h>
17 
TEST(LlvmLibcFEnvTest,EnableTest)18 TEST(LlvmLibcFEnvTest, EnableTest) {
19 #if defined(LLVM_LIBC_ARCH_AARCH64)
20   // Few aarch64 HW implementations do not trap exceptions. We skip this test
21   // completely on such HW.
22   //
23   // Whether HW supports trapping exceptions or not is deduced by enabling an
24   // exception and reading back to see if the exception got enabled. If the
25   // exception did not get enabled, then it means that the HW does not support
26   // trapping exceptions.
27   __llvm_libc::fedisableexcept(FE_ALL_EXCEPT);
28   __llvm_libc::feenableexcept(FE_DIVBYZERO);
29   if (__llvm_libc::fegetexcept() == 0)
30     return;
31 #endif // defined(LLVM_LIBC_ARCH_AARCH64)
32 
33   int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW,
34                    FE_UNDERFLOW};
35   __llvm_libc::fedisableexcept(FE_ALL_EXCEPT);
36   ASSERT_EQ(0, __llvm_libc::fegetexcept());
37 
38   for (int e : excepts) {
39     __llvm_libc::feenableexcept(e);
40     ASSERT_EQ(e, __llvm_libc::fegetexcept());
41     __llvm_libc::fedisableexcept(e);
42   }
43 
44   for (int e1 : excepts) {
45     for (int e2 : excepts) {
46       __llvm_libc::feenableexcept(e1 | e2);
47       ASSERT_EQ(e1 | e2, __llvm_libc::fegetexcept());
48       __llvm_libc::fedisableexcept(e1 | e2);
49     }
50   }
51 
52   for (int e1 : excepts) {
53     for (int e2 : excepts) {
54       for (int e3 : excepts) {
55         __llvm_libc::feenableexcept(e1 | e2 | e3);
56         ASSERT_EQ(e1 | e2 | e3, __llvm_libc::fegetexcept());
57         __llvm_libc::fedisableexcept(e1 | e2 | e3);
58       }
59     }
60   }
61 
62   for (int e1 : excepts) {
63     for (int e2 : excepts) {
64       for (int e3 : excepts) {
65         for (int e4 : excepts) {
66           __llvm_libc::feenableexcept(e1 | e2 | e3 | e4);
67           ASSERT_EQ(e1 | e2 | e3 | e4, __llvm_libc::fegetexcept());
68           __llvm_libc::fedisableexcept(e1 | e2 | e3 | e4);
69         }
70       }
71     }
72   }
73 
74   for (int e1 : excepts) {
75     for (int e2 : excepts) {
76       for (int e3 : excepts) {
77         for (int e4 : excepts) {
78           for (int e5 : excepts) {
79             __llvm_libc::feenableexcept(e1 | e2 | e3 | e4 | e5);
80             ASSERT_EQ(e1 | e2 | e3 | e4 | e5, __llvm_libc::fegetexcept());
81             __llvm_libc::fedisableexcept(e1 | e2 | e3 | e4 | e5);
82           }
83         }
84       }
85     }
86   }
87 }
88