1*6c3f53c7SSiva Chandra Reddy //===-- FPExceptMatchers.cpp ----------------------------------------------===// 2*6c3f53c7SSiva Chandra Reddy // 3*6c3f53c7SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*6c3f53c7SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 5*6c3f53c7SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*6c3f53c7SSiva Chandra Reddy // 7*6c3f53c7SSiva Chandra Reddy //===----------------------------------------------------------------------===// 8*6c3f53c7SSiva Chandra Reddy 9*6c3f53c7SSiva Chandra Reddy #include "FPExceptMatcher.h" 10*6c3f53c7SSiva Chandra Reddy 11*6c3f53c7SSiva Chandra Reddy #include <fenv.h> 12*6c3f53c7SSiva Chandra Reddy #include <memory> 13*6c3f53c7SSiva Chandra Reddy #include <setjmp.h> 14*6c3f53c7SSiva Chandra Reddy #include <signal.h> 15*6c3f53c7SSiva Chandra Reddy 16*6c3f53c7SSiva Chandra Reddy namespace __llvm_libc { 17*6c3f53c7SSiva Chandra Reddy namespace fputil { 18*6c3f53c7SSiva Chandra Reddy namespace testing { 19*6c3f53c7SSiva Chandra Reddy 20*6c3f53c7SSiva Chandra Reddy #if defined(_WIN32) 21*6c3f53c7SSiva Chandra Reddy #define sigjmp_buf jmp_buf 22*6c3f53c7SSiva Chandra Reddy #define sigsetjmp(buf, save) setjmp(buf) 23*6c3f53c7SSiva Chandra Reddy #define siglongjmp(buf, val) longjmp(buf, val) 24*6c3f53c7SSiva Chandra Reddy #endif 25*6c3f53c7SSiva Chandra Reddy 26*6c3f53c7SSiva Chandra Reddy static thread_local sigjmp_buf jumpBuffer; 27*6c3f53c7SSiva Chandra Reddy static thread_local bool caughtExcept; 28*6c3f53c7SSiva Chandra Reddy sigfpeHandler(int sig)29*6c3f53c7SSiva Chandra Reddystatic void sigfpeHandler(int sig) { 30*6c3f53c7SSiva Chandra Reddy caughtExcept = true; 31*6c3f53c7SSiva Chandra Reddy siglongjmp(jumpBuffer, -1); 32*6c3f53c7SSiva Chandra Reddy } 33*6c3f53c7SSiva Chandra Reddy FPExceptMatcher(FunctionCaller * func)34*6c3f53c7SSiva Chandra ReddyFPExceptMatcher::FPExceptMatcher(FunctionCaller *func) { 35*6c3f53c7SSiva Chandra Reddy auto oldSIGFPEHandler = signal(SIGFPE, &sigfpeHandler); 36*6c3f53c7SSiva Chandra Reddy std::unique_ptr<FunctionCaller> funcUP(func); 37*6c3f53c7SSiva Chandra Reddy 38*6c3f53c7SSiva Chandra Reddy caughtExcept = false; 39*6c3f53c7SSiva Chandra Reddy fenv_t oldEnv; 40*6c3f53c7SSiva Chandra Reddy fegetenv(&oldEnv); 41*6c3f53c7SSiva Chandra Reddy if (sigsetjmp(jumpBuffer, 1) == 0) 42*6c3f53c7SSiva Chandra Reddy funcUP->call(); 43*6c3f53c7SSiva Chandra Reddy // We restore the previous floating point environment after 44*6c3f53c7SSiva Chandra Reddy // the call to the function which can potentially raise SIGFPE. 45*6c3f53c7SSiva Chandra Reddy fesetenv(&oldEnv); 46*6c3f53c7SSiva Chandra Reddy signal(SIGFPE, oldSIGFPEHandler); 47*6c3f53c7SSiva Chandra Reddy exceptionRaised = caughtExcept; 48*6c3f53c7SSiva Chandra Reddy } 49*6c3f53c7SSiva Chandra Reddy 50*6c3f53c7SSiva Chandra Reddy } // namespace testing 51*6c3f53c7SSiva Chandra Reddy } // namespace fputil 52*6c3f53c7SSiva Chandra Reddy } // namespace __llvm_libc 53