# reproducible: to get the same tools versions (autoconf, aclocal, ...)
runs-on: ubuntu-24.04
container:
- image: ghcr.io/python/autoconf:2024.10.11.11293396815
+ image: ghcr.io/python/autoconf:2024.10.16.11360930377
timeout-minutes: 60
needs: check_source
if: needs.check_source.outputs.run_tests == 'true'
--- /dev/null
+Improve detection of float word ordering on Linux when link-time optimizations
+are enabled.
--- /dev/null
+Hard-code float word ordering as little endian on WASM.
# The check_generated_files job of .github/workflows/build.yml must kept in
# sync with this script. Use the same container image than the job so the job
# doesn't need to run autoreconf in a container.
-IMAGE="ghcr.io/python/autoconf:2024.10.06.11200919239"
+IMAGE="ghcr.io/python/autoconf:2024.10.16.11360930377"
AUTORECONF="autoreconf -ivf -Werror"
WORK_DIR="/src"
# If neither value is found, the user is instructed to specify the
# ordering.
#
+# Early versions of this macro (i.e., before serial 12) would not work
+# when interprocedural optimization (via link-time optimization) was
+# enabled. This would happen when, say, the GCC/clang "-flto" flag, or the
+# ICC "-ipo" flag was used, for example. The problem was that under
+# these conditions, the compiler did not allocate for and write the special
+# float value in the data segment of the object file, since doing so might
+# not prove optimal once more context was available. Thus, the special value
+# (in platform-dependent binary form) could not be found in the object file,
+# and the macro would fail.
+#
+# The solution to the above problem was to:
+#
+# 1) Compile and link a whole test program rather than just compile an
+# object file. This ensures that we reach the point where even an
+# interprocedural optimizing compiler writes values to the data segment.
+#
+# 2) Add code that requires the compiler to write the special value to
+# the data segment, as opposed to "optimizing away" the variable's
+# allocation. This could be done via compiler keywords or options, but
+# it's tricky to make this work for all versions of all compilers with
+# all optimization settings. The chosen solution was to make the exit
+# code of the test program depend on the storing of the special value
+# in memory (in the data segment). Because the exit code can be
+# verified, any compiler that aspires to be correct will produce a
+# program binary that contains the value, which the macro can then find.
+#
+# How does the exit code depend on the special value residing in memory?
+# Memory, unlike variables and registers, can be addressed indirectly at run
+# time. The exit code of this test program is a result of indirectly reading
+# and writing to the memory region where the special value is supposed to
+# reside. The actual memory addresses used and the values to be written are
+# derived from the the program input ("argv") and are therefore not known at
+# compile or link time. The compiler has no choice but to defer the
+# computation to run time, and to prepare by allocating and populating the
+# data segment with the special value. For further details, refer to the
+# source code of the test program.
+#
+# Note that the test program is never meant to be run. It only exists to host
+# a double float value in a given platform's binary format. Thus, error
+# handling is not included.
+#
# LICENSE
#
-# Copyright (c) 2008 Daniel Amelang <dan@amelang.net>
+# Copyright (c) 2008, 2023 Daniel Amelang <dan@amelang.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 11
+#serial 12
AC_DEFUN([AX_C_FLOAT_WORDS_BIGENDIAN],
[AC_CACHE_CHECK(whether float word ordering is bigendian,
ax_cv_c_float_words_bigendian, [
ax_cv_c_float_words_bigendian=unknown
-AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+AC_LINK_IFELSE([AC_LANG_SOURCE([[
+
+#include <stdlib.h>
+
+static double m[] = {9.090423496703681e+223, 0.0};
-double d = 90904234967036810337470478905505011476211692735615632014797120844053488865816695273723469097858056257517020191247487429516932130503560650002327564517570778480236724525140520121371739201496540132640109977779420565776568942592.0;
+int main (int argc, char *argv[])
+{
+ m[atoi (argv[1])] += atof (argv[2]);
+ return m[atoi (argv[3])] > 0.0;
+}
]])], [
-if grep noonsees conftest.$ac_objext >/dev/null ; then
+if grep noonsees conftest$EXEEXT >/dev/null ; then
ax_cv_c_float_words_bigendian=yes
fi
-if grep seesnoon conftest.$ac_objext >/dev/null ; then
+if grep seesnoon conftest$EXEEXT >/dev/null ; then
if test "$ax_cv_c_float_words_bigendian" = unknown; then
ax_cv_c_float_words_bigendian=no
else
/* end confdefs.h. */
-double d = 90904234967036810337470478905505011476211692735615632014797120844053488865816695273723469097858056257517020191247487429516932130503560650002327564517570778480236724525140520121371739201496540132640109977779420565776568942592.0;
+#include <stdlib.h>
+
+static double m[] = {9.090423496703681e+223, 0.0};
+
+int main (int argc, char *argv[])
+{
+ m[atoi (argv[1])] += atof (argv[2]);
+ return m[atoi (argv[3])] > 0.0;
+}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"
+if ac_fn_c_try_link "$LINENO"
then :
-if grep noonsees conftest.$ac_objext >/dev/null ; then
+if grep noonsees conftest$EXEEXT >/dev/null ; then
ax_cv_c_float_words_bigendian=yes
fi
-if grep seesnoon conftest.$ac_objext >/dev/null ; then
+if grep seesnoon conftest$EXEEXT >/dev/null ; then
if test "$ax_cv_c_float_words_bigendian" = unknown; then
ax_cv_c_float_words_bigendian=no
else
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_c_float_words_bigendian" >&5
printf "%s\n" "$ax_cv_c_float_words_bigendian" >&6; }
case $ax_cv_c_float_words_bigendian in
yes)
-printf "%s\n" "#define FLOAT_WORDS_BIGENDIAN 1" >>confdefs.h
+printf "%s\n" "#define DOUBLE_IS_BIG_ENDIAN_IEEE754 1" >>confdefs.h
;;
no)
- ;;
- *)
- as_fn_error $? "
-
-Unknown float word ordering. You need to manually preset
-ax_cv_c_float_words_bigendian=no (or yes) according to your system.
-
- " "$LINENO" 5 ;;
-esac
-
-if test "$ax_cv_c_float_words_bigendian" = "yes"
-then
-
-printf "%s\n" "#define DOUBLE_IS_BIG_ENDIAN_IEEE754 1" >>confdefs.h
+printf "%s\n" "#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 1" >>confdefs.h
+ ;;
+ *)
+ case $host_cpu in #(
+ *arm*) :
+ # Some ARM platforms use a mixed-endian representation for
+ # doubles. While Python doesn't currently have full support
+ # for these platforms (see e.g., issue 1762561), we can at
+ # least make sure that float <-> string conversions work.
+ # FLOAT_WORDS_BIGENDIAN doesn't actually detect this case,
+ # but if it's not big or little, then it must be this?
-elif test "$ax_cv_c_float_words_bigendian" = "no"
-then
+printf "%s\n" "#define DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 1" >>confdefs.h
+ ;; #(
+ wasm*) :
printf "%s\n" "#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 1" >>confdefs.h
+ ;; #(
+ *) :
+ ;;
+esac ;;
+esac
-else
- # Some ARM platforms use a mixed-endian representation for doubles.
- # While Python doesn't currently have full support for these platforms
- # (see e.g., issue 1762561), we can at least make sure that float <-> string
- # conversions work.
- # FLOAT_WORDS_BIGENDIAN doesn't actually detect this case, but if it's not big
- # or little, then it must be this?
-
-printf "%s\n" "#define DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 1" >>confdefs.h
-fi
# The short float repr introduced in Python 3.1 requires the
# correctly-rounded string <-> double conversion functions from
# * Check for various properties of floating point *
# **************************************************
-AX_C_FLOAT_WORDS_BIGENDIAN
-if test "$ax_cv_c_float_words_bigendian" = "yes"
-then
- AC_DEFINE([DOUBLE_IS_BIG_ENDIAN_IEEE754], [1],
- [Define if C doubles are 64-bit IEEE 754 binary format, stored
- with the most significant byte first])
-elif test "$ax_cv_c_float_words_bigendian" = "no"
-then
- AC_DEFINE([DOUBLE_IS_LITTLE_ENDIAN_IEEE754], [1],
- [Define if C doubles are 64-bit IEEE 754 binary format, stored
- with the least significant byte first])
-else
- # Some ARM platforms use a mixed-endian representation for doubles.
- # While Python doesn't currently have full support for these platforms
- # (see e.g., issue 1762561), we can at least make sure that float <-> string
- # conversions work.
- # FLOAT_WORDS_BIGENDIAN doesn't actually detect this case, but if it's not big
- # or little, then it must be this?
- AC_DEFINE([DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754], [1],
- [Define if C doubles are 64-bit IEEE 754 binary format, stored
- in ARM mixed-endian order (byte order 45670123)])
-fi
+AX_C_FLOAT_WORDS_BIGENDIAN(
+ [AC_DEFINE([DOUBLE_IS_BIG_ENDIAN_IEEE754], [1],
+ [Define if C doubles are 64-bit IEEE 754 binary format,
+ stored with the most significant byte first])],
+ [AC_DEFINE([DOUBLE_IS_LITTLE_ENDIAN_IEEE754], [1],
+ [Define if C doubles are 64-bit IEEE 754 binary format,
+ stored with the least significant byte first])],
+ [AS_CASE([$host_cpu],
+ [*arm*], [# Some ARM platforms use a mixed-endian representation for
+ # doubles. While Python doesn't currently have full support
+ # for these platforms (see e.g., issue 1762561), we can at
+ # least make sure that float <-> string conversions work.
+ # FLOAT_WORDS_BIGENDIAN doesn't actually detect this case,
+ # but if it's not big or little, then it must be this?
+ AC_DEFINE([DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754], [1],
+ [Define if C doubles are 64-bit IEEE 754 binary format,
+ stored in ARM mixed-endian order (byte order 45670123)])],
+ [wasm*], [AC_DEFINE([DOUBLE_IS_LITTLE_ENDIAN_IEEE754], [1],
+ [Define if C doubles are 64-bit IEEE 754 binary format,
+ stored with the least significant byte first])])])
# The short float repr introduced in Python 3.1 requires the
# correctly-rounded string <-> double conversion functions from
/* Define if --enable-ipv6 is specified */
#undef ENABLE_IPV6
-/* Define to 1 if your system stores words within floats with the most
- significant word first */
-#undef FLOAT_WORDS_BIGENDIAN
-
/* Define if getpgrp() must be called as getpgrp(0). */
#undef GETPGRP_HAVE_ARG