1 //===-- FEnvSafeTest.cpp ---------------------------------------*- C++ -*-===// 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 "FEnvSafeTest.h" 10 11 #include "src/__support/FPUtil/FEnvImpl.h" 12 #include "src/__support/macros/config.h" 13 #include "src/__support/macros/properties/architectures.h" 14 15 namespace LIBC_NAMESPACE_DECL { 16 namespace testing { 17 18 void FEnvSafeTest::PreserveFEnv::check() { 19 fenv_t after; 20 test.get_fenv(after); 21 test.expect_fenv_eq(before, after); 22 } 23 24 void FEnvSafeTest::TearDown() { 25 if (!should_be_unchanged) { 26 restore_fenv(); 27 } 28 } 29 30 void FEnvSafeTest::get_fenv(fenv_t &fenv) { 31 ASSERT_EQ(LIBC_NAMESPACE::fputil::get_env(&fenv), 0); 32 } 33 34 void FEnvSafeTest::set_fenv(const fenv_t &fenv) { 35 ASSERT_EQ(LIBC_NAMESPACE::fputil::set_env(&fenv), 0); 36 } 37 38 void FEnvSafeTest::expect_fenv_eq(const fenv_t &before_fenv, 39 const fenv_t &after_fenv) { 40 #if defined(LIBC_TARGET_ARCH_IS_AARCH64) 41 using FPState = LIBC_NAMESPACE::fputil::FEnv::FPState; 42 const FPState &before_state = reinterpret_cast<const FPState &>(before_fenv); 43 const FPState &after_state = reinterpret_cast<const FPState &>(after_fenv); 44 45 EXPECT_EQ(before_state.ControlWord, after_state.ControlWord); 46 EXPECT_EQ(before_state.StatusWord, after_state.StatusWord); 47 48 #elif defined(LIBC_TARGET_ARCH_IS_X86) && !defined(__APPLE__) 49 using LIBC_NAMESPACE::fputil::internal::FPState; 50 const FPState &before_state = reinterpret_cast<const FPState &>(before_fenv); 51 const FPState &after_state = reinterpret_cast<const FPState &>(after_fenv); 52 53 #if defined(_WIN32) 54 EXPECT_EQ(before_state.control_word, after_state.control_word); 55 EXPECT_EQ(before_state.status_word, after_state.status_word); 56 #elif defined(__APPLE__) 57 EXPECT_EQ(before_state.control_word, after_state.control_word); 58 EXPECT_EQ(before_state.status_word, after_state.status_word); 59 EXPECT_EQ(before_state.mxcsr, after_state.mxcsr); 60 #else 61 EXPECT_EQ(before_state.x87_status.control_word, 62 after_state.x87_status.control_word); 63 EXPECT_EQ(before_state.x87_status.status_word, 64 after_state.x87_status.status_word); 65 EXPECT_EQ(before_state.mxcsr, after_state.mxcsr); 66 #endif 67 68 #elif defined(LIBC_TARGET_ARCH_IS_ARM) && defined(__ARM_FP) 69 using LIBC_NAMESPACE::fputil::FEnv; 70 const FEnv &before_state = reinterpret_cast<const FEnv &>(before_fenv); 71 const FEnv &after_state = reinterpret_cast<const FEnv &>(after_fenv); 72 73 EXPECT_EQ(before_state.fpscr, after_state.fpscr); 74 75 #elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV) 76 const uint32_t &before_fcsr = reinterpret_cast<const uint32_t &>(before_fenv); 77 const uint32_t &after_fcsr = reinterpret_cast<const uint32_t &>(after_fenv); 78 EXPECT_EQ(before_fcsr, after_fcsr); 79 80 #else 81 // No arch-specific `fenv_t` support, so nothing to compare. 82 83 #endif 84 } 85 86 } // namespace testing 87 } // namespace LIBC_NAMESPACE_DECL 88