From 94d3ea58ff99483cba839ec978f65da745b209d0 Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Mon, 9 Jun 2003 18:47:40 +0000 Subject: [PATCH] re PR c++/8861 ([ABI] mangling floating point literal in template arg expression) PR 8861 * mangle.c (write_real_cst): New function. Implement ABI-compliant mangling of floating-point literals when -fabi-version>=2; provide backward compatibility with 3.3 when -fabi-version=1 (with warning). Clarify commentary. (write_template_arg_literal): Use write_real_cst. From-SVN: r67670 --- gcc/cp/ChangeLog | 15 ++++++-- gcc/cp/mangle.c | 92 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 81 insertions(+), 26 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ad74fd570c5f..417fb863ce45 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2003-06-09 Zack Weinberg + + PR 8861 + * mangle.c (write_real_cst): New function. Implement + ABI-compliant mangling of floating-point literals when + -fabi-version>=2; provide backward compatibility with 3.3 when + -fabi-version=1 (with warning). Clarify commentary. + (write_template_arg_literal): Use write_real_cst. + 2003-06-07 Andreas Jaeger * cp/decl.c (xref_tag): Remove undefined macro NONNESTED_CLASSES. @@ -23,11 +32,11 @@ Thu Jun 5 18:33:40 CEST 2003 Jan Hubicka 2003-06-03 Jason Merrill - * cp/cp-tree.h (CP_AGGREGATE_TYPE_P): Accept vectors. + * cp/cp-tree.h (CP_AGGREGATE_TYPE_P): Accept vectors. - * cp/decl.c (reshape_init): Handle vectors. + * cp/decl.c (reshape_init): Handle vectors. - * testsuite/g++.dg/init/array10.C: New. + * testsuite/g++.dg/init/array10.C: New. 2003-06-03 Kriang Lerdsuwanakij diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index a105db18bb8d..343cca556c25 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -175,6 +175,7 @@ static int hwint_to_ascii PARAMS ((unsigned HOST_WIDE_INT, unsigned int, char *, static void write_number PARAMS ((unsigned HOST_WIDE_INT, int, unsigned int)); static void write_integer_cst PARAMS ((tree)); +static void write_real_cst PARAMS ((tree)); static void write_identifier PARAMS ((const char *)); static void write_special_name_constructor PARAMS ((tree)); static void write_special_name_destructor PARAMS ((tree)); @@ -1192,6 +1193,72 @@ write_integer_cst (cst) } } +/* Write out a floating-point literal. + + "Floating-point literals are encoded using the bit pattern of the + target processor's internal representation of that number, as a + fixed-length lowercase hexadecimal string, high-order bytes first + (even if the target processor would store low-order bytes first). + The "n" prefix is not used for floating-point literals; the sign + bit is encoded with the rest of the number. + + Here are some examples, assuming the IEEE standard representation + for floating point numbers. (Spaces are for readability, not + part of the encoding.) + + 1.0f Lf 3f80 0000 E + -1.0f Lf bf80 0000 E + 1.17549435e-38f Lf 0080 0000 E + 1.40129846e-45f Lf 0000 0001 E + 0.0f Lf 0000 0000 E" + + Caller is responsible for the Lx and the E. */ +static void +write_real_cst (value) + tree value; +{ + if (abi_version_at_least (2)) + { + long target_real[4]; /* largest supported float */ + char buffer[9]; /* eight hex digits in a 32-bit number */ + int i, limit, dir; + + tree type = TREE_TYPE (value); + int words = GET_MODE_BITSIZE (TYPE_MODE (type)) / 32; + + real_to_target (target_real, &TREE_REAL_CST (value), + TYPE_MODE (type)); + + /* The value in target_real is in the target word order, + so we must write it out backward if that happens to be + little-endian. write_number cannot be used, it will + produce uppercase. */ + if (FLOAT_WORDS_BIG_ENDIAN) + i = 0, limit = words, dir = 1; + else + i = words - 1, limit = -1, dir = -1; + + for (; i != limit; i += dir) + { + sprintf (buffer, "%08lx", target_real[i]); + write_chars (buffer, 8); + } + } + else + { + /* In G++ 3.3 and before the REAL_VALUE_TYPE was written out + literally. Note that compatibility with 3.2 is impossible, + because the old floating-point emulator used a different + format for REAL_VALUE_TYPE. */ + size_t i; + for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i) + write_number (((unsigned char *) &TREE_REAL_CST (value))[i], + /*unsigned_p*/ 1, + /*base*/ 16); + G.need_abi_warning = 1; + } +} + /* Non-terminal . ::= */ @@ -2024,11 +2091,7 @@ write_expression (expr) "Literal arguments, e.g. "A<42L>", are encoded with their type and value. Negative integer values are preceded with "n"; for example, "A<-42L>" becomes "1AILln42EE". The bool value false is - encoded as 0, true as 1. If floating-point arguments are accepted - as an extension, their values should be encoded using a - fixed-length lowercase hexadecimal string corresponding to the - internal representation (IEEE on IA-64), high-order bytes first, - without leading zeroes. For example: "Lfbff000000E" is -1.0f." */ + encoded as 0, true as 1." */ static void write_template_arg_literal (value) @@ -2055,24 +2118,7 @@ write_template_arg_literal (value) write_integer_cst (value); } else if (TREE_CODE (value) == REAL_CST) - { -#ifdef CROSS_COMPILE - static int explained; - - if (!explained) - { - sorry ("real-valued template parameters when cross-compiling"); - explained = 1; - } -#else - size_t i; - for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i) - write_number (((unsigned char *) - &TREE_REAL_CST (value))[i], - /*unsigned_p=*/1, - 16); -#endif - } + write_real_cst (value); else abort ();