Mercurial > hg > CbC > CbC_llvm
view flang/lib/Evaluate/host.cpp @ 182:0f533c0a1429
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 31 May 2020 19:50:32 +0900 |
parents | 0572611fdcc8 |
children | 2e18cbf3894f |
line wrap: on
line source
//===-- lib/Evaluate/host.cpp ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "host.h" #include "flang/Common/idioms.h" #include "llvm/Support/Errno.h" #include <cfenv> namespace Fortran::evaluate::host { using namespace Fortran::parser::literals; void HostFloatingPointEnvironment::SetUpHostFloatingPointEnvironment( FoldingContext &context) { errno = 0; if (feholdexcept(&originalFenv_) != 0) { common::die("Folding with host runtime: feholdexcept() failed: %s", llvm::sys::StrError(errno).c_str()); return; } if (fegetenv(¤tFenv_) != 0) { common::die("Folding with host runtime: fegetenv() failed: %s", llvm::sys::StrError(errno).c_str()); return; } #if __x86_64__ hasSubnormalFlushingHardwareControl_ = true; if (context.flushSubnormalsToZero()) { currentFenv_.__mxcsr |= 0x8000; // result currentFenv_.__mxcsr |= 0x0040; // operands } else { currentFenv_.__mxcsr &= ~0x8000; // result currentFenv_.__mxcsr &= ~0x0040; // operands } #elif defined(__aarch64__) #if defined(__GNU_LIBRARY__) hasSubnormalFlushingHardwareControl_ = true; if (context.flushSubnormalsToZero()) { currentFenv_.__fpcr |= (1U << 24); // control register } else { currentFenv_.__fpcr &= ~(1U << 24); // control register } #elif defined(__BIONIC__) hasSubnormalFlushingHardwareControl_ = true; if (context.flushSubnormalsToZero()) { currentFenv_.__control |= (1U << 24); // control register } else { currentFenv_.__control &= ~(1U << 24); // control register } #else // If F18 is built with other C libraries on AArch64, software flushing will // be performed around host library calls if subnormal flushing is requested #endif #else // If F18 is not built on one of the above host architecture, software // flushing will be performed around host library calls if needed. #endif #ifdef __clang__ // clang does not ensure that floating point environment flags are meaningful. // It may perform optimizations that will impact the floating point // environment. For instance, libc++ complex float tan and tanh compilation // with clang -O2 introduces a division by zero on X86 in unused slots of xmm // registers. Therefore, fetestexcept should not be used. hardwareFlagsAreReliable_ = false; #endif errno = 0; if (fesetenv(¤tFenv_) != 0) { common::die("Folding with host runtime: fesetenv() failed: %s", llvm::sys::StrError(errno).c_str()); return; } switch (context.rounding().mode) { case common::RoundingMode::TiesToEven: fesetround(FE_TONEAREST); break; case common::RoundingMode::ToZero: fesetround(FE_TOWARDZERO); break; case common::RoundingMode::Up: fesetround(FE_UPWARD); break; case common::RoundingMode::Down: fesetround(FE_DOWNWARD); break; case common::RoundingMode::TiesAwayFromZero: fesetround(FE_TONEAREST); context.messages().Say( "TiesAwayFromZero rounding mode is not available when folding constants" " with host runtime; using TiesToEven instead"_en_US); break; } flags_.clear(); errno = 0; } void HostFloatingPointEnvironment::CheckAndRestoreFloatingPointEnvironment( FoldingContext &context) { int errnoCapture{errno}; if (hardwareFlagsAreReliable()) { int exceptions{fetestexcept(FE_ALL_EXCEPT)}; if (exceptions & FE_INVALID) { flags_.set(RealFlag::InvalidArgument); } if (exceptions & FE_DIVBYZERO) { flags_.set(RealFlag::DivideByZero); } if (exceptions & FE_OVERFLOW) { flags_.set(RealFlag::Overflow); } if (exceptions & FE_UNDERFLOW) { flags_.set(RealFlag::Underflow); } if (exceptions & FE_INEXACT) { flags_.set(RealFlag::Inexact); } } if (flags_.empty()) { if (errnoCapture == EDOM) { flags_.set(RealFlag::InvalidArgument); } if (errnoCapture == ERANGE) { // can't distinguish over/underflow from errno flags_.set(RealFlag::Overflow); } } if (!flags_.empty()) { RealFlagWarnings(context, flags_, "intrinsic function"); } errno = 0; if (fesetenv(&originalFenv_) != 0) { std::fprintf( stderr, "fesetenv() failed: %s\n", llvm::sys::StrError(errno).c_str()); common::die( "Folding with host runtime: fesetenv() failed while restoring fenv: %s", llvm::sys::StrError(errno).c_str()); } errno = 0; } } // namespace Fortran::evaluate::host