#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"
}
}
-// 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<unsigned char>* bits(&this->bits_);
+ std::vector<unsigned char> 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<unsigned char>::const_iterator p = this->bits_.begin();
- p != this->bits_.end();
+ for (std::vector<unsigned char>::const_iterator p = bits->begin();
+ p != bits->end();
++p)
{
b |= *p << remaining;