Skip to content

Commit 2a9c380

Browse files
rossburtonbenjaminp
authored andcommitted
closes bpo-34585: Don't do runtime test to get float byte order. (GH-9085)
Currently configure.ac uses AC_RUN_IFELSE to determine the byte order of doubles, but this silently fails under cross compilation and Python doesn't do floats properly. Instead, steal a macro from autoconf-archive which compiles code using magic doubles (which encode to ASCII) and grep for the representation in the binary. RFC because this doesn't yet handle the weird ancient ARMv4 OABI 'mixed-endian' encoding properly. This encoding is ancient and I don't believe the union of "Python 3.8 users" and "OABI users" has anything in. Should the support for this just be dropped too? Alternatively, someone will need to find an OABI toolchain to verify the encoding of the magic double.
1 parent 4715039 commit 2a9c380

File tree

3 files changed

+99
-63
lines changed

3 files changed

+99
-63
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Check for floating-point byte order in configure.ac using compilation tests
2+
instead of executing code, so that these checks work in cross-compiled
3+
builds.

configure.ac

Lines changed: 13 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4206,74 +4206,24 @@ fi
42064206
# * Check for various properties of floating point *
42074207
# **************************************************
42084208

4209-
AC_MSG_CHECKING(whether C doubles are little-endian IEEE 754 binary64)
4210-
AC_CACHE_VAL(ac_cv_little_endian_double, [
4211-
AC_RUN_IFELSE([AC_LANG_SOURCE([[
4212-
#include <string.h>
4213-
int main() {
4214-
double x = 9006104071832581.0;
4215-
if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0)
4216-
return 0;
4217-
else
4218-
return 1;
4219-
}
4220-
]])],
4221-
[ac_cv_little_endian_double=yes],
4222-
[ac_cv_little_endian_double=no],
4223-
[ac_cv_little_endian_double=no])])
4224-
AC_MSG_RESULT($ac_cv_little_endian_double)
4225-
if test "$ac_cv_little_endian_double" = yes
4226-
then
4227-
AC_DEFINE(DOUBLE_IS_LITTLE_ENDIAN_IEEE754, 1,
4228-
[Define if C doubles are 64-bit IEEE 754 binary format, stored
4229-
with the least significant byte first])
4230-
fi
4231-
4232-
AC_MSG_CHECKING(whether C doubles are big-endian IEEE 754 binary64)
4233-
AC_CACHE_VAL(ac_cv_big_endian_double, [
4234-
AC_RUN_IFELSE([AC_LANG_SOURCE([[
4235-
#include <string.h>
4236-
int main() {
4237-
double x = 9006104071832581.0;
4238-
if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0)
4239-
return 0;
4240-
else
4241-
return 1;
4242-
}
4243-
]])],
4244-
[ac_cv_big_endian_double=yes],
4245-
[ac_cv_big_endian_double=no],
4246-
[ac_cv_big_endian_double=no])])
4247-
AC_MSG_RESULT($ac_cv_big_endian_double)
4248-
if test "$ac_cv_big_endian_double" = yes
4209+
AX_C_FLOAT_WORDS_BIGENDIAN
4210+
if test "$ax_cv_c_float_words_bigendian" = "yes"
42494211
then
42504212
AC_DEFINE(DOUBLE_IS_BIG_ENDIAN_IEEE754, 1,
42514213
[Define if C doubles are 64-bit IEEE 754 binary format, stored
42524214
with the most significant byte first])
4253-
fi
4254-
4255-
# Some ARM platforms use a mixed-endian representation for doubles.
4256-
# While Python doesn't currently have full support for these platforms
4257-
# (see e.g., issue 1762561), we can at least make sure that float <-> string
4258-
# conversions work.
4259-
AC_MSG_CHECKING(whether C doubles are ARM mixed-endian IEEE 754 binary64)
4260-
AC_CACHE_VAL(ac_cv_mixed_endian_double, [
4261-
AC_RUN_IFELSE([AC_LANG_SOURCE([[
4262-
#include <string.h>
4263-
int main() {
4264-
double x = 9006104071832581.0;
4265-
if (memcmp(&x, "\x01\xff\x3f\x43\x05\x04\x03\x02", 8) == 0)
4266-
return 0;
4267-
else
4268-
return 1;
4269-
}
4270-
]])],
4271-
[ac_cv_mixed_endian_double=yes],
4272-
[ac_cv_mixed_endian_double=no],
4273-
[ac_cv_mixed_endian_double=no])])
4274-
AC_MSG_RESULT($ac_cv_mixed_endian_double)
4275-
if test "$ac_cv_mixed_endian_double" = yes
4215+
elif test "$ax_cv_c_float_words_bigendian" = "no"
42764216
then
4217+
AC_DEFINE(DOUBLE_IS_LITTLE_ENDIAN_IEEE754, 1,
4218+
[Define if C doubles are 64-bit IEEE 754 binary format, stored
4219+
with the least significant byte first])
4220+
else
4221+
# Some ARM platforms use a mixed-endian representation for doubles.
4222+
# While Python doesn't currently have full support for these platforms
4223+
# (see e.g., issue 1762561), we can at least make sure that float <-> string
4224+
# conversions work.
4225+
# FLOAT_WORDS_BIGENDIAN doesnt actually detect this case, but if it's not big
4226+
# or little, then it must be this?
42774227
AC_DEFINE(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754, 1,
42784228
[Define if C doubles are 64-bit IEEE 754 binary format, stored
42794229
in ARM mixed-endian order (byte order 45670123)])

m4/ax_c_float_words_bigendian.m4

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# ===============================================================================
2+
# https://www.gnu.org/software/autoconf-archive/ax_c_float_words_bigendian.html
3+
# ===============================================================================
4+
#
5+
# SYNOPSIS
6+
#
7+
# AX_C_FLOAT_WORDS_BIGENDIAN([ACTION-IF-TRUE], [ACTION-IF-FALSE], [ACTION-IF-UNKNOWN])
8+
#
9+
# DESCRIPTION
10+
#
11+
# Checks the ordering of words within a multi-word float. This check is
12+
# necessary because on some systems (e.g. certain ARM systems), the float
13+
# word ordering can be different from the byte ordering. In a multi-word
14+
# float context, "big-endian" implies that the word containing the sign
15+
# bit is found in the memory location with the lowest address. This
16+
# implementation was inspired by the AC_C_BIGENDIAN macro in autoconf.
17+
#
18+
# The endianness is detected by first compiling C code that contains a
19+
# special double float value, then grepping the resulting object file for
20+
# certain strings of ASCII values. The double is specially crafted to have
21+
# a binary representation that corresponds with a simple string. In this
22+
# implementation, the string "noonsees" was selected because the
23+
# individual word values ("noon" and "sees") are palindromes, thus making
24+
# this test byte-order agnostic. If grep finds the string "noonsees" in
25+
# the object file, the target platform stores float words in big-endian
26+
# order. If grep finds "seesnoon", float words are in little-endian order.
27+
# If neither value is found, the user is instructed to specify the
28+
# ordering.
29+
#
30+
# LICENSE
31+
#
32+
# Copyright (c) 2008 Daniel Amelang <[email protected]>
33+
#
34+
# Copying and distribution of this file, with or without modification, are
35+
# permitted in any medium without royalty provided the copyright notice
36+
# and this notice are preserved. This file is offered as-is, without any
37+
# warranty.
38+
39+
#serial 11
40+
41+
AC_DEFUN([AX_C_FLOAT_WORDS_BIGENDIAN],
42+
[AC_CACHE_CHECK(whether float word ordering is bigendian,
43+
ax_cv_c_float_words_bigendian, [
44+
45+
ax_cv_c_float_words_bigendian=unknown
46+
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
47+
48+
double d = 90904234967036810337470478905505011476211692735615632014797120844053488865816695273723469097858056257517020191247487429516932130503560650002327564517570778480236724525140520121371739201496540132640109977779420565776568942592.0;
49+
50+
]])], [
51+
52+
if grep noonsees conftest.$ac_objext >/dev/null ; then
53+
ax_cv_c_float_words_bigendian=yes
54+
fi
55+
if grep seesnoon conftest.$ac_objext >/dev/null ; then
56+
if test "$ax_cv_c_float_words_bigendian" = unknown; then
57+
ax_cv_c_float_words_bigendian=no
58+
else
59+
ax_cv_c_float_words_bigendian=unknown
60+
fi
61+
fi
62+
63+
])])
64+
65+
case $ax_cv_c_float_words_bigendian in
66+
yes)
67+
m4_default([$1],
68+
[AC_DEFINE([FLOAT_WORDS_BIGENDIAN], 1,
69+
[Define to 1 if your system stores words within floats
70+
with the most significant word first])]) ;;
71+
no)
72+
$2 ;;
73+
*)
74+
m4_default([$3],
75+
[AC_MSG_ERROR([
76+
77+
Unknown float word ordering. You need to manually preset
78+
ax_cv_c_float_words_bigendian=no (or yes) according to your system.
79+
80+
])]) ;;
81+
esac
82+
83+
])# AX_C_FLOAT_WORDS_BIGENDIAN

0 commit comments

Comments
 (0)