diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2001-04-26 08:34:06 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2001-04-26 08:34:06 +0000 |
commit | 0576ec13087498afc8beda9cda8da33f07ecdbeb (patch) | |
tree | 57ec9557a296544a9c561271ab13d8230ec7a18b /gcc | |
parent | cc6e9bc399d78744000d23307cbf09d3bf35ffff (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 136 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/mangle2.C | 40 |
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> (); +} |