aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2001-04-26 08:34:06 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2001-04-26 08:34:06 +0000
commit0576ec13087498afc8beda9cda8da33f07ecdbeb (patch)
tree57ec9557a296544a9c561271ab13d8230ec7a18b /gcc
parentcc6e9bc399d78744000d23307cbf09d3bf35ffff (diff)
downloadgcc-0576ec13087498afc8beda9cda8da33f07ecdbeb.zip
gcc-0576ec13087498afc8beda9cda8da33f07ecdbeb.tar.gz
gcc-0576ec13087498afc8beda9cda8da33f07ecdbeb.tar.bz2
mangle.c (write_chars): New macro.
cp: * mangle.c (write_chars): New macro. (hwint_to_ascii): New function (write_number): Use it. (write_integer_cst): Deal with really big numbers. testsuite: * g++.old-deja/g++.pt/mangle2.C: New test. From-SVN: r41584
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/mangle.c136
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/mangle2.C40
4 files changed, 158 insertions, 29 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 40d6d96..d6c2f48 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2001-04-26 Nathan Sidwell <nathan@codesourcery.com>
+
+ * mangle.c (write_chars): New macro.
+ (hwint_to_ascii): New function
+ (write_number): Use it.
+ (write_integer_cst): Deal with really big numbers.
+
2001-04-25 Mark Mitchell <mark@codesourcery.com>
* optimize.c (maybe_clone_body): Copy TREE_PUBLIC before emitting
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 7b6857d..e193f00 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -153,6 +153,7 @@ static void write_prefix PARAMS ((tree));
static void write_template_prefix PARAMS ((tree));
static void write_unqualified_name PARAMS ((tree));
static void write_source_name PARAMS ((tree));
+static int hwint_to_ascii PARAMS ((unsigned HOST_WIDE_INT, unsigned int, char *, unsigned));
static void write_number PARAMS ((unsigned HOST_WIDE_INT, int,
unsigned int));
static void write_integer_cst PARAMS ((tree));
@@ -198,6 +199,10 @@ static void write_java_integer_type_codes PARAMS ((tree));
#define write_char(CHAR) \
obstack_1grow (&G.name_obstack, (CHAR))
+/* Append a sized buffer to the end of the mangled representation. */
+#define write_chars(CHAR, LEN) \
+ obstack_grow (&G.name_obstack, (CHAR), (LEN))
+
/* Append a NUL-terminated string to the end of the mangled
representation. */
#define write_string(STRING) \
@@ -1013,6 +1018,38 @@ write_source_name (identifier)
write_identifier (IDENTIFIER_POINTER (identifier));
}
+/* Convert NUMBER to ascii using base BASE and generating at least
+ MIN_DIGITS characters. BUFFER points to the _end_ of the buffer
+ into which to store the characters. Returns the number of
+ characters generated (these will be layed out in advance of where
+ BUFFER points). */
+
+static int
+hwint_to_ascii (number, base, buffer, min_digits)
+ unsigned HOST_WIDE_INT number;
+ unsigned int base;
+ char *buffer;
+ unsigned min_digits;
+{
+ static const char base_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ unsigned digits = 0;
+
+ while (number)
+ {
+ unsigned HOST_WIDE_INT d = number / base;
+
+ *--buffer = base_digits[number - d * base];
+ digits++;
+ number = d;
+ }
+ while (digits < min_digits)
+ {
+ *--buffer = base_digits[0];
+ digits++;
+ }
+ return digits;
+}
+
/* Non-terminal <number>.
<number> ::= [n] </decimal integer/> */
@@ -1023,50 +1060,91 @@ write_number (number, unsigned_p, base)
int unsigned_p;
unsigned int base;
{
- static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- unsigned HOST_WIDE_INT n;
- unsigned HOST_WIDE_INT m = 1;
+ char buffer[sizeof (HOST_WIDE_INT) * 8];
+ unsigned count = 0;
if (!unsigned_p && (HOST_WIDE_INT) number < 0)
{
write_char ('n');
number = -((HOST_WIDE_INT) number);
}
-
- /* Figure out how many digits there are. */
- n = number;
- while (n >= base)
- {
- n /= base;
- m *= base;
- }
-
- /* Write them out. */
- while (m > 0)
- {
- int digit = number / m;
- write_char (digits[digit]);
- number -= digit * m;
- m /= base;
- }
-
- my_friendly_assert (number == 0, 20000407);
+ count = hwint_to_ascii (number, base, buffer + sizeof (buffer), 1);
+ write_chars (buffer + sizeof (buffer) - count, count);
}
-/* Write out an integeral CST in decimal. */
+/* Write out an integral CST in decimal. Most numbers are small, and
+ representable in a HOST_WIDE_INT. Occasionally we'll have numbers
+ bigger than that, which we must deal with. */
static inline void
write_integer_cst (cst)
tree cst;
{
- if (tree_int_cst_sgn (cst) >= 0)
+ int sign = tree_int_cst_sgn (cst);
+
+ if (TREE_INT_CST_HIGH (cst) + (sign < 0))
{
- if (TREE_INT_CST_HIGH (cst) != 0)
- sorry ("mangling very large integers");
- write_unsigned_number (TREE_INT_CST_LOW (cst));
+ /* A bignum. We do this in chunks, each of which fits in a
+ HOST_WIDE_INT. */
+ char buffer[sizeof (HOST_WIDE_INT) * 8 * 2];
+ unsigned HOST_WIDE_INT chunk;
+ unsigned chunk_digits;
+ char *ptr = buffer + sizeof (buffer);
+ unsigned count = 0;
+ tree n, base, type;
+ int done;
+
+ /* HOST_WIDE_INT must be at least 32 bits, so 10^9 is
+ representable. */
+ chunk = 1000000000;
+ chunk_digits = 9;
+
+ if (sizeof (HOST_WIDE_INT) >= 8)
+ {
+ /* It is at least 64 bits, so 10^18 is representable. */
+ chunk_digits = 18;
+ chunk *= chunk;
+ }
+
+ type = signed_or_unsigned_type (1, TREE_TYPE (cst));
+ base = build_int_2 (chunk, 0);
+ n = build_int_2 (TREE_INT_CST_LOW (cst), TREE_INT_CST_HIGH (cst));
+ TREE_TYPE (n) = TREE_TYPE (base) = type;
+
+ if (sign < 0)
+ {
+ write_char ('n');
+ n = fold (build1 (NEGATE_EXPR, type, n));
+ }
+ do
+ {
+ tree d = fold (build (FLOOR_DIV_EXPR, type, n, base));
+ tree tmp = fold (build (MULT_EXPR, type, d, base));
+ unsigned c;
+
+ done = integer_zerop (d);
+ tmp = fold (build (MINUS_EXPR, type, n, tmp));
+ c = hwint_to_ascii (TREE_INT_CST_LOW (tmp), 10, ptr,
+ done ? 1 : chunk_digits);
+ ptr -= c;
+ count += c;
+ n = d;
+ }
+ while (!done);
+ write_chars (ptr, count);
+ }
+ else
+ {
+ /* A small num. */
+ unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
+
+ if (sign < 0)
+ {
+ write_char ('n');
+ low = -low;
+ }
+ write_unsigned_number (low);
}
- else
- write_signed_number (tree_low_cst (cst, 0));
}
/* Non-terminal <identifier>.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 14f70fd..8025228 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2001-04-26 Nathan Sidwell <nathan@codesourcery.com>
+
+ * g++.old-deja/g++.pt/mangle2.C: New test.
+
2001-04-25 Jakub Jelinek <jakub@redhat.com>
* c-format.c (check_format_info_recurse): Handle
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/mangle2.C b/gcc/testsuite/g++.old-deja/g++.pt/mangle2.C
new file mode 100644
index 0000000..a7b95b1
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/mangle2.C
@@ -0,0 +1,40 @@
+// Build don't link:
+//
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 25 April 2001 <nathan@codesourcery.com>
+// Origin:pcarlini@unitus.it
+
+// Bug 2559. We hadn't implemented code to mangle numbers bigger than
+// HOST_WIDE_INT.
+
+template<class T, T min_val, T max_val>
+class integer_traits_base
+{
+public:
+static const bool is_integral = true;
+};
+
+template<class T>
+class integer_traits
+{
+public:
+static const bool is_integral = false;
+};
+
+template<>
+class integer_traits<long long>
+: public integer_traits_base<long long, (-9223372036854775807LL - 1),
+9223372036854775807LL>
+{ };
+
+integer_traits<long long> f;
+
+template <class T, T value> T foo ()
+{
+ return value;
+}
+
+void x ()
+{
+ foo<long long, -9223372036854775807LL> ();
+}