diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 304c910b2d0..2cd7a0e94fe 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -b5ab7b419d6328f5126ba8d6795280129eaf6e79 +54aacecc8167bfba8420cb7b245787ff80bde61b The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 52606261833..f6c104cef8a 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -12,6 +12,7 @@ #include "gogo.h" #include "go-diagnostics.h" #include "go-encode-id.h" +#include "go-sha1.h" #include "operator.h" #include "expressions.h" #include "statements.h" @@ -2776,22 +2777,43 @@ Ptrmask::set_from(Gogo* gogo, Type* type, int64_t ptrsize, int64_t offset) } } -// Return a symbol name for this ptrmask. This is used to coalesce -// identical ptrmasks, which are common. The symbol name must use -// only characters that are valid in symbols. It's nice if it's -// short. We convert it to a string that uses only 32 characters, -// avoiding digits and u and U. - +// Return a symbol name for this ptrmask. This is used to coalesce identical +// ptrmasks, which are common. The symbol name must use only characters that are +// valid in symbols. It's nice if it's short. For smaller ptrmasks, we convert +// it to a string that uses only 32 characters, avoiding digits and u and U. For +// longer pointer masks, apply the same process to the SHA1 digest of the bits, +// so as to avoid pathologically long symbol names (see related Go issues #32083 +// and #11583 for more on this). To avoid collisions between the two encoding +// schemes, use a prefix ("X") for the SHA form to disambiguate. std::string Ptrmask::symname() const { + const std::vector* bits(&this->bits_); + std::vector shabits; + std::string prefix; + + if (this->bits_.size() > 128) + { + // Produce a SHA1 digest of the data. + Go_sha1_helper* sha1_helper = go_create_sha1_helper(); + sha1_helper->process_bytes(&this->bits_[0], this->bits_.size()); + std::string digest = sha1_helper->finish(); + delete sha1_helper; + + // Redirect the bits vector to the digest, and update the prefix. + prefix = "X"; + for (char c : digest) + shabits.push_back((unsigned char) c); + bits = &shabits; + } + const char chars[33] = "abcdefghijklmnopqrstvwxyzABCDEFG"; go_assert(chars[32] == '\0'); - std::string ret; + std::string ret(prefix); unsigned int b = 0; int remaining = 0; - for (std::vector::const_iterator p = this->bits_.begin(); - p != this->bits_.end(); + for (std::vector::const_iterator p = bits->begin(); + p != bits->end(); ++p) { b |= *p << remaining;