This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/8861] [3.3/3.4 regression] [ABI] mangling floating point literal in template arg expression
- From: "zack at codesourcery dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 9 Jun 2003 18:25:41 -0000
- Subject: [Bug c++/8861] [3.3/3.4 regression] [ABI] mangling floating point literal in template arg expression
- References: <20021207125600.8861.catherin@ca.ibm.com>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8861
------- Additional Comments From zack@codesourcery.com 2003-06-09 18:25 -------
Subject: Revised patch - floating point literal mangling
After some discussion on the C++ ABI mailing list, the consensus seems
to be that leading zeroes should *not* be stripped. Also I've
implemented compatibility with 3.3 under -fabi-version=1, and an -Wabi
warning.
Bootstrapped i686-linux. OK mainline?
The patch applies unmodified to the 3.3 branch. I don't see any harm
in providing forward-compatibility with -fabi-version>=2 on the
branch, but if Mark would prefer I can instead simply add the warning.
zw
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.
===================================================================
Index: mangle.c
--- mangle.c 3 Apr 2003 03:45:48 -0000 1.68
+++ mangle.c 9 Jun 2003 18:22:47 -0000
@@ -175,6 +175,7 @@ static int hwint_to_ascii PARAMS ((unsig
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 <identifier>.
<identifier> ::= </unqualified source code identifier> */
@@ -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 ();