aboutsummaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-09-20 13:53:30 +0200
committerMartin Liska <mliska@suse.cz>2022-09-20 13:53:30 +0200
commit6df29b782e87c6c800be0425023d8438fdc67b92 (patch)
tree48eebe497e384d66a7f5cf861b4b1b963785a2cd /libgfortran
parentfdb97cd0b7d15efa39ba79dca44be93debb0ef12 (diff)
parent63e3cc294d835b43701eeef9410d1b8fc8922869 (diff)
downloadgcc-6df29b782e87c6c800be0425023d8438fdc67b92.zip
gcc-6df29b782e87c6c800be0425023d8438fdc67b92.tar.gz
gcc-6df29b782e87c6c800be0425023d8438fdc67b92.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog18
-rw-r--r--libgfortran/config/fpu-387.h7
-rw-r--r--libgfortran/config/fpu-aarch64.h7
-rw-r--r--libgfortran/config/fpu-aix.h22
-rw-r--r--libgfortran/config/fpu-generic.h11
-rw-r--r--libgfortran/config/fpu-glibc.h18
-rw-r--r--libgfortran/config/fpu-sysv.h7
-rw-r--r--libgfortran/ieee/ieee_arithmetic.F9010
-rw-r--r--libgfortran/ieee/ieee_exceptions.F9063
9 files changed, 150 insertions, 13 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 51c9f5c..fab472e 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,21 @@
+2022-09-19 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ * ieee/ieee_exceptions.F90: Add IEEE_MODES_TYPE, IEEE_GET_MODES
+ and IEEE_SET_MODES.
+ * ieee/ieee_arithmetic.F90: Make them public in IEEE_ARITHMETIC
+ as well.
+
+2022-09-19 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ * ieee/ieee_arithmetic.F90: Add RADIX argument to
+ IEEE_SET_ROUNDING_MODE and IEEE_GET_ROUNDING_MODE.
+ * config/fpu-387.h: Add IEEE_AWAY mode.
+ * config/fpu-aarch64.h: Add IEEE_AWAY mode.
+ * config/fpu-aix.h: Add IEEE_AWAY mode.
+ * config/fpu-generic.h: Add IEEE_AWAY mode.
+ * config/fpu-glibc.h: Add IEEE_AWAY mode.
+ * config/fpu-sysv.h: Add IEEE_AWAY mode.
+
2022-09-10 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR fortran/95644
diff --git a/libgfortran/config/fpu-387.h b/libgfortran/config/fpu-387.h
index fd00dab..e2f4a7d 100644
--- a/libgfortran/config/fpu-387.h
+++ b/libgfortran/config/fpu-387.h
@@ -418,9 +418,12 @@ get_fpu_rounding_mode (void)
}
int
-support_fpu_rounding_mode (int mode __attribute__((unused)))
+support_fpu_rounding_mode (int mode)
{
- return 1;
+ if (mode == GFC_FPE_AWAY)
+ return 0;
+ else
+ return 1;
}
void
diff --git a/libgfortran/config/fpu-aarch64.h b/libgfortran/config/fpu-aarch64.h
index 3a2e4ba..4789390 100644
--- a/libgfortran/config/fpu-aarch64.h
+++ b/libgfortran/config/fpu-aarch64.h
@@ -293,9 +293,12 @@ set_fpu_rounding_mode (int round)
int
-support_fpu_rounding_mode (int mode __attribute__((unused)))
+support_fpu_rounding_mode (int mode)
{
- return 1;
+ if (mode == GFC_FPE_AWAY)
+ return 0;
+ else
+ return 1;
}
diff --git a/libgfortran/config/fpu-aix.h b/libgfortran/config/fpu-aix.h
index c643874..fb1ac80 100644
--- a/libgfortran/config/fpu-aix.h
+++ b/libgfortran/config/fpu-aix.h
@@ -320,6 +320,11 @@ get_fpu_rounding_mode (void)
return GFC_FPE_TOWARDZERO;
#endif
+#ifdef FE_TONEARESTFROMZERO
+ case FE_TONEARESTFROMZERO:
+ return GFC_FPE_AWAY;
+#endif
+
default:
return 0; /* Should be unreachable. */
}
@@ -357,8 +362,14 @@ set_fpu_rounding_mode (int mode)
break;
#endif
+#ifdef FE_TONEARESTFROMZERO
+ case GFC_FPE_AWAY:
+ rnd_mode = FE_TONEARESTFROMZERO;
+ break;
+#endif
+
default:
- return; /* Should be unreachable. */
+ return;
}
fesetround (rnd_mode);
@@ -398,8 +409,15 @@ support_fpu_rounding_mode (int mode)
return 0;
#endif
+ case GFC_FPE_AWAY:
+#ifdef FE_TONEARESTFROMZERO
+ return 1;
+#else
+ return 0;
+#endif
+
default:
- return 0; /* Should be unreachable. */
+ return 0;
}
}
diff --git a/libgfortran/config/fpu-generic.h b/libgfortran/config/fpu-generic.h
index 3b62228..9e976a8 100644
--- a/libgfortran/config/fpu-generic.h
+++ b/libgfortran/config/fpu-generic.h
@@ -66,9 +66,16 @@ get_fpu_except_flags (void)
int
get_fpu_rounding_mode (void)
-{
+{
+ return 0;
+}
+
+
+int
+support_fpu_rounding_mode (int mode __attribute__((unused)))
+{
return 0;
-}
+}
void
diff --git a/libgfortran/config/fpu-glibc.h b/libgfortran/config/fpu-glibc.h
index 265ef69..f34b696 100644
--- a/libgfortran/config/fpu-glibc.h
+++ b/libgfortran/config/fpu-glibc.h
@@ -342,6 +342,11 @@ get_fpu_rounding_mode (void)
return GFC_FPE_TOWARDZERO;
#endif
+#ifdef FE_TONEARESTFROMZERO
+ case FE_TONEARESTFROMZERO:
+ return GFC_FPE_AWAY;
+#endif
+
default:
return 0; /* Should be unreachable. */
}
@@ -379,6 +384,12 @@ set_fpu_rounding_mode (int mode)
break;
#endif
+#ifdef FE_TONEARESTFROMZERO
+ case GFC_FPE_AWAY:
+ rnd_mode = FE_TONEARESTFROMZERO;
+ break;
+#endif
+
default:
return; /* Should be unreachable. */
}
@@ -420,6 +431,13 @@ support_fpu_rounding_mode (int mode)
return 0;
#endif
+ case GFC_FPE_AWAY:
+#ifdef FE_TONEARESTFROMZERO
+ return 1;
+#else
+ return 0;
+#endif
+
default:
return 0; /* Should be unreachable. */
}
diff --git a/libgfortran/config/fpu-sysv.h b/libgfortran/config/fpu-sysv.h
index 4de3852..4681322 100644
--- a/libgfortran/config/fpu-sysv.h
+++ b/libgfortran/config/fpu-sysv.h
@@ -374,9 +374,12 @@ set_fpu_rounding_mode (int mode)
int
-support_fpu_rounding_mode (int mode __attribute__((unused)))
+support_fpu_rounding_mode (int mode)
{
- return 1;
+ if (mode == GFC_FPE_AWAY)
+ return 0;
+ else
+ return 1;
}
diff --git a/libgfortran/ieee/ieee_arithmetic.F90 b/libgfortran/ieee/ieee_arithmetic.F90
index 4e01aa5..ce30e4a 100644
--- a/libgfortran/ieee/ieee_arithmetic.F90
+++ b/libgfortran/ieee/ieee_arithmetic.F90
@@ -39,7 +39,8 @@ module IEEE_ARITHMETIC
IEEE_DIVIDE_BY_ZERO, IEEE_UNDERFLOW, IEEE_INEXACT, IEEE_USUAL, &
IEEE_ALL, IEEE_STATUS_TYPE, IEEE_GET_FLAG, IEEE_GET_HALTING_MODE, &
IEEE_GET_STATUS, IEEE_SET_FLAG, IEEE_SET_HALTING_MODE, &
- IEEE_SET_STATUS, IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING
+ IEEE_SET_STATUS, IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING, &
+ IEEE_MODES_TYPE, IEEE_GET_MODES, IEEE_SET_MODES
! Derived types and named constants
@@ -73,6 +74,7 @@ module IEEE_ARITHMETIC
IEEE_TO_ZERO = IEEE_ROUND_TYPE(GFC_FPE_TOWARDZERO), &
IEEE_UP = IEEE_ROUND_TYPE(GFC_FPE_UPWARD), &
IEEE_DOWN = IEEE_ROUND_TYPE(GFC_FPE_DOWNWARD), &
+ IEEE_AWAY = IEEE_ROUND_TYPE(GFC_FPE_AWAY), &
IEEE_OTHER = IEEE_ROUND_TYPE(0)
@@ -1044,9 +1046,10 @@ contains
! IEEE_GET_ROUNDING_MODE
- subroutine IEEE_GET_ROUNDING_MODE (ROUND_VALUE)
+ subroutine IEEE_GET_ROUNDING_MODE (ROUND_VALUE, RADIX)
implicit none
type(IEEE_ROUND_TYPE), intent(out) :: ROUND_VALUE
+ integer, intent(in), optional :: RADIX
interface
integer function helper() &
@@ -1060,9 +1063,10 @@ contains
! IEEE_SET_ROUNDING_MODE
- subroutine IEEE_SET_ROUNDING_MODE (ROUND_VALUE)
+ subroutine IEEE_SET_ROUNDING_MODE (ROUND_VALUE, RADIX)
implicit none
type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE
+ integer, intent(in), optional :: RADIX
interface
subroutine helper(val) &
diff --git a/libgfortran/ieee/ieee_exceptions.F90 b/libgfortran/ieee/ieee_exceptions.F90
index 77363cf..3ed2f6e 100644
--- a/libgfortran/ieee/ieee_exceptions.F90
+++ b/libgfortran/ieee/ieee_exceptions.F90
@@ -56,6 +56,13 @@ module IEEE_EXCEPTIONS
character(len=GFC_FPE_STATE_BUFFER_SIZE) :: hidden
end type
+ type, public :: IEEE_MODES_TYPE
+ private
+ integer :: rounding
+ integer :: underflow
+ integer :: halting
+ end type
+
interface IEEE_SUPPORT_FLAG
module procedure IEEE_SUPPORT_FLAG_4, &
IEEE_SUPPORT_FLAG_8, &
@@ -72,9 +79,65 @@ module IEEE_EXCEPTIONS
public :: IEEE_SET_HALTING_MODE, IEEE_GET_HALTING_MODE
public :: IEEE_SET_FLAG, IEEE_GET_FLAG
public :: IEEE_SET_STATUS, IEEE_GET_STATUS
+ public :: IEEE_SET_MODES, IEEE_GET_MODES
contains
+! Fortran 2018: Saving and restoring floating-point modes
+! (rounding modes, underflow mode, and halting mode)
+!
+! For now, we only have one rounding mode for all kinds.
+! Some targets could optimize getting/setting all modes at once, but for now
+! we make three calls. This code must be kept in sync with:
+! - IEEE_{GET,SET}_ROUNDING_MODE
+! - IEEE_{GET,SET}_UNDERFLOW_MODE
+! - IEEE_{GET,SET}_HALTING_MODE
+
+ subroutine IEEE_GET_MODES (MODES)
+ implicit none
+ type(IEEE_MODES_TYPE), intent(out) :: MODES
+
+ interface
+ integer function helper_rounding() &
+ bind(c, name="_gfortrani_get_fpu_rounding_mode")
+ end function
+ integer function helper_underflow() &
+ bind(c, name="_gfortrani_get_fpu_underflow_mode")
+ end function
+ pure integer function helper_halting() &
+ bind(c, name="_gfortrani_get_fpu_trap_exceptions")
+ end function
+ end interface
+
+ MODES%rounding = helper_rounding()
+ MODES%underflow = helper_underflow()
+ MODES%halting = helper_halting()
+ end subroutine
+
+ subroutine IEEE_SET_MODES (MODES)
+ implicit none
+ type(IEEE_MODES_TYPE), intent(in) :: MODES
+
+ interface
+ subroutine helper_rounding(val) &
+ bind(c, name="_gfortrani_set_fpu_rounding_mode")
+ integer, value :: val
+ end subroutine
+ subroutine helper_underflow(val) &
+ bind(c, name="_gfortrani_set_fpu_underflow_mode")
+ integer, value :: val
+ end subroutine
+ pure subroutine helper_halting(trap, notrap) &
+ bind(c, name="_gfortrani_set_fpu_trap_exceptions")
+ integer, intent(in), value :: trap, notrap
+ end subroutine
+ end interface
+
+ call helper_rounding(MODES%rounding)
+ call helper_underflow(MODES%underflow)
+ call helper_halting(MODES%halting, NOT(MODES%halting))
+ end subroutine
+
! Saving and restoring floating-point status
subroutine IEEE_GET_STATUS (STATUS_VALUE)