compiler, libgo: change mangling scheme
authorIan Lance Taylor <iant@golang.org>
Tue, 17 Nov 2020 04:06:53 +0000 (20:06 -0800)
committerIan Lance Taylor <iant@golang.org>
Fri, 20 Nov 2020 20:44:35 +0000 (12:44 -0800)
Overhaul the mangling scheme to avoid ambiguities if the package path
contains a dot. Instead of using dot both to separate components and
to mangle characters, use dot only to separate components and use
underscore to mangle characters.

For golang/go#41862

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/271726

57 files changed:
gcc/go/gofrontend/MERGE
gcc/go/gofrontend/ast-dump.cc
gcc/go/gofrontend/export.cc
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/go-encode-id.cc
gcc/go/gofrontend/go-encode-id.h
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/names.cc
gcc/go/gofrontend/runtime.def
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h
libgo/configure
libgo/configure.ac
libgo/go/cmd/cgo/out.go
libgo/go/cmd/internal/pkgpath/pkgpath.go
libgo/go/cmd/internal/pkgpath/pkgpath_test.go
libgo/go/go/internal/srcimporter/srcimporter.go
libgo/go/internal/bytealg/bytealg.c
libgo/go/internal/cpu/cpu_gccgo.c
libgo/go/log/syslog/syslog_c.c
libgo/go/runtime/atomic_pointer.go
libgo/go/runtime/chan.go
libgo/go/runtime/cpuprof.go
libgo/go/runtime/debug.go
libgo/go/runtime/heapdump.go
libgo/go/runtime/iface.go
libgo/go/runtime/internal/atomic/atomic.c
libgo/go/runtime/malloc.go
libgo/go/runtime/map.go
libgo/go/runtime/mbarrier.go
libgo/go/runtime/mgc.go
libgo/go/runtime/mheap.go
libgo/go/runtime/mprof.go
libgo/go/runtime/mstats.go
libgo/go/runtime/net_plan9.go
libgo/go/runtime/netpoll.go
libgo/go/runtime/pprof/mprof_test.go
libgo/go/runtime/pprof/pprof_test.go
libgo/go/runtime/preempt.go
libgo/go/runtime/proc.go
libgo/go/runtime/proflabel.go
libgo/go/runtime/rdebug.go
libgo/go/runtime/runtime.go
libgo/go/runtime/runtime1.go
libgo/go/runtime/sema.go
libgo/go/runtime/sigqueue.go
libgo/go/runtime/symtab.go
libgo/go/runtime/trace.go
libgo/go/runtime/traceback_gccgo.go
libgo/go/sync/atomic/atomic.c
libgo/runtime/go-ffi.c
libgo/runtime/go-setenv.c
libgo/runtime/go-unsafe-pointer.c
libgo/runtime/go-unsetenv.c
libgo/runtime/runtime.h
libgo/testsuite/gotest

index 1f3c25ce710fc9248f6704bfbb234657c6555e77..9545a59873855363f54e75653ee0b1949114434e 100644 (file)
@@ -1,4 +1,4 @@
-c948c2d770122932a05b62f653efa2c51f72d3ae
+b483d0e0a289ba5fcdbd0388cbc75393367ca870
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index a3cbda9debc55b0a63c598a5820ad50b63a81719..eca0bf1fad2dcd40b234bd06e61219f2eb06f1bd 100644 (file)
@@ -226,7 +226,11 @@ Ast_dump_context::dump_type(const Type* t)
     // FIXME: write a type pretty printer instead of
     // using mangled names.
     if (this->gogo_ != NULL)
-      this->ostream() << "(" << t->mangled_name(this->gogo_) <<  ")";
+      {
+       Backend_name bname;
+       t->backend_name(this->gogo_, &bname);
+       this->ostream() << "(" << bname.name() << ")";
+      }
 }
 
 // Dump a textual representation of a block to the
index 90a5f6dbcec619f3fe0ebdd16bf470cb2d228cdb..e99c680f709fcfaba032f935736e7310ddfd5a64 100644 (file)
@@ -461,7 +461,7 @@ should_export(Named_object* no)
     return false;
 
   // We don't export various special functions.
-  if (Gogo::is_special_name(no->name()))
+  if (Gogo::special_name_pos(no->name()) != std::string::npos)
     return false;
 
   // Methods are exported with the type, not here.
@@ -524,7 +524,11 @@ struct Sort_types
     if (t1->classification() != t2->classification())
       return t1->classification() < t2->classification();
     Gogo* gogo = go_get_gogo();
-    return gogo->type_descriptor_name(t1, NULL).compare(gogo->type_descriptor_name(t2, NULL)) < 0;
+    Backend_name b1;
+    gogo->type_descriptor_backend_name(t1, NULL, &b1);
+    Backend_name b2;
+    gogo->type_descriptor_backend_name(t2, NULL, &b2);
+    return b1.name() < b2.name();
   }
 };
 
index e76bc6997c16902b8a4f90507b4f6188e7c24b58..6bc93488939dbf4b70d0fd30f0ce3cef9c7e6bdb 100644 (file)
@@ -1596,7 +1596,8 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
     return context->backend()->var_expression(this->dvar_, loc);
 
   Gogo* gogo = context->gogo();
-  std::string var_name(gogo->function_descriptor_name(no));
+  Backend_name bname;
+  gogo->function_descriptor_backend_name(no, &bname);
   bool is_descriptor = false;
   if (no->is_function_declaration()
       && !no->func_declaration_value()->asm_name().empty()
@@ -1616,10 +1617,11 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
   Btype* btype = this->type()->get_backend(gogo);
 
   Bvariable* bvar;
-  std::string asm_name(go_selectively_encode_id(var_name));
   if (no->package() != NULL || is_descriptor)
-    bvar = context->backend()->immutable_struct_reference(var_name, asm_name,
-                                                          btype, loc);
+    bvar =
+      context->backend()->immutable_struct_reference(bname.name(),
+                                                    bname.optional_asm_name(),
+                                                    btype, loc);
   else
     {
       Location bloc = Linemap::predeclared_location();
@@ -1644,7 +1646,8 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
       if (no->is_function() && no->func_value()->is_referenced_by_inline())
        is_hidden = false;
 
-      bvar = context->backend()->immutable_struct(var_name, asm_name,
+      bvar = context->backend()->immutable_struct(bname.name(),
+                                                 bname.optional_asm_name(),
                                                   is_hidden, false,
                                                  btype, bloc);
       Expression_list* vals = new Expression_list();
@@ -1654,8 +1657,9 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
       Translate_context bcontext(gogo, NULL, NULL, NULL);
       bcontext.set_is_const();
       Bexpression* binit = init->get_backend(&bcontext);
-      context->backend()->immutable_struct_set_init(bvar, var_name, is_hidden,
-                                                   false, btype, bloc, binit);
+      context->backend()->immutable_struct_set_init(bvar, bname.name(),
+                                                   is_hidden, false, btype,
+                                                   bloc, binit);
     }
 
   this->dvar_ = bvar;
@@ -5190,11 +5194,9 @@ Unary_expression::do_get_backend(Translate_context* context)
              copy_to_heap = (context->function() != NULL
                               || context->is_const());
            }
-         std::string asm_name(go_selectively_encode_id(var_name));
          Bvariable* implicit =
-              gogo->backend()->implicit_variable(var_name, asm_name,
-                                                 btype, true, copy_to_heap,
-                                                 false, 0);
+              gogo->backend()->implicit_variable(var_name, "", btype, true,
+                                                copy_to_heap, false, 0);
          gogo->backend()->implicit_variable_set_init(implicit, var_name, btype,
                                                      true, copy_to_heap, false,
                                                      bexpr);
@@ -5219,10 +5221,9 @@ Unary_expression::do_get_backend(Translate_context* context)
               && this->expr_->is_static_initializer())
         {
          std::string var_name(gogo->initializer_name());
-         std::string asm_name(go_selectively_encode_id(var_name));
           Bvariable* decl =
-              gogo->backend()->immutable_struct(var_name, asm_name,
-                                                true, false, btype, loc);
+              gogo->backend()->immutable_struct(var_name, "", true, false,
+                                               btype, loc);
           gogo->backend()->immutable_struct_set_init(decl, var_name, true,
                                                     false, btype, loc, bexpr);
           bexpr = gogo->backend()->var_expression(decl, loc);
@@ -5230,9 +5231,8 @@ Unary_expression::do_get_backend(Translate_context* context)
       else if (this->expr_->is_constant())
         {
           std::string var_name(gogo->initializer_name());
-          std::string asm_name(go_selectively_encode_id(var_name));
           Bvariable* decl =
-              gogo->backend()->implicit_variable(var_name, asm_name, btype,
+              gogo->backend()->implicit_variable(var_name, "", btype,
                                                  true, true, false, 0);
           gogo->backend()->implicit_variable_set_init(decl, var_name, btype,
                                                       true, true, false,
@@ -18251,9 +18251,8 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
     {
       // The interface conversion table is defined elsewhere.
       Btype* btype = this->type()->get_backend(gogo);
-      std::string asm_name(go_selectively_encode_id(mangled_name));
       this->bvar_ =
-          gogo->backend()->immutable_struct_reference(mangled_name, asm_name,
+          gogo->backend()->immutable_struct_reference(mangled_name, "",
                                                       btype, loc);
       return gogo->backend()->var_expression(this->bvar_, this->location());
     }
@@ -18323,8 +18322,7 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
   Bexpression* ctor =
       gogo->backend()->constructor_expression(btype, ctor_bexprs, loc);
 
-  std::string asm_name(go_selectively_encode_id(mangled_name));
-  this->bvar_ = gogo->backend()->immutable_struct(mangled_name, asm_name, false,
+  this->bvar_ = gogo->backend()->immutable_struct(mangled_name, "", false,
                                                  !is_public, btype, loc);
   gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, false,
                                              !is_public, btype, loc, ctor);
index 550da9759f637f46bdcbcd772f326340d587eebc..7ab65f513b394642c7448f6e21ff91719b1474fc 100644 (file)
@@ -12,8 +12,8 @@
 #include "go-encode-id.h"
 #include "lex.h"
 
-// Return whether the character c is OK to use in the assembler.  We
-// only permit ASCII alphanumeric characters, underscore, and dot.
+// Return whether the character c can appear in a name that we are
+// encoding.  We only permit ASCII alphanumeric characters.
 
 static bool
 char_needs_encoding(char c)
@@ -32,7 +32,6 @@ char_needs_encoding(char c)
     case 'y': case 'z':
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
-    case '_': case '.':
       return false;
     default:
       return true;
@@ -53,6 +52,52 @@ go_id_needs_encoding(const std::string& str)
   return false;
 }
 
+// Map from characters to the underscore encoding for them.
+
+class Special_char_code
+{
+ public:
+  Special_char_code();
+
+  // Return the simple underscore encoding for C, or 0 if none.
+  char
+  code_for(unsigned int c) const
+  {
+    if (c <= 127)
+      return this->codes_[c];
+    return 0;
+  }
+
+ private:
+  // Encodings for characters.
+  char codes_[128];
+};
+
+// Construct the underscore encoding map.
+
+Special_char_code::Special_char_code()
+{
+  memset(this->codes_, 0, sizeof this->codes_);
+  this->codes_['_'] = '_';
+  this->codes_['.'] = '0';
+  this->codes_['/'] = '1';
+  this->codes_['*'] = '2';
+  this->codes_[','] = '3';
+  this->codes_['{'] = '4';
+  this->codes_['}'] = '5';
+  this->codes_['['] = '6';
+  this->codes_[']'] = '7';
+  this->codes_['('] = '8';
+  this->codes_[')'] = '9';
+  this->codes_['"'] = 'a';
+  this->codes_[' '] = 'b';
+  this->codes_[';'] = 'c';
+}
+
+// The singleton Special_char_code.
+
+static const Special_char_code special_char_code;
+
 // Pull the next UTF-8 character out of P and store it in *PC.  Return
 // the number of bytes read.
 
@@ -82,10 +127,9 @@ fetch_utf8_char(const char* p, unsigned int* pc)
   return len;
 }
 
-// Encode an identifier using assembler-friendly characters. The encoding is
-// described in detail near the end of the long comment at the start of
-// names.cc. Short version: translate all non-ASCII-alphanumeric characters into
-// ..uXXXX or ..UXXXXXXXX, translate ASCII non-alphanumerics into ".zXX".
+// Encode an identifier using assembler-friendly characters.  The
+// encoding is described in detail near the end of the long comment at
+// the start of names.cc.
 
 std::string
 go_encode_id(const std::string &id)
@@ -96,50 +140,57 @@ go_encode_id(const std::string &id)
       return id;
     }
 
-  // The encoding is only unambiguous if the input string does not
-  // contain ..z, ..u or ..U.
-  go_assert(id.find("..z") == std::string::npos);
-  go_assert(id.find("..u") == std::string::npos);
-  go_assert(id.find("..U") == std::string::npos);
-
   std::string ret;
   const char* p = id.c_str();
   const char* pend = p + id.length();
 
-  // A leading ".0" is a space introduced before a mangled type name
-  // that starts with a 'u' or 'U', to avoid confusion with the
-  // mangling used here.  We don't need a leading ".0", and we don't
-  // want symbols that start with '.', so remove it.
-  if (p[0] == '.' && p[1] == '0')
-    p += 2;
+  // We encode a leading digit, to ensure that no identifier starts
+  // with a digit.
+  if (pend > p && p[0] >= '0' && p[0] <= '9')
+    {
+      char buf[8];
+      snprintf(buf, sizeof buf, "_x%02x", p[0]);
+      ret.append(buf);
+      ++p;
+    }
 
   while (p < pend)
     {
       unsigned int c;
       size_t len = fetch_utf8_char(p, &c);
-      if (len == 1 && !char_needs_encoding(c))
+      if (len == 1)
        {
-         ret += c;
+         if (!char_needs_encoding(c))
+           ret.push_back(c);
+         else
+           {
+             char code = special_char_code.code_for(c);
+             if (code != 0)
+               {
+                 ret.push_back('_');
+                 ret.push_back(code);
+               }
+             else
+               {
+                 char buf[8];
+                 snprintf(buf, sizeof buf, "_x%02x", c);
+                 ret.append(buf);
+               }
+           }
        }
       else
        {
          char buf[16];
-          if (len == 1)
-            snprintf(buf, sizeof buf, "..z%02x", c);
-         else if (c < 0x10000)
-           snprintf(buf, sizeof buf, "..u%04x", c);
+         if (c < 0x10000)
+           snprintf(buf, sizeof buf, "_u%04x", c);
          else
-           snprintf(buf, sizeof buf, "..U%08x", c);
-
-         // We don't want a symbol to start with '.', so add a prefix
-         // if needed.
-         if (ret.empty())
-           ret += '_';
-
-         ret += buf;
+           snprintf(buf, sizeof buf, "_U%08x", c);
+         ret.append(buf);
        }
+
       p += len;
     }
+
   return ret;
 }
 
@@ -170,64 +221,116 @@ go_decode_id(const std::string &encoded)
   const char* pend = p + encoded.length();
   const Location loc = Linemap::predeclared_location();
 
-  // Special case for initial "_", in case it was introduced
-  // as a way to prevent encoded symbol starting with ".".
-  if (*p == '_' && (strncmp(p+1, "..u", 3) == 0 || strncmp(p+1, "..U", 3) == 0))
-    p++;
-
   while (p < pend)
     {
-      if (strncmp(p, "..z", 3) == 0)
-        {
-          const char* digits = p+3;
-          if (strlen(digits) < 2)
-            return "";
-          unsigned rune = hex_digits_to_unicode_codepoint(digits, 2);
-          Lex::append_char(rune, true, &ret, loc);
-          p += 5;
-        }
-      else if (strncmp(p, "..u", 3) == 0)
-        {
-          const char* digits = p+3;
-          if (strlen(digits) < 4)
-            return "";
-          unsigned rune = hex_digits_to_unicode_codepoint(digits, 4);
-          Lex::append_char(rune, true, &ret, loc);
-          p += 7;
-        }
-      else if (strncmp(p, "..U", 3) == 0)
-        {
-          const char* digits = p+3;
-          if (strlen(digits) < 8)
-            return "";
-          unsigned rune = hex_digits_to_unicode_codepoint(digits, 8);
-          Lex::append_char(rune, true, &ret, loc);
-          p += 11;
-        }
-      else
-        {
-          ret += *p;
-          p += 1;
-        }
+      if (*p != '_' || p + 1 == pend)
+       {
+         ret.push_back(*p);
+         p++;
+         continue;
+       }
+
+      switch (p[1])
+       {
+       case '_':
+         ret.push_back('_');
+         p += 2;
+         break;
+       case '0':
+         ret.push_back('.');
+         p += 2;
+         break;
+       case '1':
+         ret.push_back('/');
+         p += 2;
+         break;
+       case '2':
+         ret.push_back('*');
+         p += 2;
+         break;
+       case '3':
+         ret.push_back(',');
+         p += 2;
+         break;
+       case '4':
+         ret.push_back('{');
+         p += 2;
+         break;
+       case '5':
+         ret.push_back('}');
+         p += 2;
+         break;
+       case '6':
+         ret.push_back('[');
+         p += 2;
+         break;
+       case '7':
+         ret.push_back(']');
+         p += 2;
+         break;
+       case '8':
+         ret.push_back('(');
+         p += 2;
+         break;
+       case '9':
+         ret.push_back(')');
+         p += 2;
+         break;
+       case 'a':
+         ret.push_back('"');
+         p += 2;
+         break;
+       case 'b':
+         ret.push_back(' ');
+         p += 2;
+         break;
+       case 'c':
+         ret.push_back(';');
+         p += 2;
+         break;
+        case 'x':
+         {
+           const char* digits = p + 2;
+           if (strlen(digits) < 2)
+             return "";
+           unsigned int rune = hex_digits_to_unicode_codepoint(digits, 2);
+           Lex::append_char(rune, true, &ret, loc);
+           p += 4;
+         }
+         break;
+       case 'u':
+         {
+           const char* digits = p + 2;
+           if (strlen(digits) < 4)
+             return "";
+           unsigned int rune = hex_digits_to_unicode_codepoint(digits, 4);
+           Lex::append_char(rune, true, &ret, loc);
+           p += 6;
+         }
+         break;
+       case 'U':
+         {
+           const char* digits = p + 2;
+           if (strlen(digits) < 8)
+             return "";
+           unsigned int rune = hex_digits_to_unicode_codepoint(digits, 8);
+           Lex::append_char(rune, true, &ret, loc);
+           p += 10;
+         }
+         break;
+       default:
+         return "";
+       }
     }
 
   return ret;
 }
 
-std::string
-go_selectively_encode_id(const std::string &id)
-{
-  if (go_id_needs_encoding(id))
-    return go_encode_id(id);
-  return std::string();
-}
-
 // Encode a struct field tag.  This is only used when we need to
 // create a type descriptor for an anonymous struct type with field
-// tags.  This mangling is applied before go_encode_id.  We skip
-// alphanumerics and underscore, replace every other single byte
-// character with .xNN, and leave larger UTF-8 characters for
-// go_encode_id.
+// tags.  Underscore encoding will be applied to the returned string.
+// The tag will appear between curly braces, so that is all we have to
+// avoid.
 
 std::string
 go_mangle_struct_tag(const std::string& tag)
@@ -241,28 +344,14 @@ go_mangle_struct_tag(const std::string& tag)
       size_t len = fetch_utf8_char(p, &c);
       if (len > 1)
        ret.append(p, len);
-      else if (!char_needs_encoding(c) && c != '.')
-       ret += c;
+      else if (c != '{' && c != '}' && c != '\\')
+       ret.push_back(c);
       else
        {
-         char buf[16];
-         snprintf(buf, sizeof buf, ".x%02x", c);
-         ret += buf;
+         ret.push_back('\\');
+         ret.push_back(c);
        }
       p += len;
     }
   return ret;
 }
-
-// Encode a package path.
-
-std::string
-go_mangle_pkgpath(const std::string& pkgpath)
-{
-  std::string s = pkgpath;
-  for (size_t i = s.find('.');
-       i != std::string::npos;
-       i = s.find('.', i + 1))
-    s.replace(i, 1, ".x2e"); // 0x2e is the ASCII encoding for '.'
-  return s;
-}
index 2d09b0c545d630b63b896cf7594e8d60c318c04e..cbafd5447d6f33d543e589d52bb6b1820a8cd39d 100644 (file)
@@ -25,21 +25,8 @@ go_encode_id(const std::string &id);
 extern std::string
 go_decode_id(const std::string &id);
 
-// Returns the empty string if the specified name needs encoding,
-// otherwise invokes go_encode_id on the name and returns the result.
-extern std::string
-go_selectively_encode_id(const std::string &id);
-
 // Encodes a struct tag that appears in a type literal encoding.
 extern std::string
 go_mangle_struct_tag(const std::string& tag);
 
-// Encode a package path.  A package path can contain any arbitrary
-// character, including '.'.  go_encode_id expects that any '.' will
-// be inserted by name mangling in a controlled manner.  So first
-// translate any '.' using the same .x encoding as used by
-// go_mangle_struct_tag.
-extern std::string
-go_mangle_pkgpath(const std::string& pkgpath);
-
 #endif // !defined(GO_ENCODE_ID_H)
index f40f13129e6988ab7a4151795182df6a947272c6..93a4a5773a20e019c8737e75630793b064cd9a93 100644 (file)
@@ -299,7 +299,7 @@ void
 Gogo::set_pkgpath(const std::string& arg)
 {
   go_assert(!this->pkgpath_set_);
-  this->pkgpath_ = go_mangle_pkgpath(arg);
+  this->pkgpath_ = arg;
   this->pkgpath_set_ = true;
   this->pkgpath_from_option_ = true;
 }
@@ -324,32 +324,6 @@ Gogo::set_prefix(const std::string& arg)
   this->prefix_from_option_ = true;
 }
 
-// Given a name which may or may not have been hidden, append the
-// appropriate version of the name to the result string. Take care
-// to avoid creating a sequence that will be rejected by go_encode_id
-// (avoid ..u, ..U, ..z).
-void
-Gogo::append_possibly_hidden_name(std::string *result, const std::string& name)
-{
-  // FIXME: This adds in pkgpath twice for hidden symbols, which is
-  // less than ideal.
-  if (!Gogo::is_hidden_name(name))
-    (*result) += name;
-  else
-    {
-      std::string n = ".";
-      std::string pkgpath = Gogo::hidden_name_pkgpath(name);
-      char lastR = result->at(result->length() - 1);
-      char firstP = pkgpath.at(0);
-      if (lastR == '.' && (firstP == 'u' || firstP == 'U' || firstP == 'z'))
-        n = "_.";
-      n.append(pkgpath);
-      n.append(1, '.');
-      n.append(Gogo::unpack_hidden_name(name));
-      (*result) += n;
-    }
-}
-
 // Munge name for use in an error message.
 
 std::string
@@ -397,8 +371,7 @@ Gogo::set_package_name(const std::string& package_name,
        {
          if (!this->prefix_from_option_)
            this->prefix_ = "go";
-         this->pkgpath_ = (go_mangle_pkgpath(this->prefix_) + '.'
-                           + package_name);
+         this->pkgpath_ = this->prefix_ + '.' + package_name;
          this->pkgpath_symbol_ = (Gogo::pkgpath_for_symbol(this->prefix_) + '.'
                                   + Gogo::pkgpath_for_symbol(package_name));
        }
@@ -997,9 +970,9 @@ Gogo::register_type_descriptors(std::vector<Bstatement*>& init_stmts,
        it != this->imported_init_fns_.end();
        ++it)
     {
-      std::string pkgpath =
-        this->pkgpath_from_init_fn_name((*it)->init_name());
-      list_names.push_back(this->type_descriptor_list_symbol(pkgpath));
+      std::string pkgpath_symbol =
+        this->pkgpath_symbol_from_init_fn_name((*it)->init_name());
+      list_names.push_back(this->type_descriptor_list_symbol(pkgpath_symbol));
     }
   // Add the main package itself.
   list_names.push_back(this->type_descriptor_list_symbol("main"));
@@ -2746,8 +2719,7 @@ Gogo::clear_file_scope()
 // parse tree is lowered.
 
 void
-Gogo::queue_hash_function(Type* type, int64_t size,
-                         const std::string& hash_name,
+Gogo::queue_hash_function(Type* type, int64_t size, Backend_name* bname,
                          Function_type* hash_fntype)
 {
   go_assert(!this->specific_type_functions_are_written_);
@@ -2755,7 +2727,7 @@ Gogo::queue_hash_function(Type* type, int64_t size,
   Specific_type_function::Specific_type_function_kind kind =
     Specific_type_function::SPECIFIC_HASH;
   Specific_type_function* tsf = new Specific_type_function(type, NULL, size,
-                                                          kind, hash_name,
+                                                          kind, bname,
                                                           hash_fntype);
   this->specific_type_functions_.push_back(tsf);
 }
@@ -2766,15 +2738,14 @@ Gogo::queue_hash_function(Type* type, int64_t size,
 
 void
 Gogo::queue_equal_function(Type* type, Named_type* name, int64_t size,
-                          const std::string& equal_name,
-                          Function_type* equal_fntype)
+                          Backend_name* bname, Function_type* equal_fntype)
 {
   go_assert(!this->specific_type_functions_are_written_);
   go_assert(!this->in_global_scope());
   Specific_type_function::Specific_type_function_kind kind =
     Specific_type_function::SPECIFIC_EQUAL;
   Specific_type_function* tsf = new Specific_type_function(type, name, size,
-                                                          kind, equal_name,
+                                                          kind, bname,
                                                           equal_fntype);
   this->specific_type_functions_.push_back(tsf);
 }
@@ -2872,11 +2843,11 @@ Gogo::write_specific_type_functions()
       Specific_type_function* tsf = this->specific_type_functions_.back();
       this->specific_type_functions_.pop_back();
       if (tsf->kind == Specific_type_function::SPECIFIC_HASH)
-       tsf->type->write_hash_function(this, tsf->size, tsf->fnname,
+       tsf->type->write_hash_function(this, tsf->size, &tsf->bname,
                                       tsf->fntype);
       else
        tsf->type->write_equal_function(this, tsf->name, tsf->size,
-                                       tsf->fnname, tsf->fntype);
+                                       &tsf->bname, tsf->fntype);
       delete tsf;
     }
   this->specific_type_functions_are_written_ = true;
@@ -6218,6 +6189,56 @@ Function::import_func(Import* imp, std::string* pname,
   return true;
 }
 
+// Get the backend name.
+
+void
+Function::backend_name(Gogo* gogo, Named_object* no, Backend_name *bname)
+{
+  if (!this->asm_name_.empty())
+    bname->set_asm_name(this->asm_name_);
+  else if (no->package() == NULL && no->name() == gogo->get_init_fn_name())
+    {
+      // These names appear in the export data and are used
+      // directly in the assembler code.  If we change this here
+      // we need to change Gogo::init_imports.
+      bname->set_asm_name(no->name());
+    }
+  else if (this->enclosing_ != NULL)
+    {
+      // Rewrite the nested name to use the enclosing function name.
+      // We don't do this earlier because we just store simple names
+      // in a Named_object, not Backend_names.
+
+      // The name was set by nested_function_name, which always
+      // appends ..funcNNN.  We want that to be our suffix.
+      size_t pos = no->name().find("..func");
+      go_assert(pos != std::string::npos);
+
+      Named_object* enclosing = this->enclosing_;
+      while (true)
+       {
+         Named_object* parent = enclosing->func_value()->enclosing();
+         if (parent == NULL)
+           break;
+         enclosing = parent;
+       }
+
+      Type* rtype = NULL;
+      if (enclosing->func_value()->type()->is_method())
+       rtype = enclosing->func_value()->type()->receiver()->type();
+      gogo->function_backend_name(enclosing->name(), enclosing->package(),
+                                 rtype, bname);
+      bname->append_suffix(no->name().substr(pos));
+    }
+  else
+    {
+      Type* rtype = NULL;
+      if (this->type_->is_method())
+       rtype = this->type_->receiver()->type();
+      gogo->function_backend_name(no->name(), no->package(), rtype, bname);
+    }
+}
+
 // Get the backend representation.
 
 Bfunction*
@@ -6226,7 +6247,6 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
   if (this->fndecl_ == NULL)
     {
       unsigned int flags = 0;
-      bool is_init_fn = false;
       if (no->package() != NULL)
        {
          // Functions defined in other packages must be visible.
@@ -6238,10 +6258,7 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
                && !this->type_->is_method())
        ;
       else if (no->name() == gogo->get_init_fn_name())
-       {
-         flags |= Backend::function_is_visible;
-         is_init_fn = true;
-       }
+       flags |= Backend::function_is_visible;
       else if (Gogo::unpack_hidden_name(no->name()) == "main"
                && gogo->is_main_package())
        flags |= Backend::function_is_visible;
@@ -6255,29 +6272,13 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
            flags |= Backend::function_is_visible;
         }
 
-      Type* rtype = NULL;
-      if (this->type_->is_method())
-       rtype = this->type_->receiver()->type();
-
-      std::string asm_name;
       if (!this->asm_name_.empty())
        {
-         asm_name = this->asm_name_;
-
          // If an assembler name is explicitly specified, there must
          // be some reason to refer to the symbol from a different
          // object file.
          flags |= Backend::function_is_visible;
        }
-      else if (is_init_fn)
-       {
-         // These names appear in the export data and are used
-         // directly in the assembler code.  If we change this here
-         // we need to change Gogo::init_imports.
-         asm_name = no->name();
-       }
-      else
-       asm_name = gogo->function_asm_name(no->name(), no->package(), rtype);
 
       // If an inline body refers to this function, then it
       // needs to be visible in the symbol table.
@@ -6337,13 +6338,36 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
        flags |= Backend::function_only_inline;
 
       Btype* functype = this->type_->get_backend_fntype(gogo);
-      this->fndecl_ =
-          gogo->backend()->function(functype, no->get_id(gogo), asm_name,
-                                   flags, this->location());
+
+      Backend_name bname;
+      this->backend_name(gogo, no, &bname);
+
+      this->fndecl_ = gogo->backend()->function(functype,
+                                               bname.name(),
+                                               bname.optional_asm_name(),
+                                               flags,
+                                               this->location());
     }
   return this->fndecl_;
 }
 
+// Get the backend name.
+
+void
+Function_declaration::backend_name(Gogo* gogo, Named_object* no,
+                                  Backend_name* bname)
+{
+  if (!this->asm_name_.empty())
+    bname->set_asm_name(this->asm_name_);
+  else
+    {
+      Type* rtype = NULL;
+      if (this->fntype_->is_method())
+       rtype = this->fntype_->receiver()->type();
+      gogo->function_backend_name(no->name(), no->package(), rtype, bname);
+    }
+}
+
 // Get the backend representation.
 
 Bfunction*
@@ -6375,21 +6399,16 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
            flags |= Backend::function_does_not_return;
        }
 
-      std::string asm_name;
-      if (this->asm_name_.empty())
-       {
-         Type* rtype = NULL;
-         if (this->fntype_->is_method())
-           rtype = this->fntype_->receiver()->type();
-         asm_name = gogo->function_asm_name(no->name(), no->package(), rtype);
-       }
-      else if (go_id_needs_encoding(no->get_id(gogo)))
-        asm_name = go_encode_id(no->get_id(gogo));
-
       Btype* functype = this->fntype_->get_backend_fntype(gogo);
-      this->fndecl_ =
-          gogo->backend()->function(functype, no->get_id(gogo), asm_name,
-                                   flags, this->location());
+
+      Backend_name bname;
+      this->backend_name(gogo, no, &bname);
+
+      this->fndecl_ = gogo->backend()->function(functype,
+                                               bname.name(),
+                                               bname.optional_asm_name(),
+                                               flags,
+                                               this->location());
     }
 
   return this->fndecl_;
@@ -7993,7 +8012,6 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
              type = Type::make_pointer_type(type);
            }
 
-         const std::string n = Gogo::unpack_hidden_name(name);
          Btype* btype = type->get_backend(gogo);
 
          Bvariable* bvar;
@@ -8001,19 +8019,14 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
            bvar = Map_type::backend_zero_value(gogo);
          else if (this->is_global_)
            {
-             std::string var_name(package != NULL
-                                  ? package->package_name()
-                                  : gogo->package_name());
-             var_name.push_back('.');
-             var_name.append(n);
-
-              std::string asm_name(gogo->global_var_asm_name(name, package));
+             Backend_name bname;
+             gogo->global_var_backend_name(name, package, &bname);
 
              bool is_hidden = Gogo::is_hidden_name(name);
              // Hack to export runtime.writeBarrier.  FIXME.
              // This is because go:linkname doesn't work on variables.
              if (gogo->compiling_runtime()
-                 && var_name == "runtime.writeBarrier")
+                 && bname.name() == "runtime.writeBarrier")
                is_hidden = false;
 
              // If an inline body refers to this variable, then it
@@ -8028,8 +8041,12 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
              if (package != NULL)
                is_hidden = false;
 
-             bvar = backend->global_variable(var_name,
-                                             asm_name,
+             // For some reason asm_name can't be the empty string
+             // for global_variable, so we call asm_name rather than
+             // optional_asm_name here.  FIXME.
+
+             bvar = backend->global_variable(bname.name(),
+                                             bname.asm_name(),
                                              btype,
                                              package != NULL,
                                              is_hidden,
@@ -8043,6 +8060,7 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
            }
          else
            {
+             const std::string n = Gogo::unpack_hidden_name(name);
              Bfunction* bfunction = function->func_value()->get_decl();
              bool is_address_taken = (this->is_non_escaping_address_taken_
                                       && !this->is_in_heap());
@@ -8216,7 +8234,13 @@ Named_constant::get_backend(Gogo* gogo, Named_object* const_no)
       if (type != NULL && type->is_numeric_type())
        {
          Btype* btype = type->get_backend(gogo);
-         std::string name = const_no->get_id(gogo);
+         std::string name;
+         if (const_no->package() == NULL)
+           name = gogo->pkgpath();
+         else
+           name = const_no->package()->pkgpath();
+         name.push_back('.');
+         name.append(Gogo::unpack_hidden_name(const_no->name()));
          const_decl =
            gogo->backend()->named_constant_expression(btype, name,
                                                       const_decl, loc);
@@ -8637,54 +8661,6 @@ Named_object::get_backend_variable(Gogo* gogo, Named_object* function)
     go_unreachable();
 }
 
-// Return the external identifier for this object.
-
-std::string
-Named_object::get_id(Gogo* gogo)
-{
-  go_assert(!this->is_variable()
-           && !this->is_result_variable()
-           && !this->is_type());
-  std::string decl_name;
-  if (this->is_function_declaration()
-      && !this->func_declaration_value()->asm_name().empty())
-    decl_name = this->func_declaration_value()->asm_name();
-  else
-    {
-      std::string package_name;
-      if (this->package_ == NULL)
-       package_name = gogo->package_name();
-      else
-       package_name = this->package_->package_name();
-
-      // Note that this will be misleading if this is an unexported
-      // method generated for an embedded imported type.  In that case
-      // the unexported method should have the package name of the
-      // package from which it is imported, but we are going to give
-      // it our package name.  Fixing this would require knowing the
-      // package name, but we only know the package path.  It might be
-      // better to use package paths here anyhow.  This doesn't affect
-      // the assembler code, because we always set that name in
-      // Function::get_or_make_decl anyhow.  FIXME.
-
-      decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_);
-
-      Function_type* fntype;
-      if (this->is_function())
-       fntype = this->func_value()->type();
-      else if (this->is_function_declaration())
-       fntype = this->func_declaration_value()->type();
-      else
-       fntype = NULL;
-      if (fntype != NULL && fntype->is_method())
-       {
-         decl_name.push_back('.');
-         decl_name.append(fntype->receiver()->type()->mangled_name(gogo));
-       }
-    }
-  return decl_name;
-}
-
 void
 debug_go_named_object(Named_object* no)
 {
index 45be1732aa0fa97f39323bf1104f7023cbc9f77d..f22d47656db04977b81f6a13ae31f607bd0bac4c 100644 (file)
@@ -57,6 +57,101 @@ class Node;
 // This file declares the basic classes used to hold the internal
 // representation of Go which is built by the parser.
 
+// The name of some backend object.  Backend objects have a
+// user-visible name and an assembler name.  The user visible name
+// might include arbitrary Unicode characters.  The assembler name
+// will not.
+
+class Backend_name
+{
+ public:
+  Backend_name()
+    : prefix_(NULL), components_(), count_(0), suffix_(),
+      is_asm_name_(false)
+  {}
+
+  // Set the prefix.  Prefixes are always constant strings.
+  void
+  set_prefix(const char* p)
+  {
+    go_assert(this->prefix_ == NULL && !this->is_asm_name_);
+    this->prefix_ = p;
+  }
+
+  // Set the suffix.
+  void
+  set_suffix(const std::string& s)
+  {
+    go_assert(this->suffix_.empty() && !this->is_asm_name_);
+    this->suffix_ = s;
+  }
+
+  // Append to the suffix.
+  void
+  append_suffix(const std::string& s)
+  {
+    if (this->is_asm_name_)
+      this->components_[0].append(s);
+    else
+      this->suffix_.append(s);
+  }
+
+  // Add a component.
+  void
+  add(const std::string& c)
+  {
+    go_assert(this->count_ < Backend_name::max_components
+             && !this->is_asm_name_);
+    this->components_[this->count_] = c;
+    ++this->count_;
+  }
+
+  // Set an assembler name specified by the user.  This overrides both
+  // the user-visible name and the assembler name.  No further
+  // encoding is applied.
+  void
+  set_asm_name(const std::string& n)
+  {
+    go_assert(this->prefix_ == NULL
+             && this->count_ == 0
+             && this->suffix_.empty()
+             && !this->is_asm_name_);
+    this->components_[0] = n;
+    this->is_asm_name_ = true;
+  }
+
+  // Get the user visible name.
+  std::string
+  name() const;
+
+  // Get the assembler name.  This may be the same as the user visible
+  // name.
+  std::string
+  asm_name() const;
+
+  // Get an optional assembler name: if it would be the same as the
+  // user visible name, this returns the empty string.
+  std::string
+  optional_asm_name() const;
+
+ private:
+  // The maximum number of components.
+  static const int max_components = 4;
+
+  // An optional prefix that does not require encoding.
+  const char *prefix_;
+  // Up to four components.  The name will include these components
+  // separated by dots.  Each component will be underscore-encoded
+  // (see the long comment near the top of names.cc).
+  std::string components_[Backend_name::max_components];
+  // Number of components.
+  int count_;
+  // An optional suffix that does not require encoding.
+  std::string suffix_;
+  // True if components_[0] is an assembler name specified by the user.
+  bool is_asm_name_;
+};
+
 // An initialization function for an imported package.  This is a
 // magic function which initializes variables and runs the "init"
 // function.
@@ -613,7 +708,7 @@ class Gogo
   // is used when a type-specific hash function is needed when not at
   // top level.
   void
-  queue_hash_function(Type* type, int64_t size, const std::string& hash_name,
+  queue_hash_function(Type* type, int64_t size, Backend_name*,
                      Function_type* hash_fntype);
 
   // Queue up a type-specific equal function to be written out.  This
@@ -621,8 +716,7 @@ class Gogo
   // top level.
   void
   queue_equal_function(Type* type, Named_type* name, int64_t size,
-                      const std::string& equal_name,
-                      Function_type* equal_fntype);
+                      Backend_name*, Function_type* equal_fntype);
 
   // Write out queued specific type functions.
   void
@@ -869,31 +963,32 @@ class Gogo
   Expression*
   allocate_memory(Type *type, Location);
 
-  // Return the assembler name to use for an exported function, a
-  // method, or a function/method declaration.
-  std::string
-  function_asm_name(const std::string& go_name, const Package*,
-                   const Type* receiver);
+  // Get the backend name to use for an exported function, a method,
+  // or a function/method declaration.
+  void
+  function_backend_name(const std::string& go_name, const Package*,
+                       const Type* receiver, Backend_name*);
 
   // Return the name to use for a function descriptor.
-  std::string
-  function_descriptor_name(Named_object*);
+  void
+  function_descriptor_backend_name(Named_object*, Backend_name*);
 
   // Return the name to use for a generated stub method.
   std::string
   stub_method_name(const Package*, const std::string& method_name);
 
-  // Return the name of the hash function for TYPE.
-  std::string
-  hash_function_name(const Type*);
+  // Get the backend name of the hash function for TYPE.
+  void
+  hash_function_name(const Type*, Backend_name*);
 
-  // Return the name of the equal function for TYPE.
-  std::string
-  equal_function_name(const Type*, const Named_type*);
+  // Get the backend name of the equal function for TYPE.
+  void
+  equal_function_name(const Type*, const Named_type*, Backend_name*);
 
-  // Return the assembler name to use for a global variable.
-  std::string
-  global_var_asm_name(const std::string& go_name, const Package*);
+  // Get the backend name to use for a global variable.
+  void
+  global_var_backend_name(const std::string& go_name, const Package*,
+                         Backend_name*);
 
   // Return a name to use for an error case.  This should only be used
   // after reporting an error, and is used to avoid useless knockon
@@ -961,13 +1056,14 @@ class Gogo
   // Return the package path symbol from an init function name, which
   // can be a real init function or a dummy one.
   std::string
-  pkgpath_from_init_fn_name(std::string);
+  pkgpath_symbol_from_init_fn_name(std::string);
 
-  // Return the name for a type descriptor symbol.
-  std::string
-  type_descriptor_name(const Type*, Named_type*);
+  // Get the backend name for a type descriptor symbol.
+  void
+  type_descriptor_backend_name(const Type*, Named_type*, Backend_name*);
 
   // Return the name of the type descriptor list symbol of a package.
+  // The argument is an encoded pkgpath, as with pkgpath_symbol.
   std::string
   type_descriptor_list_symbol(const std::string&);
 
@@ -987,11 +1083,11 @@ class Gogo
   std::string
   interface_method_table_name(Interface_type*, Type*, bool is_pointer);
 
-  // Return whether NAME is a special name that can not be passed to
-  // unpack_hidden_name.  This is needed because various special names
-  // use "..SUFFIX", but unpack_hidden_name just looks for '.'.
-  static bool
-  is_special_name(const std::string& name);
+  // If NAME is a special name used as a Go identifier, return the
+  // position within the string where the special part of the name
+  // occurs.
+  static size_t
+  special_name_pos(const std::string& name);
 
  private:
   // During parsing, we keep a stack of functions.  Each function on
@@ -1056,6 +1152,9 @@ class Gogo
   Named_object*
   write_barrier_variable();
 
+  static bool
+  is_digits(const std::string&);
+
   // Type used to map import names to packages.
   typedef std::map<std::string, Package*> Imports;
 
@@ -1079,15 +1178,15 @@ class Gogo
     Named_type* name;
     int64_t size;
     Specific_type_function_kind kind;
-    std::string fnname;
+    Backend_name bname;
     Function_type* fntype;
 
     Specific_type_function(Type* atype, Named_type* aname, int64_t asize,
                           Specific_type_function_kind akind,
-                          const std::string& afnname,
+                          Backend_name* abname,
                           Function_type* afntype)
       : type(atype), name(aname), size(asize), kind(akind),
-       fnname(afnname), fntype(afntype)
+       bname(*abname), fntype(afntype)
     { }
   };
 
@@ -1631,6 +1730,10 @@ class Function
   Bstatement*
   return_value(Gogo*, Named_object*, Location) const;
 
+  // Get the backend name of this function.
+  void
+  backend_name(Gogo*, Named_object*, Backend_name*);
+
   // Get an expression for the variable holding the defer stack.
   Expression*
   defer_stack(Location);
@@ -1872,6 +1975,10 @@ class Function_declaration
   void
   build_backend_descriptor(Gogo*);
 
+  // Get the backend name of this function declaration.
+  void
+  backend_name(Gogo*, Named_object*, Backend_name*);
+
   // Export a function declaration.
   void
   export_func(Export* exp, const Named_object* no) const
@@ -2863,10 +2970,6 @@ class Named_object
   Bvariable*
   get_backend_variable(Gogo*, Named_object* function);
 
-  // Return the external identifier for this object.
-  std::string
-  get_id(Gogo*);
-
   // Get the backend representation of this object.
   void
   get_backend(Gogo*, std::vector<Bexpression*>&, std::vector<Btype*>&,
index 1f0a54502dbad729d1c7d574aa490896c1c6125d..0097417cff0003edc6352784259efeb67c55ce3e 100644 (file)
 // assembly code.  This is not used for names that appear only in the
 // debug info.
 
-// Our external names contain only ASCII alphanumeric characters,
+// Our external names may contain only ASCII alphanumeric characters,
 // underscore, and dot.  (According to the GCC sources, dot is not
 // permitted in assembler symbols on VxWorks and MMIX.  We will not
-// support those systems.)  Go names can not contain dot, so we rely
-// on using dot to encode Unicode characters, and to separate Go
-// symbols by package, and so forth.  We assume that none of the
-// non-Go symbols in the final link will contain a dot, so we don't
-// worry about conflicts.
+// support those systems.)  Go identifiers cannot contain dot, but Go
+// package paths can.  Both Go identifiers and package paths can, of
+// course, contain all sorts of Unicode characters.
+//
+// The gc compiler uses names like "pkg.F", and it seems convenient to
+// emulate that.  Therefore, we will use dot to separate different
+// components of names.
+//
+// Since package paths can contain dot, to avoid ambiguity we must
+// encode package paths such that they do not contain any dot.  The
+// natural way to do this is to encode forbidden characters, including
+// dot, using a notation based on underscore.  We will, of course,
+// have to encode underscore itself.
+//
+// Since we will be using an underscore encoding for the package path,
+// it seems reasonable to use the same encoding for Go identifiers.
+// This has the disadvantage that encoded Go identifiers will appear
+// to be valid Go identifiers with funny spellings, but it seems like
+// the best available approach.
+//
+// Therefore, in the following discussion we may assume that none of
+// the names under discussion contain a dot.  All of the names we
+// generate for Go identifiers (that don't use //export or
+// //go:linkname) will contain at least one dot, as discussed below.
+// We assume that none of the non-Go symbols in the final link will
+// contain a dot, so we don't worry about conflicts.
 //
 // We first describe the basic symbol names, used to represent Go
-// functions and variables.  These never start with a dot, never end
-// with a dot, never contain two consecutive dots, and never contain a
-// dot followed by a digit.
+// functions and variables.
 //
 // The external name for a normal Go symbol NAME, a function or
 // variable, is simply "PKGPATH.NAME".  Note that NAME is not the
 // packed form used for the "hidden" name internally in the compiler;
-// it is the name that appears in the source code.  PKGPATH is the
-// -fgo-pkgpath option as adjusted by Gogo::pkgpath_for_symbol. Note
-// that PKGPATH can not contain a dot and neither can NAME.  Also,
-// NAME may not begin with a digit.  NAME may require further encoding
-// for non-ASCII characters as described below, but until that
-// encoding these symbols contain exactly one dot, and they do not
-// start with a dot.
+// it is the name that appears in the source code.  Both PKGPATH and
+// NAME will be encoded as described below.  The encoding process
+// ensures that neither encoded string can contain a dot, and neither
+// will start with a digit (NAME is a Go identifier that can't contain
+// a dot or start with a digit anyhow).  The encoding process means
+// that these external names contain exactly one dot and do not start
+// with a dot.
 //
 // The external name for a method NAME for a named type TYPE is
-// "PKGPATH.TYPE.NAME".  Unlike the gc compiler, the external name
-// does not indicate whether this is a pointer method or a value
-// method; a named type can not have both a pointer and value method
-// with the same name, so there is no ambiguity.  PKGPATH is the
-// package path of the package in which TYPE is defined.  Here none of
-// PKGPATH, TYPE, or NAME can be empty or contain a dot, and neither
-// TYPE nor NAME may begin with a digit.  Before encoding these names
-// contain exactly two dots, not consecutive, and they do not start
-// with a dot.
+// "PKGPATH.TYPE.NAME".  Both NAME and TYPE are simple Go identifiers.
+// Unlike the gc compiler, the external name does not indicate whether
+// this is a pointer method or a value method; a named type can not
+// have both a pointer and value method with the same name, so there
+// is no ambiguity.  PKGPATH is the package path of the package in
+// which TYPE is defined.  PKGPATH, TYPE, and NAME are encoded, and
+// cannot be empty or contain a dot or start with a digit.  These
+// external names contain exactly two dots, not consecutive, and they
+// do not start with a dot.
 //
 // It's uncommon, but the use of type literals with embedded fields
 // can cause us to have methods on unnamed types.  The external names
-// for these are also PKGPATH.TYPE.NAME, where TYPE is an
+// for these are also PKGPATH.TYPELIT.NAME, where TYPELIT is an
 // approximately readable version of the type literal, described
-// below.  As the type literal encoding always contains multiple dots,
-// these names always contain more than two dots.  Although the type
-// literal encoding contains dots, neither PKGPATH nor NAME can
-// contain a dot, and neither TYPE nor NAME can begin with a digit.
-// The effect is that PKGPATH is always the portion of the name before
-// the first dot and NAME is always the portion after the last dot.
-// There is no ambiguity as long as encoded type literals are
+// below.  A TYPELIT will always contain characters that cannot appear
+// in a Go identifier, so TYPELIT can never be confused with a TYPE
+// name.  There is no ambiguity as long as encoded type literals are
 // unambiguous.
 //
 // Also uncommon is an external name that must refer to a named type
 // the function with an added suffix "..f".
 //
 // A thunk for a go or defer statement is treated as a function whose
-// name is ".thunkNN" where NN is a sequence of digits (these
-// functions are never globally visible).  Thus the final name of a
-// thunk will be PKGPATH..thunkNN.
+// name is ".thunkNN", unencoded, where NN is a sequence of digits
+// (these functions are never globally visible).  Thus the final name
+// of a thunk will be PKGPATH..thunkNN (PKGPATH is encoded).
 //
-// An init function is treated as a function whose name is ".initNN"
-// where NN is a sequence of digits (these functions are never
-// globally visible).  Thus the final name of an init function will be
-// PKGPATH..initNN.
+// An init function is treated as a function whose name is ".initNN",
+// unencoded, where NN is a sequence of digits (these functions are
+// never globally visible).  Thus the final name of an init function
+// will be PKGPATH..initNN (PKGPATH is encoded).
 //
 // A nested function is given the name of outermost enclosing function
-// or method with an added suffix "..funcNN" where NN is a sequence of
-// digits.  Note that the function descriptor of a nested function, if
-// needed, will end with "..funcNN..f".
+// or method with an added suffix "..funcNN", unencoded, where NN is a
+// sequence of digits.  Note that the function descriptor of a nested
+// function, if needed, will end with "..funcNN..f".
 //
 // A recover thunk is the same as the name of the function with an
 // added suffix "..r".
 //
-// The name of a type descriptor for a named type is PKGPATH.TYPE..d.
+// The name of a type descriptor for a named type is
+// PKGPATH.TYPENAME..d (PKGPATH and TYPENAME are encoded).
 //
-// The name of a type descriptor for an unnamed type is type..TYPE.
-// That is, the string "type.." followed by the type literal encoding.
+// The name of a type descriptor for a pointer to a named type is
+// PKGPATH.TYPENAME..p (PKGPATH and TYPENAME are encoded).
+//
+// The name of a type descriptor for an unnamed type is type..TYPELIT.
+// That is, the string "type.." followed by the encoded type literal.
 // These names are common symbols, in the linker's sense of the word
 // common: in the final executable there is only one instance of the
-// type descriptor for a given unnamed type.  The type literal
-// encoding can never start with a digit or with 'u' or 'U'.
+// type descriptor for a given unnamed type.
 //
-// The name of the GC symbol for a named type is PKGPATH.TYPE..g.
+// The name of the GC symbol for a named type is PKGPATH.TYPE..g
+// (PKGPATH and TYPE are encoded).
 //
-// The name of the GC symbol for an unnamed type is typeg..TYPE.
+// The name of the GC symbol for an unnamed type is type..TYPELIT..g.
 // These are common symbols.
 //
 // The name of a ptrmask symbol is gcbits..B32 where B32 is an
-// encoding of the ptrmask bits using only ASCII letters without 'u'
-// or 'U'.  These are common symbols.
+// encoding of the ptrmask bits using only ASCII letters.  These are
+// common symbols.
 //
 // An interface method table for assigning the non-interface type TYPE
 // to the interface type ITYPE is named imt..ITYPE..TYPE.  If ITYPE or
-// TYPE is a named type, they are written as PKGPATH.TYPE.  Otherwise
-// they are written as a type literal.  An interface method table for
-// a pointer method set uses pimt instead of imt.
+// TYPE is a named type, they are written as PKGPATH.TYPE (where both
+// PKGPATH and TYPE are encoded).  Otherwise they are written as a
+// type literal.  An interface method table for a pointer method set
+// uses pimt instead of imt.
 //
 // The names of composite literal initializers, including the GC root
 // variable, are not referenced.  They must not conflict with any C
 // PKGPATH..import.  If a package doesn't need an init function, it
 // will have a dummy one, named ~PKGPATH.
 //
-// In each pacakge there is a list of all the type descriptors defined
+// In each package there is a list of all the type descriptors defined
 // in this package.  The name of the list is PKGPATH..types.
 //
 // In the main package it gathers all the type descriptor lists in a
 // The type literal encoding is not quite valid Go, as some aspects of
 // compiler generated types can not be represented.  For example,
 // incomparable struct types have an extra field "{x}".  Struct tags
-// are quoted inside curly braces, rather than introduce an encoding
-// for quotes.  Struct tags can contain any character, so any single
-// byte Unicode character that is not alphanumeric or underscore is
-// replaced with .xNN where NN is the hex encoding.
+// can contain any character, which will be underscore encoded as
+// usual.  In the unusual case of a curly brace or a backslash in a
+// struct tag, the brace or backslash will be backslash quoted, before
+// underscore encoding.
+//
+// The underscore encoding is, naturally, an underscore followed by
+// other characters.  As there are various characters that commonly
+// appear in type literals and in package paths, we have a set of
+// short encodings.  Then we have general encodings for other
+// characters.
 //
-// There is a simple encoding for glue characters in type literals:
-//   .0 - ' '
-//   .1 - '*'
-//   .2 - ';'
-//   .3 - ','
-//   .4 - '{'
-//   .5 - '}'
-//   .6 - '['
-//   .7 - ']'
-//   .8 - '('
-//   .9 - ')'
-// This is unambiguous as, although the type literal can contain a dot
-// as shown above, those dots are always followed by a name and names
-// can not begin with a digit.  A dot is always followed by a name or
-// a digit, and a type literal can neither start nor end with a dot,
-// so this never introduces consecutive dots.
+//   __ - '_'
+//   _0 - '.'
+//   _1 - '/'
+//   _2 - '*'
+//   _3 - ','
+//   _4 - '{'
+//   _5 - '}'
+//   _6 - '['
+//   _7 - ']'
+//   _8 - '('
+//   _9 - ')'
+//   _a - '"'
+//   _b - ' '
+//   _c - ';'
 //
-// Struct tags can contain any character, so they need special
-// treatment.  Alphanumerics, underscores, and Unicode characters that
-// require more than a single byte are left alone (Unicode characters
-// will be encoded later, as described below).  Other single bytes
-// characters are replace with .xNN where NN is the hex encoding.
+// Other non-alphanumeric ASCII characters are encoded as _xNN, where
+// NN is the hex value for the character.  If an encoded name would
+// otherwise start with a digit, this encoding is also used for the
+// leading digit.
 //
-// Since Go identifiers can contain Unicode characters, we must encode
-// them into ASCII.  We do this last, after the name is generated as
-// described above and after type literals are encoded.  To make the
-// encoding unambiguous, we introduce it with two consecutive dots.
-// This is followed by the letter u and four hex digits or the letter
-// U and eight digits, just as in the language only using ..u and ..U
-// instead of \u and \U.  The compiler also produces identifiers that
-// are qualified by package path, which means that there may also be ASCII
-// characters that are not assembler-friendly (ex: '=', '/'). The encoding
-// scheme translates such characters into the "..zNN" where NN is the
-// hex value for the character. Since before this encoding names can never
-// contain consecutive dots followed by 'z', 'u' or 'U', and after this
-// encoding "..z", "..u" and "..U" are followed by a known number of
-// characters, this is unambiguous.
+// Non-ASCII Unicode characters are encoded as _u and four hex digits
+// or _U and eight digits, just as in the language only using _u and
+// _U instead of \u and \U.
 //
 // Demangling these names is straightforward:
-//  - replace ..zXX with an ASCII character
-//  - replace ..uXXXX with a unicode character
-//  - replace ..UXXXXXXXX with a unicode character
-//  - replace .D, where D is a digit, with the character from the above
+//  - replace _xXX with an ASCII character
+//  - replace _uXXXX with a unicode character
+//  - replace _UXXXXXXXX with a unicode character
+//  - replace _C per the table above
 // That will get you as close as possible to a readable name.
 
-// Return the assembler name to use for an exported function, a
-// method, or a function/method declaration.  This is not called if
-// the function has been given an explicit name via a magic //extern
-// or //go:linkname comment.  GO_NAME is the name that appears in the
-// Go code.  PACKAGE is the package where the function is defined, and
-// is NULL for the package being compiled.  For a method, RTYPE is
+// Set BNAME to the name to use for an exported function, a method, or
+// a function/method declaration.  GO_NAME is the name that appears in
+// the Go code.  PACKAGE is the package where the function is defined,
+// and is NULL for the package being compiled.  For a method, RTYPE is
 // the method's receiver type; for a function, RTYPE is NULL.
 
-std::string
-Gogo::function_asm_name(const std::string& go_name, const Package* package,
-                       const Type* rtype)
+void
+Gogo::function_backend_name(const std::string& go_name,
+                           const Package* package, const Type* rtype,
+                           Backend_name* bname)
 {
-  std::string ret;
   if (rtype != NULL)
-    ret = rtype->deref()->mangled_name(this);
+    rtype->deref()->backend_name(this, bname);
   else if (package == NULL)
-    ret = this->pkgpath();
+    bname->add(this->pkgpath());
   else
-    ret = package->pkgpath();
-  ret.push_back('.');
-  // Check for special names that will break if we use
-  // Gogo::unpack_hidden_name.
-  if (Gogo::is_special_name(go_name))
-    ret.append(go_name);
+    bname->add(package->pkgpath());
+
+  size_t pos = Gogo::special_name_pos(go_name);
+  if (pos == std::string::npos)
+    bname->add(Gogo::unpack_hidden_name(go_name));
   else
-    ret.append(Gogo::unpack_hidden_name(go_name));
-  return go_encode_id(ret);
+    {
+      if (pos > 0)
+       bname->add(go_name.substr(0, pos));
+      bname->set_suffix(go_name.substr(pos));
+    }
 }
 
-// Return the name to use for a function descriptor.  These symbols
-// are globally visible.
+// Set BNAME to the name to use for a function descriptor.  These
+// symbols are globally visible.
 
-std::string
-Gogo::function_descriptor_name(Named_object* no)
+void
+Gogo::function_descriptor_backend_name(Named_object* no,
+                                      Backend_name* bname)
 {
-  if (no->is_function() && !no->func_value()->asm_name().empty())
-    return no->func_value()->asm_name() + "..f";
-  else if (no->is_function_declaration()
-          && !no->func_declaration_value()->asm_name().empty())
-    return no->func_declaration_value()->asm_name() + "..f";
-  std::string ret = this->function_asm_name(no->name(), no->package(), NULL);
-  ret.append("..f");
-  return ret;
+  if (no->is_function())
+    no->func_value()->backend_name(this, no, bname);
+  else if (no->is_function_declaration())
+    no->func_declaration_value()->backend_name(this, no, bname);
+  else
+    go_unreachable();
+  bname->append_suffix("..f");
 }
 
-// Return the name to use for a generated stub method.  MNAME is the
-// method name.  PACKAGE is the package where the type that needs this
-// stub method is defined.  These functions are globally visible.
-// Note that this is the function name that corresponds to the name
-// used for the method in Go source code, if this stub method were
-// written in Go.  The assembler name will be generated by
-// Gogo::function_asm_name, and because this is a method that name
-// will include the receiver type.
+// Return the name to use for a generated stub method.  A stub method
+// is used as the method table entry for a promoted method of an
+// embedded type.  MNAME is the method name.  PACKAGE is the package
+// where the type that needs this stub method is defined.  These
+// functions are globally visible.
+//
+// This returns a name that acts like a Go identifier, as though the
+// stub method were written in Go as an explicitly defined method that
+// simply calls the promoted method.  The name we return here will
+// eventually be passed to function_backend_name, which will return a
+// name that includes the receiver type.
+//
+// We construct a unique method name and append "..stub".
+// function_backend_name will look for the "..stub" and turn that into
+// an unencoded suffix.  The rest of the name will be encoded as
+// usual.
 
 std::string
 Gogo::stub_method_name(const Package* package, const std::string& mname)
@@ -279,56 +299,70 @@ Gogo::stub_method_name(const Package* package, const std::string& mname)
     return Gogo::unpack_hidden_name(mname) + "..stub";
 
   // We are creating a stub method for an unexported method of an
-  // imported embedded type.  We need to disambiguate the method name.
-  std::string ret = mpkgpath;
+  // imported embedded type.  A single type can have multiple promoted
+  // methods with the same unexported name, if it embeds types from
+  // different packages.  We need to disambiguate the method name.
+  // This produces an unambiguous name because even though MPKGPATH
+  // can be anything, we know that MNAME does not contain a dot.  The
+  // dot we return here, between MPKGPATH and MNAME, will wind up
+  // being underscore encoded.
+  std::string ret(mpkgpath);
   ret.push_back('.');
   ret.append(Gogo::unpack_hidden_name(mname));
   ret.append("..stub");
   return ret;
 }
 
-// Return the name of the hash function for TYPE.
+// Set BNAME to the name of the hash function for TYPE.
 
-std::string
-Gogo::hash_function_name(const Type* type)
+void
+Gogo::hash_function_name(const Type* type, Backend_name* bname)
 {
-  std::string tname = type->mangled_name(this);
-  return tname + "..hash";
+  if (type->named_type() != NULL)
+    type->backend_name(this, bname);
+  else
+    {
+      bname->add(this->pkgpath());
+      type->backend_name(this, bname);
+    }
+  bname->set_suffix("..hash");
 }
 
-// Return the name of the equal function for TYPE.  If NAME is not
-// NULL it is the name of the type.
+// Set BNAME to the name of the equal function for TYPE.  If NAME is
+// not NULL it is the name of the type.
 
-std::string
-Gogo::equal_function_name(const Type* type, const Named_type* name)
+void
+Gogo::equal_function_name(const Type* type, const Named_type* name,
+                         Backend_name* bname)
 {
-  const Type* rtype = type;
   if (name != NULL)
-    rtype = name;
-  std::string tname = rtype->mangled_name(this);
-  return tname + "..eq";
+    name->backend_name(this, bname);
+  else
+    {
+      bname->add(this->pkgpath());
+      type->backend_name(this, bname);
+    }
+  bname->set_suffix("..eq");
 }
 
-// Return the assembler name to use for a global variable.  GO_NAME is
-// the name that appears in the Go code.  PACKAGE is the package where
-// the variable is defined, and is NULL for the package being
-// compiled.
+// Set BNAME to the name to use for a global variable.  GO_NAME is the
+// name that appears in the Go code.  PACKAGE is the package where the
+// variable is defined, and is NULL for the package being compiled.
 
-std::string
-Gogo::global_var_asm_name(const std::string& go_name, const Package* package)
+void
+Gogo::global_var_backend_name(const std::string& go_name,
+                             const Package* package,
+                             Backend_name* bname)
 {
-  std::string ret;
   if (package == NULL)
-    ret = this->pkgpath();
+    bname->add(this->pkgpath());
   else
-    ret = package->pkgpath();
-  ret.append(1, '.');
-  ret.append(Gogo::unpack_hidden_name(go_name));
-  return go_encode_id(ret);
+    bname->add(package->pkgpath());
+  bname->add(Gogo::unpack_hidden_name(go_name));
 }
 
 // Return an erroneous name that indicates that an error has already
-// been reported.
+// been reported.  This name will act like a Go identifier.
 
 std::string
 Gogo::erroneous_name()
@@ -349,7 +383,10 @@ Gogo::is_erroneous_name(const std::string& name)
   return name.compare(0, 10, ".erroneous") == 0;
 }
 
-// Return a name for a thunk object.
+// Return a name for a thunk object.  This name will act like a Go
+// identifier.  The name returned here will eventually be passed to
+// function_backend_name, which will pull off the ..thunk as an
+// unencoded suffix.
 
 std::string
 Gogo::thunk_name()
@@ -358,7 +395,12 @@ Gogo::thunk_name()
   char thunk_name[50];
   snprintf(thunk_name, sizeof thunk_name, "..thunk%d", thunk_count);
   ++thunk_count;
-  std::string ret = this->pkgpath();
+  // We don't want to return a name that starts with a dot, as that
+  // will confuse Gogo::is_hidden_name.  And we don't want to change
+  // ..thunk, which fits our general theme and is used by code like
+  // runtime.Callers.  But the prefix doesn't matter, as the actual
+  // name will include the package path.
+  std::string ret = "go";
   return ret + thunk_name;
 }
 
@@ -368,13 +410,10 @@ bool
 Gogo::is_thunk(const Named_object* no)
 {
   const std::string& name(no->name());
-  size_t i = name.find("..thunk");
+  size_t i = name.rfind("..thunk");
   if (i == std::string::npos)
     return false;
-  for (i += 7; i < name.size(); ++i)
-    if (name[i] < '0' || name[i] > '9')
-      return false;
-  return true;
+  return Gogo::is_digits(name.substr(i + 7));
 }
 
 // Return the name to use for an init function.  There can be multiple
@@ -387,11 +426,12 @@ Gogo::init_function_name()
   char buf[30];
   snprintf(buf, sizeof buf, "..init%d", init_count);
   ++init_count;
-  std::string ret = this->pkgpath();
-  return ret + buf;
+  return this->pkgpath() + buf;
 }
 
-// Return the name to use for a nested function.
+// Return the name to use for a nested function.  This name acts like
+// a Go identifier.  This name will be rewritten by
+// Function::backend_name.
 
 std::string
 Gogo::nested_function_name(Named_object* enclosing)
@@ -420,7 +460,9 @@ Gogo::nested_function_name(Named_object* enclosing)
        enclosing->func_value()->type()->receiver();
       if (rcvr != NULL)
        {
-         prefix = rcvr->type()->mangled_name(this);
+         Backend_name bname;
+         rcvr->type()->backend_name(this, &bname);
+         prefix = bname.name();
          prefix.push_back('.');
        }
       prefix.append(Gogo::unpack_hidden_name(enclosing->name()));
@@ -460,7 +502,8 @@ Gogo::redefined_function_name()
 }
 
 // Return the name to use for a recover thunk for the function NAME.
-// If the function is a method, RTYPE is the receiver type.
+// If the function is a method, RTYPE is the receiver type.  This is a
+// name that acts like a Go identifier.
 
 std::string
 Gogo::recover_thunk_name(const std::string& name, const Type* rtype)
@@ -468,10 +511,12 @@ Gogo::recover_thunk_name(const std::string& name, const Type* rtype)
   std::string ret;
   if (rtype != NULL)
     {
-      ret = rtype->mangled_name(this);
+      Backend_name bname;
+      rtype->backend_name(this, &bname);
+      ret = bname.name();
       ret.append(1, '.');
     }
-  if (Gogo::is_special_name(name))
+  if (Gogo::special_name_pos(name) != std::string::npos)
     ret.append(name);
   else
     ret.append(Gogo::unpack_hidden_name(name));
@@ -504,8 +549,8 @@ Gogo::initializer_name()
   return buf;
 }
 
-// Return the name of the variable used to represent the zero value of
-// a map.  This is a globally visible common symbol.
+// Return the assembler name of the variable used to represent the
+// zero value of a map.  This is a globally visible common symbol.
 
 std::string
 Gogo::map_zero_value_name()
@@ -513,7 +558,9 @@ Gogo::map_zero_value_name()
   return "go..zerovalue";
 }
 
-// Return the name to use for the import control function.
+// Return the name to use for the import control function.  This name
+// is handled specially by Function::backend_name.  It is not encoded
+// further.
 
 const std::string&
 Gogo::get_init_fn_name()
@@ -550,7 +597,7 @@ Gogo::dummy_init_fn_name()
 // can be a real init function or a dummy one.
 
 std::string
-Gogo::pkgpath_from_init_fn_name(std::string name)
+Gogo::pkgpath_symbol_from_init_fn_name(std::string name)
 {
   go_assert(!name.empty());
   if (name[0] == '~')
@@ -561,60 +608,38 @@ Gogo::pkgpath_from_init_fn_name(std::string name)
   go_unreachable();
 }
 
-// Return a mangled name for a type.  These names appear in symbol
-// names in the assembler file for things like type descriptors and
-// methods.
+// Set BNAME to a name for a type to use in a symbol.  Return a name
+// for a type to use in a symbol.  These names appear in symbol names
+// in the assembler file for things like type descriptors and methods.
 
-std::string
-Type::mangled_name(Gogo* gogo) const
+void
+Type::backend_name(Gogo* gogo, Backend_name* bname) const
 {
-  std::string ret;
-
-  // The do_mangled_name virtual function will set RET to the mangled
-  // name before glue character mapping.
-  this->do_mangled_name(gogo, &ret);
-
-  // Type descriptor names and interface method table names use a ".."
-  // before the mangled name of a type, so to avoid ambiguity the
-  // mangled name must not start with 'u' or 'U' or a digit.
-  go_assert((ret[0] < '0' || ret[0] > '9') && ret[0] != ' ');
-  if (ret[0] == 'u' || ret[0] == 'U')
-    ret = " " + ret;
-
-  // Map glue characters as described above.
-
-  // The mapping is only unambiguous if there is no .DIGIT in the
-  // string, so check that.
-  for (size_t i = ret.find('.');
-       i != std::string::npos;
-       i = ret.find('.', i + 1))
+  // Special case top level named types to get nicer name encodings
+  // for this common case.
+  const Named_type* nt = this->unalias()->named_type();
+  if (nt != NULL && !nt->is_builtin())
     {
-      if (i + 1 < ret.size())
+      unsigned int index;
+      if (nt->in_function(&index) == NULL)
        {
-         char c = ret[i + 1];
-         go_assert(c < '0' || c > '9');
+         const Named_object* no = nt->named_object();
+         if (no->package() == NULL)
+           bname->add(gogo->pkgpath());
+         else
+           bname->add(no->package()->pkgpath());
+         bname->add(Gogo::unpack_hidden_name(no->name()));
+         return;
        }
     }
 
-  // The order of these characters is the replacement code.
-  const char * const replace = " *;,{}[]()";
+  std::string name;
 
-  const size_t rlen = strlen(replace);
-  char buf[2];
-  buf[0] = '.';
-  for (size_t ri = 0; ri < rlen; ++ri)
-    {
-      buf[1] = '0' + ri;
-      while (true)
-       {
-         size_t i = ret.find(replace[ri]);
-         if (i == std::string::npos)
-           break;
-         ret.replace(i, 1, buf, 2);
-       }
-    }
+  // The do_symbol_name virtual function will set RET to the mangled
+  // name before encoding.
+  this->do_mangled_name(gogo, &name);
 
-  return ret;
+  bname->add(name);
 }
 
 // The mangled name is implemented as a method on each instance of
@@ -701,12 +726,7 @@ Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
          else
            ret->push_back(',');
          if (this->is_varargs_ && p + 1 == params->end())
-           {
-             // We can't use "..." here because the mangled name
-             // might start with 'u' or 'U', which would be ambiguous
-             // with the encoding of Unicode characters.
-             ret->append(",,,");
-           }
+           ret->append("...");
          this->append_mangled_name(p->type(), gogo, ret);
        }
     }
@@ -776,15 +796,15 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
          if (p->is_anonymous()
              && p->type()->named_type() != NULL
              && p->type()->named_type()->is_alias())
-           p->type()->named_type()->append_mangled_type_name(gogo, true, ret);
+           p->type()->named_type()->append_symbol_type_name(gogo, true, ret);
          else
            this->append_mangled_name(p->type(), gogo, ret);
 
          if (p->has_tag())
            {
              // Use curly braces around a struct tag, since they are
-             // unambiguous here and we have no encoding for
-             // quotation marks.
+             // unambiguous here and struct tags rarely contain curly
+             // braces.
              ret->push_back('{');
              ret->append(go_mangle_struct_tag(p->tag()));
              ret->push_back('}');
@@ -837,10 +857,10 @@ void
 Channel_type::do_mangled_name(Gogo* gogo, std::string* ret) const
 {
   if (!this->may_send_)
-    ret->append("{}");
+    ret->append("<-");
   ret->append("chan");
   if (!this->may_receive_)
-    ret->append("{}");
+    ret->append("<-");
   ret->push_back(' ');
   this->append_mangled_name(this->element_type_, gogo, ret);
 }
@@ -883,7 +903,7 @@ Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
 void
 Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
 {
-  this->append_mangled_type_name(gogo, false, ret);
+  this->append_symbol_type_name(gogo, false, ret);
 }
 
 void
@@ -903,13 +923,13 @@ Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
     }
 }
 
-// Append the mangled name for a named type to RET.  For an alias we
+// Append the symbol name for a named type to RET.  For an alias we
 // normally use the real name, but if USE_ALIAS is true we use the
 // alias name itself.
 
 void
-Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
-                                    std::string* ret) const
+Named_type::append_symbol_type_name(Gogo* gogo, bool use_alias,
+                                   std::string* ret) const
 {
   if (this->is_error_)
     return;
@@ -933,7 +953,11 @@ Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
          const Typed_identifier* rcvr =
            this->in_function_->func_value()->type()->receiver();
          if (rcvr != NULL)
-           ret->append(rcvr->type()->deref()->mangled_name(gogo));
+           {
+             Backend_name bname;
+             rcvr->type()->deref()->backend_name(gogo, &bname);
+             ret->append(bname.name());
+           }
          else if (this->in_function_->package() == NULL)
            ret->append(gogo->pkgpath());
          else
@@ -956,23 +980,46 @@ Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
   if (this->in_function_ != NULL && this->in_function_index_ > 0)
     {
       char buf[30];
-      snprintf(buf, sizeof buf, "..i%u", this->in_function_index_);
+      snprintf(buf, sizeof buf, ".i%u", this->in_function_index_);
       ret->append(buf);
     }
 }
 
-// Return the name for the type descriptor symbol for TYPE.  This can
-// be a global, common, or local symbol, depending.  NT is not NULL if
-// it is the name to use.
+// Given a name which may or may not have been hidden, append the
+// appropriate version of the name to the result string.
 
-std::string
-Gogo::type_descriptor_name(const Type* type, Named_type* nt)
+void
+Gogo::append_possibly_hidden_name(std::string *result, const std::string& name)
+{
+  if (!Gogo::is_hidden_name(name))
+    *result += name;
+  else
+    *result += name.substr(1);
+}
+
+// Set BNAME to the name for the type descriptor symbol for TYPE.
+// This can be a global, common, or local symbol, depending.  NT is
+// not NULL if it is the name to use.
+
+void
+Gogo::type_descriptor_backend_name(const Type* type, Named_type* nt,
+                                  Backend_name* bname)
 {
   // The type descriptor symbol for the unsafe.Pointer type is defined
   // in libgo/runtime/go-unsafe-pointer.c, so just use a reference to
   // that symbol for all unsafe pointer types.
   if (type->is_unsafe_pointer_type())
-    return "unsafe.Pointer..d";
+    {
+      bname->set_asm_name("unsafe.Pointer..d");
+      return;
+    }
+
+  bool is_pointer = false;
+  if (nt == NULL && type->points_to() != NULL)
+    {
+      nt = type->points_to()->named_type();
+      is_pointer = true;
+    }
 
   if (nt == NULL)
     {
@@ -981,63 +1028,28 @@ Gogo::type_descriptor_name(const Type* type, Named_type* nt)
       // using a named type, like "int".
       go_assert(!type->is_basic_type());
 
-      return "type.." + type->mangled_name(this);
+      type->backend_name(this, bname);
+      bname->set_prefix("type..");
     }
-
-  std::string ret;
-  Named_object* no = nt->named_object();
-  unsigned int index;
-  const Named_object* in_function = nt->in_function(&index);
-  if (nt->is_builtin())
-    go_assert(in_function == NULL);
   else
     {
-      if (in_function != NULL)
-       {
-         const Typed_identifier* rcvr =
-           in_function->func_value()->type()->receiver();
-         if (rcvr != NULL)
-           ret.append(rcvr->type()->deref()->mangled_name(this));
-         else if (in_function->package() == NULL)
-           ret.append(this->pkgpath());
-         else
-           ret.append(in_function->package()->pkgpath());
-         ret.push_back('.');
-         ret.append(Gogo::unpack_hidden_name(in_function->name()));
-         ret.push_back('.');
-       }
-
-      if (no->package() == NULL)
-       ret.append(this->pkgpath());
-      else
-       ret.append(no->package()->pkgpath());
-      ret.push_back('.');
+      nt->backend_name(this, bname);
+      bname->set_suffix(is_pointer ? "..p" : "..d");
     }
-
-  Gogo::append_possibly_hidden_name(&ret, no->name());
-
-  if (in_function != NULL && index > 0)
-    {
-      char buf[30];
-      snprintf(buf, sizeof buf, "..i%u", index);
-      ret.append(buf);
-    }
-
-  ret.append("..d");
-
-  return ret;
 }
 
 // Return the name of the type descriptor list symbol of a package.
+// This is passed directly to the backend without further encoding.
 
 std::string
-Gogo::type_descriptor_list_symbol(const std::string& pkgpath)
+Gogo::type_descriptor_list_symbol(const std::string& pkgpath_symbol)
 {
-  return pkgpath + "..types";
+  return pkgpath_symbol + "..types";
 }
 
 // Return the name of the list of all type descriptor lists.  This is
-// only used in the main package.
+// only used in the main package.  This is passed directly to the
+// backend without further encoding.
 
 std::string
 Gogo::typelists_symbol()
@@ -1045,24 +1057,30 @@ Gogo::typelists_symbol()
   return "go..typelists";
 }
 
-// Return the name for the GC symbol for a type.  This is used to
-// initialize the gcdata field of a type descriptor.  This is a local
-// name never referenced outside of this assembly file.  (Note that
-// some type descriptors will initialize the gcdata field with a name
-// generated by ptrmask_symbol_name rather than this method.)
+// Return the assembler name for the GC symbol for a type.  This is
+// used to initialize the gcdata field of a type descriptor.  This is
+// a local name never referenced outside of this assembly file.  (Note
+// that some type descriptors will initialize the gcdata field with a
+// name generated by ptrmask_symbol_name rather than this method.)
+// This is passed directly to the backend without further encoding.
 
 std::string
 Gogo::gc_symbol_name(Type* type)
 {
-  return this->type_descriptor_name(type, type->named_type()) + "..g";
+  Backend_name bname;
+  this->type_descriptor_backend_name(type, type->named_type(), &bname);
+  bname.append_suffix("..g");
+  return bname.asm_name();
 }
 
-// Return the name for a ptrmask variable.  PTRMASK_SYM_NAME is a
-// base32 string encoding the ptrmask (as returned by Ptrmask::symname
-// in types.cc).  This name is used to intialize the gcdata field of a
-// type descriptor.  These names are globally visible.  (Note that
-// some type descriptors will initialize the gcdata field with a name
-// generated by gc_symbol_name rather than this method.)
+// Return the assembler name for a ptrmask variable.  PTRMASK_SYM_NAME
+// is a base32 string encoding the ptrmask (as returned by
+// Ptrmask::symname in types.cc).  This name is used to intialize the
+// gcdata field of a type descriptor.  These names are globally
+// visible.  (Note that some type descriptors will initialize the
+// gcdata field with a name generated by gc_symbol_name rather than
+// this method.)  This is passed directly to the backend without
+// further encoding.
 
 std::string
 Gogo::ptrmask_symbol_name(const std::string& ptrmask_sym_name)
@@ -1070,34 +1088,123 @@ Gogo::ptrmask_symbol_name(const std::string& ptrmask_sym_name)
   return "gcbits.." + ptrmask_sym_name;
 }
 
-// Return the name to use for an interface method table used for the
-// ordinary type TYPE converted to the interface type ITYPE.
+// Return the assembler name to use for an interface method table used
+// for the ordinary type TYPE converted to the interface type ITYPE.
 // IS_POINTER is true if this is for the method set for a pointer
-// receiver.
+// receiver.  This is passed directly to the backend without further
+// encoding.
 
 std::string
 Gogo::interface_method_table_name(Interface_type* itype, Type* type,
                                  bool is_pointer)
 {
+  Backend_name iname;
+  itype->backend_name(this, &iname);
+  Backend_name tname;
+  type->backend_name(this, &tname);
   return ((is_pointer ? "pimt.." : "imt..")
-         + itype->mangled_name(this)
+         + iname.asm_name()
          + ".."
-         + type->mangled_name(this));
+         + tname.asm_name());
 }
 
-// Return whether NAME is a special name that can not be passed to
-// unpack_hidden_name.  This is needed because various special names
-// use "..SUFFIX", but unpack_hidden_name just looks for '.'.
+// If NAME is a special name with a ".." suffix, return the position
+// of that suffix.  This is needed because various special names use
+// "..SUFFIX", but unpack_hidden_name just looks for '.', and because
+// we don't want to encode the suffix.
+
+size_t
+Gogo::special_name_pos(const std::string& name)
+{
+  size_t pos = name.rfind("..");
+  if (pos == std::string::npos)
+    return pos;
+  std::string suffix(name.substr(pos));
+  if (suffix == "..hash"
+      || suffix == "..eq"
+      || suffix == "..stub"
+      || suffix == "..d"
+      || suffix == "..f"
+      || suffix == "..r"
+      || suffix == "..import")
+    return pos;
+  if ((suffix.compare(2, 4, "func") == 0
+       || suffix.compare(2, 4, "init") == 0)
+      && Gogo::is_digits(suffix.substr(6)))
+    return pos;
+  if (suffix.compare(2, 5, "thunk") == 0
+      && Gogo::is_digits(suffix.substr(7)))
+    return pos;
+  return std::string::npos;
+}
+
+// Return whether the string is non-empty and contains only digits.
 
 bool
-Gogo::is_special_name(const std::string& name)
+Gogo::is_digits(const std::string& s)
+{
+  if (s.empty())
+    return false;
+  for (size_t i = 0; i < s.size(); ++i)
+    if (s[i] < '0' || s[i] > '9')
+      return false;
+  return true;
+}
+
+// Class Backend_name.
+
+// Get the user visible name.
+
+std::string
+Backend_name::name() const
+{
+  if (this->is_asm_name_)
+    return this->components_[0];
+  std::string ret;
+  if (this->prefix_ != NULL)
+    ret.append(this->prefix_);
+  for (int i = 0; i < this->count_; i++)
+    {
+      if (i > 0)
+       ret.push_back('.');
+      ret.append(this->components_[i]);
+    }
+  if (!this->suffix_.empty())
+    ret.append(this->suffix_);
+  return ret;
+}
+
+// Get the assembler name.
+
+std::string
+Backend_name::asm_name() const
+{
+  if (this->is_asm_name_)
+    return this->components_[0];
+  std::string ret;
+  if (this->prefix_ != NULL)
+    ret.append(this->prefix_);
+  for (int i = 0; i < this->count_; i++)
+    {
+      if (i > 0)
+       ret.push_back('.');
+      ret.append(go_encode_id(this->components_[i]));
+    }
+  if (!this->suffix_.empty())
+    ret.append(this->suffix_);
+  return ret;
+}
+
+// Get the assembler name, or the empty string if it is the same as
+// the user visible name.
+
+std::string
+Backend_name::optional_asm_name() const
 {
-  return (name.find("..hash") != std::string::npos
-         || name.find("..eq") != std::string::npos
-         || name.find("..stub") != std::string::npos
-         || name.find("..func") != std::string::npos
-         || name.find("..r") != std::string::npos
-         || name.find("..init") != std::string::npos
-         || name.find("..thunk") != std::string::npos
-         || name.find("..import") != std::string::npos);
+  if (this->is_asm_name_)
+    return "";
+  for (int i = 0; i < this->count_; i++)
+    if (go_id_needs_encoding(this->components_[i]))
+      return this->asm_name();
+  return "";
 }
index 0796cbaadceadedc779e90171f9920af03c58da5..b608766cdaf88236e81df5fc99a72eca239a5204 100644 (file)
@@ -83,7 +83,7 @@ DEF_GO_RUNTIME(MAKEMAP64, "runtime.makemap64", P3(TYPE, INT64, POINTER),
                R1(MAP))
 
 // Make a map with no hint, or a small constant hint.
-DEF_GO_RUNTIME(MAKEMAP_SMALL, "runtime.makemap_small", P0(), R1(MAP))
+DEF_GO_RUNTIME(MAKEMAP_SMALL, "runtime.makemap__small", P0(), R1(MAP))
 
 // Build a map from a composite literal.
 DEF_GO_RUNTIME(CONSTRUCT_MAP, "__go_construct_map",
@@ -95,19 +95,19 @@ DEF_GO_RUNTIME(MAPACCESS1, "runtime.mapaccess1", P3(TYPE, MAP, POINTER),
               R1(POINTER))
 
 // Look up a uint32 key in a map.
-DEF_GO_RUNTIME(MAPACCESS1_FAST32, "runtime.mapaccess1_fast32",
+DEF_GO_RUNTIME(MAPACCESS1_FAST32, "runtime.mapaccess1__fast32",
                P3(TYPE, MAP, UINT32), R1(POINTER))
 
 // Look up a uint64 key in a map.
-DEF_GO_RUNTIME(MAPACCESS1_FAST64, "runtime.mapaccess1_fast64",
+DEF_GO_RUNTIME(MAPACCESS1_FAST64, "runtime.mapaccess1__fast64",
                P3(TYPE, MAP, UINT64), R1(POINTER))
 
 // Look up a string key in a map.
-DEF_GO_RUNTIME(MAPACCESS1_FASTSTR, "runtime.mapaccess1_faststr",
+DEF_GO_RUNTIME(MAPACCESS1_FASTSTR, "runtime.mapaccess1__faststr",
                P3(TYPE, MAP, STRING), R1(POINTER))
 
 // Look up a key in a map when the value is large.
-DEF_GO_RUNTIME(MAPACCESS1_FAT, "runtime.mapaccess1_fat",
+DEF_GO_RUNTIME(MAPACCESS1_FAT, "runtime.mapaccess1__fat",
               P4(TYPE, MAP, POINTER, POINTER), R1(POINTER))
 
 // Look up a key in a map returning the value and whether it is
@@ -117,22 +117,22 @@ DEF_GO_RUNTIME(MAPACCESS2, "runtime.mapaccess2", P3(TYPE, MAP, POINTER),
 
 // Look up a uint32 key in a map returning the value and whether
 // it is present.
-DEF_GO_RUNTIME(MAPACCESS2_FAST32, "runtime.mapaccess2_fast32",
+DEF_GO_RUNTIME(MAPACCESS2_FAST32, "runtime.mapaccess2__fast32",
                P3(TYPE, MAP, UINT32), R2(POINTER, BOOL))
 
 // Look up a uint64 key in a map returning the value and whether
 // it is present.
-DEF_GO_RUNTIME(MAPACCESS2_FAST64, "runtime.mapaccess2_fast64",
+DEF_GO_RUNTIME(MAPACCESS2_FAST64, "runtime.mapaccess2__fast64",
                P3(TYPE, MAP, UINT64), R2(POINTER, BOOL))
 
 // Look up a string key in a map returning the value and whether
 // it is present.
-DEF_GO_RUNTIME(MAPACCESS2_FASTSTR, "runtime.mapaccess2_faststr",
+DEF_GO_RUNTIME(MAPACCESS2_FASTSTR, "runtime.mapaccess2__faststr",
                P3(TYPE, MAP, STRING), R2(POINTER, BOOL))
 
 // Look up a key in a map, returning the value and whether it is
 // present, when the value is large.
-DEF_GO_RUNTIME(MAPACCESS2_FAT, "runtime.mapaccess2_fat",
+DEF_GO_RUNTIME(MAPACCESS2_FAT, "runtime.mapaccess2__fat",
               P4(TYPE, MAP, POINTER, POINTER), R2(POINTER, BOOL))
 
 // Assignment to a key in a map.
@@ -140,38 +140,38 @@ DEF_GO_RUNTIME(MAPASSIGN, "runtime.mapassign", P3(TYPE, MAP, POINTER),
               R1(POINTER))
 
 // Assignment to a uint32 key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FAST32, "runtime.mapassign_fast32",
+DEF_GO_RUNTIME(MAPASSIGN_FAST32, "runtime.mapassign__fast32",
                P3(TYPE, MAP, UINT32), R1(POINTER))
 
 // Assignment to a uint64 key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FAST64, "runtime.mapassign_fast64",
+DEF_GO_RUNTIME(MAPASSIGN_FAST64, "runtime.mapassign__fast64",
                P3(TYPE, MAP, UINT64), R1(POINTER))
 
 // Assignment to a 32-bit pointer key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FAST32PTR, "runtime.mapassign_fast32ptr",
+DEF_GO_RUNTIME(MAPASSIGN_FAST32PTR, "runtime.mapassign__fast32ptr",
                P3(TYPE, MAP, POINTER), R1(POINTER))
 
 // Assignment to a 64-bit pointer key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FAST64PTR, "runtime.mapassign_fast64ptr",
+DEF_GO_RUNTIME(MAPASSIGN_FAST64PTR, "runtime.mapassign__fast64ptr",
                P3(TYPE, MAP, POINTER), R1(POINTER))
 
 // Assignment to a string key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FASTSTR, "runtime.mapassign_faststr",
+DEF_GO_RUNTIME(MAPASSIGN_FASTSTR, "runtime.mapassign__faststr",
                P3(TYPE, MAP, STRING), R1(POINTER))
 
 // Delete a key from a map.
 DEF_GO_RUNTIME(MAPDELETE, "runtime.mapdelete", P3(TYPE, MAP, POINTER), R0())
 
 // Delete a uint32 key from a map.
-DEF_GO_RUNTIME(MAPDELETE_FAST32, "runtime.mapdelete_fast32",
+DEF_GO_RUNTIME(MAPDELETE_FAST32, "runtime.mapdelete__fast32",
                P3(TYPE, MAP, UINT32), R0())
 
 // Delete a uint64 key from a map.
-DEF_GO_RUNTIME(MAPDELETE_FAST64, "runtime.mapdelete_fast64",
+DEF_GO_RUNTIME(MAPDELETE_FAST64, "runtime.mapdelete__fast64",
                P3(TYPE, MAP, UINT64), R0())
 
 // Delete a string key from a map.
-DEF_GO_RUNTIME(MAPDELETE_FASTSTR, "runtime.mapdelete_faststr",
+DEF_GO_RUNTIME(MAPDELETE_FASTSTR, "runtime.mapdelete__faststr",
                P3(TYPE, MAP, STRING), R0())
 
 // Begin a range over a map.
index f3bcf2eabd47d5def30161b1bf703b5bd4e96989..c4570b41a71bd7707b947d5a5d272c9446cf6858 100644 (file)
@@ -1342,19 +1342,21 @@ Type::make_type_descriptor_var(Gogo* gogo)
 
       Type* td_type = Type::make_type_descriptor_type();
       Btype* td_btype = td_type->get_backend(gogo);
-      std::string name = gogo->type_descriptor_name(this, nt);
-      std::string asm_name(go_selectively_encode_id(name));
+      Backend_name bname;
+      gogo->type_descriptor_backend_name(this, nt, &bname);
       this->type_descriptor_var_ =
-         gogo->backend()->immutable_struct_reference(name, asm_name,
-                                                     td_btype,
-                                                     bloc);
+       gogo->backend()->immutable_struct_reference(bname.name(),
+                                                   bname.optional_asm_name(),
+                                                   td_btype,
+                                                   bloc);
 
       if (phash != NULL)
        *phash = this->type_descriptor_var_;
       return;
     }
 
-  std::string var_name = gogo->type_descriptor_name(this, nt);
+  Backend_name bname;
+  gogo->type_descriptor_backend_name(this, nt, &bname);
 
   // Build the contents of the type descriptor.
   Expression* initializer = this->do_type_descriptor(gogo, NULL);
@@ -1366,11 +1368,11 @@ Type::make_type_descriptor_var(Gogo* gogo)
   const Package* dummy;
   if (this->type_descriptor_defined_elsewhere(nt, &dummy))
     {
-      std::string asm_name(go_selectively_encode_id(var_name));
       this->type_descriptor_var_ =
-         gogo->backend()->immutable_struct_reference(var_name, asm_name,
-                                                     initializer_btype,
-                                                     loc);
+       gogo->backend()->immutable_struct_reference(bname.name(),
+                                                   bname.optional_asm_name(),
+                                                   initializer_btype,
+                                                   loc);
       if (phash != NULL)
        *phash = this->type_descriptor_var_;
       return;
@@ -1399,10 +1401,10 @@ Type::make_type_descriptor_var(Gogo* gogo)
   // ensure that type_descriptor_pointer will work if called while
   // converting INITIALIZER.
 
-  std::string asm_name(go_selectively_encode_id(var_name));
   this->type_descriptor_var_ =
-      gogo->backend()->immutable_struct(var_name, asm_name, false, is_common,
-                                     initializer_btype, loc);
+    gogo->backend()->immutable_struct(bname.name(), bname.optional_asm_name(),
+                                     false, is_common, initializer_btype,
+                                     loc);
   if (phash != NULL)
     *phash = this->type_descriptor_var_;
 
@@ -1411,7 +1413,7 @@ Type::make_type_descriptor_var(Gogo* gogo)
   Bexpression* binitializer = initializer->get_backend(&context);
 
   gogo->backend()->immutable_struct_set_init(this->type_descriptor_var_,
-                                            var_name, false, is_common,
+                                            bname.name(), false, is_common,
                                             initializer_btype, loc,
                                             binitializer);
 
@@ -1924,19 +1926,20 @@ Type::build_hash_function(Gogo* gogo, int64_t size, Function_type* hash_fntype)
       return ins.first->second;
     }
 
-  std::string hash_name = gogo->hash_function_name(type);
+  Backend_name bname;
+  gogo->hash_function_name(type, &bname);
 
   Location bloc = Linemap::predeclared_location();
 
-  Named_object* hash_fn = gogo->declare_package_function(hash_name,
+  Named_object* hash_fn = gogo->declare_package_function(bname.name(),
                                                         hash_fntype, bloc);
 
   ins.first->second = hash_fn;
 
   if (gogo->in_global_scope())
-    type->write_hash_function(gogo, size, hash_name, hash_fntype);
+    type->write_hash_function(gogo, size, &bname, hash_fntype);
   else
-    gogo->queue_hash_function(type, size, hash_name, hash_fntype);
+    gogo->queue_hash_function(type, size, &bname, hash_fntype);
 
   return hash_fn;
 }
@@ -1944,8 +1947,7 @@ Type::build_hash_function(Gogo* gogo, int64_t size, Function_type* hash_fntype)
 // Write the hash function for a type that needs it written specially.
 
 void
-Type::write_hash_function(Gogo* gogo, int64_t size,
-                         const std::string& hash_name,
+Type::write_hash_function(Gogo* gogo, int64_t size, const Backend_name* bname,
                          Function_type* hash_fntype)
 {
   Location bloc = Linemap::predeclared_location();
@@ -1958,8 +1960,9 @@ Type::write_hash_function(Gogo* gogo, int64_t size,
 
   go_assert(this->is_comparable());
 
-  Named_object* hash_fn = gogo->start_function(hash_name, hash_fntype, false,
-                                              bloc);
+  Named_object* hash_fn = gogo->start_function(bname->name(), hash_fntype,
+                                              false, bloc);
+  hash_fn->func_value()->set_asm_name(bname->asm_name());
   hash_fn->func_value()->set_is_type_specific_function();
   gogo->start_block(bloc);
 
@@ -2245,7 +2248,8 @@ Type::build_equal_function(Gogo* gogo, Named_type* name, int64_t size,
       return ins.first->second;
     }
 
-  std::string equal_name = gogo->equal_function_name(this, name);
+  Backend_name bname;
+  gogo->equal_function_name(this, name, &bname);
 
   Location bloc = Linemap::predeclared_location();
 
@@ -2255,19 +2259,21 @@ Type::build_equal_function(Gogo* gogo, Named_type* name, int64_t size,
 
   Named_object* equal_fn;
   if (is_defined_elsewhere)
-    equal_fn = Named_object::make_function_declaration(equal_name, package,
+    equal_fn = Named_object::make_function_declaration(bname.name(), package,
                                                       equal_fntype, bloc);
   else
-    equal_fn = gogo->declare_package_function(equal_name, equal_fntype, bloc);
+    equal_fn = gogo->declare_package_function(bname.name(), equal_fntype, bloc);
 
   ins.first->second = equal_fn;
 
-  if (!is_defined_elsewhere)
+  if (is_defined_elsewhere)
+    equal_fn->func_declaration_value()->set_asm_name(bname.asm_name());
+  else
     {
       if (gogo->in_global_scope())
-       this->write_equal_function(gogo, name, size, equal_name, equal_fntype);
+       this->write_equal_function(gogo, name, size, &bname, equal_fntype);
       else
-       gogo->queue_equal_function(this, name, size, equal_name, equal_fntype);
+       gogo->queue_equal_function(this, name, size, &bname, equal_fntype);
     }
 
   return equal_fn;
@@ -2278,7 +2284,7 @@ Type::build_equal_function(Gogo* gogo, Named_type* name, int64_t size,
 
 void
 Type::write_equal_function(Gogo* gogo, Named_type* name, int64_t size,
-                          const std::string& equal_name,
+                          const Backend_name* bname,
                           Function_type* equal_fntype)
 {
   Location bloc = Linemap::predeclared_location();
@@ -2291,8 +2297,9 @@ Type::write_equal_function(Gogo* gogo, Named_type* name, int64_t size,
 
   go_assert(this->is_comparable());
 
-  Named_object* equal_fn = gogo->start_function(equal_name, equal_fntype,
+  Named_object* equal_fn = gogo->start_function(bname->name(), equal_fntype,
                                                false, bloc);
+  equal_fn->func_value()->set_asm_name(bname->asm_name());
   equal_fn->func_value()->set_is_type_specific_function();
   gogo->start_block(bloc);
 
@@ -2671,9 +2678,8 @@ Type::make_gc_symbol_var(Gogo* gogo)
   const Package* dummy;
   if (this->type_descriptor_defined_elsewhere(nt, &dummy))
     {
-      std::string asm_name(go_selectively_encode_id(sym_name));
       this->gc_symbol_var_ =
-          gogo->backend()->implicit_variable_reference(sym_name, asm_name,
+          gogo->backend()->implicit_variable_reference(sym_name, "",
                                                        sym_btype);
       if (phash != NULL)
        *phash = this->gc_symbol_var_;
@@ -2699,10 +2705,9 @@ Type::make_gc_symbol_var(Gogo* gogo)
   // Since we are building the GC symbol in this package, we must create the
   // variable before converting the initializer to its backend representation
   // because the initializer may refer to the GC symbol for this type.
-  std::string asm_name(go_selectively_encode_id(sym_name));
   this->gc_symbol_var_ =
-      gogo->backend()->implicit_variable(sym_name, asm_name,
-                                        sym_btype, false, true, is_common, 0);
+      gogo->backend()->implicit_variable(sym_name, "", sym_btype, false, true,
+                                        is_common, 0);
   if (phash != NULL)
     *phash = this->gc_symbol_var_;
 
@@ -2876,14 +2881,17 @@ 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. 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.
+// 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.  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
 {
@@ -2911,7 +2919,7 @@ Ptrmask::symname() const
       bits = &shabits;
     }
 
-  const char chars[33] = "abcdefghijklmnopqrstvwxyzABCDEFG";
+  const char chars[33] = "abcdefghijklmnopqrstuvwxyzABCDEF";
   go_assert(chars[32] == '\0');
   std::string ret(prefix);
   unsigned int b = 0;
@@ -2995,9 +3003,8 @@ Type::gc_ptrmask_var(Gogo* gogo, int64_t ptrsize, int64_t ptrdata)
   context.set_is_const();
   Bexpression* bval = val->get_backend(&context);
 
-  std::string asm_name(go_selectively_encode_id(sym_name));
   Btype *btype = val->type()->get_backend(gogo);
-  Bvariable* ret = gogo->backend()->implicit_variable(sym_name, asm_name,
+  Bvariable* ret = gogo->backend()->implicit_variable(sym_name, "",
                                                      btype, false, true,
                                                      true, 0);
   gogo->backend()->implicit_variable_set_init(ret, sym_name, btype, false,
@@ -8092,11 +8099,9 @@ Map_type::backend_zero_value(Gogo* gogo)
   Btype* barray_type = gogo->backend()->array_type(buint8_type, blength);
 
   std::string zname = Map_type::zero_value->name();
-  std::string asm_name(go_selectively_encode_id(zname));
   Bvariable* zvar =
-      gogo->backend()->implicit_variable(zname, asm_name,
-                                         barray_type, false, false, true,
-                                        Map_type::zero_value_align);
+      gogo->backend()->implicit_variable(zname, "", barray_type, false, false,
+                                        true, Map_type::zero_value_align);
   gogo->backend()->implicit_variable_set_init(zvar, zname, barray_type,
                                              false, false, true, NULL);
   return zvar;
index 9ac851699d26f0497503f8b480f7c842c7966f04..5965d5a3fdeccf734b4998a81c07db6a582d3d72 100644 (file)
@@ -49,6 +49,7 @@ class Function;
 class Translate_context;
 class Export;
 class Import;
+class Backend_name;
 class Btype;
 class Bexpression;
 class Bvariable;
@@ -1008,11 +1009,11 @@ class Type
   std::string
   reflection(Gogo*) const;
 
-  // Return a mangled name for the type.  This is a name which can be
-  // used in assembler code.  Identical types should have the same
-  // manged name.
-  std::string
-  mangled_name(Gogo*) const;
+  // Add the backend name for the type to BNAME.  This will add one or
+  // two name components.  Identical types should have the same
+  // backend name.
+  void
+  backend_name(Gogo*, Backend_name* bname) const;
 
   // If the size of the type can be determined, set *PSIZE to the size
   // in bytes and return true.  Otherwise, return false.  This queries
@@ -1066,12 +1067,11 @@ class Type
   // Write the equal function for a type.
   void
   write_equal_function(Gogo*, Named_type*, int64_t size,
-                      const std::string& equal_name,
-                      Function_type* equal_fntype);
+                      const Backend_name*, Function_type* equal_fntype);
 
   // Write the hash function for a type.
   void
-  write_hash_function(Gogo*, int64_t size, const std::string& hash_name,
+  write_hash_function(Gogo*, int64_t size, const Backend_name*,
                      Function_type* hash_fntype);
 
   // Return the alignment required by the memequalN function.
@@ -3557,10 +3557,10 @@ class Named_type : public Type
   void
   append_reflection_type_name(Gogo*, bool use_alias, std::string*) const;
 
-  // Append the mangled type name as for Type::append_mangled_name,
+  // Append the symbol type name as for Type::append_mangled_name,
   // but if USE_ALIAS use the alias name rather than the alias target.
   void
-  append_mangled_type_name(Gogo*, bool use_alias, std::string*) const;
+  append_symbol_type_name(Gogo*, bool use_alias, std::string*) const;
 
   // Import a named type.
   static void
index e7379f87047931ace5061cbdfa0936fb99f19b59..1d7d007f88ed622fe60436dfdf1a459d73b209c9 100755 (executable)
@@ -2551,7 +2551,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 ac_config_headers="$ac_config_headers config.h"
 
 
-libtool_VERSION=17:0:0
+libtool_VERSION=18:0:0
 
 
 # Default to --enable-multilib
index 80537f5f440acc5703eb02f84ac3a842f83071f3..5013f4142a6c17d64ffca15217dad6587e8bfe1d 100644 (file)
@@ -10,7 +10,7 @@ AC_INIT(package-unused, version-unused,, libgo)
 AC_CONFIG_SRCDIR(Makefile.am)
 AC_CONFIG_HEADER(config.h)
 
-libtool_VERSION=17:0:0
+libtool_VERSION=18:0:0
 AC_SUBST(libtool_VERSION)
 
 AM_ENABLE_MULTILIB(, ..)
index 2ab8425999f0b126390e411079558b602e31d10a..05441398d7abd1202abf817265172b5f64e8c80f 100644 (file)
@@ -191,7 +191,7 @@ func (p *Package) writeDefs() {
                        panic(fmt.Errorf("invalid var kind %q", n.Kind))
                }
                if *gccgo {
-                       fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
+                       fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, gccgoToSymbol(n.Mangle))
                        fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
                        fmt.Fprintf(fc, "\n")
                }
@@ -1168,7 +1168,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
                // will not be able to link against it from the C
                // code.
                goName := "Cgoexp_" + exp.ExpName
-               fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
+               fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, gccgoToSymbol(goName))
                fmt.Fprint(fgcc, "\n")
 
                fmt.Fprint(fgcc, "\nCGO_NO_SANITIZE_THREAD\n")
@@ -1202,7 +1202,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
                fmt.Fprint(fgcc, "}\n")
 
                // Dummy declaration for _cgo_main.c
-               fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName)
+               fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, gccgoToSymbol(goName))
                fmt.Fprint(fm, "\n")
 
                // For gccgo we use a wrapper function in Go, in order
@@ -1286,9 +1286,8 @@ func (p *Package) writeExportHeader(fgcch io.Writer) {
        fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
 }
 
-// gccgoPkgpathToSymbol converts a package path to a mangled packagepath
-// symbol.
-func gccgoPkgpathToSymbol(ppath string) string {
+// gccgoToSymbol converts a name to a mangled symbol for gccgo.
+func gccgoToSymbol(ppath string) string {
        if gccgoMangler == nil {
                var err error
                cmd := os.Getenv("GCCGO")
@@ -1313,12 +1312,12 @@ func (p *Package) gccgoSymbolPrefix() string {
        }
 
        if *gccgopkgpath != "" {
-               return gccgoPkgpathToSymbol(*gccgopkgpath)
+               return gccgoToSymbol(*gccgopkgpath)
        }
        if *gccgoprefix == "" && p.PackageName == "main" {
                return "main"
        }
-       prefix := gccgoPkgpathToSymbol(*gccgoprefix)
+       prefix := gccgoToSymbol(*gccgoprefix)
        if prefix == "" {
                prefix = "go"
        }
@@ -1710,8 +1709,12 @@ void _cgoPREFIX_Cfunc__Cmalloc(void *v) {
 `
 
 func (p *Package) cPrologGccgo() string {
-       return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1),
-               "GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1)
+       r := strings.NewReplacer(
+               "PREFIX", cPrefix,
+               "GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(),
+               "_cgoCheckPointer", gccgoToSymbol("_cgoCheckPointer"),
+               "_cgoCheckResult", gccgoToSymbol("_cgoCheckResult"))
+       return r.Replace(cPrologGccgo)
 }
 
 const cPrologGccgo = `
index 0b24468be642069b03a3191fe725786b331df353..40a040a81af6acb54eb272d7bf388b8f79289d99 100644 (file)
@@ -50,9 +50,12 @@ func ToSymbolFunc(cmd, tmpdir string) (func(string) string, error) {
                return nil, err
        }
 
-       // New mangling: expect go.l..u00e4ufer.Run
-       // Old mangling: expect go.l__ufer.Run
-       if bytes.Contains(buf, []byte("go.l..u00e4ufer.Run")) {
+       // Original mangling: go.l__ufer.Run
+       // Mangling v2: go.l..u00e4ufer.Run
+       // Mangling v3: go_0l_u00e4ufer.Run
+       if bytes.Contains(buf, []byte("go_0l_u00e4ufer.Run")) {
+               return toSymbolV3, nil
+       } else if bytes.Contains(buf, []byte("go.l..u00e4ufer.Run")) {
                return toSymbolV2, nil
        } else if bytes.Contains(buf, []byte("go.l__ufer.Run")) {
                return toSymbolV1, nil
@@ -82,7 +85,7 @@ func toSymbolV1(ppath string) string {
        return strings.Map(clean, ppath)
 }
 
-// toSymbolV2 converts a package path using the newer mangling scheme.
+// toSymbolV2 converts a package path using the second mangling scheme.
 func toSymbolV2(ppath string) string {
        // This has to build at boostrap time, so it has to build
        // with Go 1.4, so we don't use strings.Builder.
@@ -112,3 +115,60 @@ func toSymbolV2(ppath string) string {
        }
        return string(bsl)
 }
+
+// v3UnderscoreCodes maps from a character that supports an underscore
+// encoding to the underscore encoding character.
+var v3UnderscoreCodes = map[byte]byte{
+       '_': '_',
+       '.': '0',
+       '/': '1',
+       '*': '2',
+       ',': '3',
+       '{': '4',
+       '}': '5',
+       '[': '6',
+       ']': '7',
+       '(': '8',
+       ')': '9',
+       '"': 'a',
+       ' ': 'b',
+       ';': 'c',
+}
+
+// toSymbolV3 converts a package path using the third mangling scheme.
+func toSymbolV3(ppath string) string {
+       // This has to build at boostrap time, so it has to build
+       // with Go 1.4, so we don't use strings.Builder.
+       bsl := make([]byte, 0, len(ppath))
+       changed := false
+       for _, c := range ppath {
+               if ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') {
+                       bsl = append(bsl, byte(c))
+                       continue
+               }
+
+               if c < 0x80 {
+                       if u, ok := v3UnderscoreCodes[byte(c)]; ok {
+                               bsl = append(bsl, '_', u)
+                               changed = true
+                               continue
+                       }
+               }
+
+               var enc string
+               switch {
+               case c < 0x80:
+                       enc = fmt.Sprintf("_x%02x", c)
+               case c < 0x10000:
+                       enc = fmt.Sprintf("_u%04x", c)
+               default:
+                       enc = fmt.Sprintf("_U%08x", c)
+               }
+               bsl = append(bsl, enc...)
+               changed = true
+       }
+       if !changed {
+               return ppath
+       }
+       return string(bsl)
+}
index 7355f81baec7a9f42b33293ce19e1a811d34a576..232e803a6014df6270b24a3b782d0c60ff8209e2 100644 (file)
@@ -24,6 +24,9 @@ func init() {
        case "v2":
                os.Stdout.WriteString(`.string  "go.l..u00e4ufer.Run"`)
                os.Exit(0)
+       case "v3":
+               os.Stdout.WriteString(`.string  "go_0l_u00e4ufer.Run"`)
+               os.Exit(0)
        case "error":
                os.Stdout.WriteString(`unknown string`)
                os.Exit(0)
@@ -45,6 +48,10 @@ func TestToSymbolFunc(t *testing.T) {
                        env:     "v2",
                        mangled: "p..u00e4..u4e16..U0001f703",
                },
+               {
+                       env:     "v3",
+                       mangled: "p_u00e4_u4e16_U0001f703",
+               },
                {
                        env:  "error",
                        fail: true,
@@ -75,32 +82,37 @@ func TestToSymbolFunc(t *testing.T) {
 }
 
 var symbolTests = []struct {
-       input, v1, v2 string
+       input, v1, v2, v3 string
 }{
        {
                "",
                "",
                "",
+               "",
        },
        {
                "bytes",
                "bytes",
                "bytes",
+               "bytes",
        },
        {
                "net/http",
                "net_http",
                "net..z2fhttp",
+               "net_1http",
        },
        {
                "golang.org/x/net/http",
                "golang_org_x_net_http",
                "golang.x2eorg..z2fx..z2fnet..z2fhttp",
+               "golang_0org_1x_1net_1http",
        },
        {
                "pä世.🜃",
                "p____",
                "p..u00e4..u4e16.x2e..U0001f703",
+               "p_u00e4_u4e16_0_U0001f703",
        },
 }
 
@@ -119,3 +131,11 @@ func TestV2(t *testing.T) {
                }
        }
 }
+
+func TestV3(t *testing.T) {
+       for _, test := range symbolTests {
+               if got, want := toSymbolV3(test.input), test.v3; got != want {
+                       t.Errorf("toSymbolV3(%q) = %q, want %q", test.input, got, want)
+               }
+       }
+}
index 90bb3a9bc11554e60163d9b59f4989c8d757a554..3a2ca9aba81d34df17e3f903f7a177a3c7c345e1 100644 (file)
@@ -262,5 +262,5 @@ func (p *Importer) joinPath(elem ...string) string {
        return filepath.Join(elem...)
 }
 
-//go:linkname setUsesCgo go/types.srcimporter_setUsesCgo
+//go:linkname setUsesCgo go_1types.srcimporter__setUsesCgo
 func setUsesCgo(conf *types.Config)
index 969732dfebc0284dab83623691f88ce9aaa49ec8..6c08340b38ff90111ebe2c78466d57ff810776fc 100644 (file)
@@ -38,7 +38,7 @@ static const void *goMemmem(const void *in, size_t inl, const void *s, size_t sl
 #endif
 
 intgo Compare(struct __go_open_array, struct __go_open_array)
-  __asm__(GOSYM_PREFIX "internal..z2fbytealg.Compare")
+  __asm__(GOSYM_PREFIX "internal_1bytealg.Compare")
   __attribute__((no_split_stack));
 
 intgo Compare(struct __go_open_array a, struct __go_open_array b)
@@ -69,7 +69,7 @@ intgo Compare(struct __go_open_array a, struct __go_open_array b)
 }
 
 intgo IndexByte(struct __go_open_array, byte)
-  __asm__(GOSYM_PREFIX "internal..z2fbytealg.IndexByte")
+  __asm__(GOSYM_PREFIX "internal_1bytealg.IndexByte")
   __attribute__((no_split_stack));
 
 intgo IndexByte(struct __go_open_array b, byte c)
@@ -85,7 +85,7 @@ intgo IndexByte(struct __go_open_array b, byte c)
 
 
 intgo IndexByteString(String, byte)
-  __asm__(GOSYM_PREFIX "internal..z2fbytealg.IndexByteString")
+  __asm__(GOSYM_PREFIX "internal_1bytealg.IndexByteString")
   __attribute__((no_split_stack));
 
 intgo IndexByteString(String s, byte c)
@@ -100,7 +100,7 @@ intgo IndexByteString(String s, byte c)
 }
 
 intgo Index(struct __go_open_array, struct __go_open_array)
-  __asm__(GOSYM_PREFIX "internal..z2fbytealg.Index")
+  __asm__(GOSYM_PREFIX "internal_1bytealg.Index")
   __attribute__((no_split_stack));
 
 intgo Index(struct __go_open_array a, struct __go_open_array b)
@@ -115,7 +115,7 @@ intgo Index(struct __go_open_array a, struct __go_open_array b)
 }
 
 intgo IndexString(String, String)
-  __asm__(GOSYM_PREFIX "internal..z2fbytealg.IndexString")
+  __asm__(GOSYM_PREFIX "internal_1bytealg.IndexString")
   __attribute__((no_split_stack));
 
 intgo IndexString(String a, String b)
index 6b40f0137a4cb46c1464d9d46294ec73efb7328b..da26f4d7407ad162c49f5fff617d8dbe21b748cc 100644 (file)
@@ -21,7 +21,7 @@ struct cpuid_ret {
 };
 
 struct cpuid_ret cpuid(uint32_t, uint32_t)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.cpuid")
+  __asm__(GOSYM_PREFIX "internal_1cpu.cpuid")
   __attribute__((no_split_stack));
 
 struct cpuid_ret cpuid(uint32_t eaxArg, uint32_t ecxArg) {
@@ -45,7 +45,7 @@ struct xgetbv_ret {
 };
 
 struct xgetbv_ret xgetbv(void)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.xgetbv")
+  __asm__(GOSYM_PREFIX "internal_1cpu.xgetbv")
   __attribute__((no_split_stack));
 
 #pragma GCC push_options
@@ -82,7 +82,7 @@ struct queryResult {
 };
 
 struct facilityList stfle(void)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.stfle")
+  __asm__(GOSYM_PREFIX "internal_1cpu.stfle")
   __attribute__((no_split_stack));
 
 struct facilityList stfle(void) {
@@ -96,7 +96,7 @@ struct facilityList stfle(void) {
 }
 
 struct queryResult kmQuery(void)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.kmQuery")
+  __asm__(GOSYM_PREFIX "internal_1cpu.kmQuery")
   __attribute__((no_split_stack));
 
 struct queryResult kmQuery() {
@@ -110,7 +110,7 @@ struct queryResult kmQuery() {
 }
 
 struct queryResult kmcQuery(void)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.kmcQuery")
+  __asm__(GOSYM_PREFIX "internal_1cpu.kmcQuery")
   __attribute__((no_split_stack));
 
 struct queryResult kmcQuery() {
@@ -125,7 +125,7 @@ struct queryResult kmcQuery() {
 }
 
 struct queryResult kmctrQuery(void)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.kmctrQuery")
+  __asm__(GOSYM_PREFIX "internal_1cpu.kmctrQuery")
   __attribute__((no_split_stack));
 
 struct queryResult kmctrQuery() {
@@ -140,7 +140,7 @@ struct queryResult kmctrQuery() {
 }
 
 struct queryResult kmaQuery(void)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.kmaQuery")
+  __asm__(GOSYM_PREFIX "internal_1cpu.kmaQuery")
   __attribute__((no_split_stack));
 
 struct queryResult kmaQuery() {
@@ -155,7 +155,7 @@ struct queryResult kmaQuery() {
 }
 
 struct queryResult kimdQuery(void)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.kimdQuery")
+  __asm__(GOSYM_PREFIX "internal_1cpu.kimdQuery")
   __attribute__((no_split_stack));
 
 struct queryResult kimdQuery() {
@@ -170,7 +170,7 @@ struct queryResult kimdQuery() {
 }
 
 struct queryResult klmdQuery(void)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.klmdQuery")
+  __asm__(GOSYM_PREFIX "internal_1cpu.klmdQuery")
   __attribute__((no_split_stack));
 
 struct queryResult klmdQuery() {
@@ -185,7 +185,7 @@ struct queryResult klmdQuery() {
 }
 
 struct queryResult kdsaQuery(void)
-  __asm__(GOSYM_PREFIX "internal..z2fcpu.kdsaQuery")
+  __asm__(GOSYM_PREFIX "internal_1cpu.kdsaQuery")
   __attribute__((no_split_stack));
 
 struct queryResult kdsaQuery() {
index 36e76942ba93a40efb8170c08d65160774a59b3a..329df404efd0876a91b4d5e6f7061467bf65c167 100644 (file)
@@ -12,7 +12,7 @@
    can't represent a C varargs function in Go.  */
 
 void syslog_c(intgo, const char*)
-  __asm__ (GOSYM_PREFIX "log..z2fsyslog.syslog_c");
+  __asm__ (GOSYM_PREFIX "log_1syslog.syslog_c");
 
 void
 syslog_c (intgo priority, const char *msg)
index 49b0f2b84fd35dd2a8f49a0b80127232f7e847be..029591394b49513f7738ed4c3a926950d0fe6784 100644 (file)
@@ -39,10 +39,10 @@ func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
 // We cannot just call the runtime routines, because the race detector expects
 // to be able to intercept the sync/atomic forms but not the runtime forms.
 
-//go:linkname sync_atomic_StoreUintptr sync..z2fatomic.StoreUintptr
+//go:linkname sync_atomic_StoreUintptr sync_1atomic.StoreUintptr
 func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr)
 
-//go:linkname sync_atomic_StorePointer sync..z2fatomic.StorePointer
+//go:linkname sync_atomic_StorePointer sync_1atomic.StorePointer
 //go:nosplit
 func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
        if writeBarrier.enabled {
@@ -51,10 +51,10 @@ func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
        sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
 }
 
-//go:linkname sync_atomic_SwapUintptr sync..z2fatomic.SwapUintptr
+//go:linkname sync_atomic_SwapUintptr sync_1atomic.SwapUintptr
 func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr
 
-//go:linkname sync_atomic_SwapPointer sync..z2fatomic.SwapPointer
+//go:linkname sync_atomic_SwapPointer sync_1atomic.SwapPointer
 //go:nosplit
 func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
        if writeBarrier.enabled {
@@ -64,10 +64,10 @@ func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Poi
        return old
 }
 
-//go:linkname sync_atomic_CompareAndSwapUintptr sync..z2fatomic.CompareAndSwapUintptr
+//go:linkname sync_atomic_CompareAndSwapUintptr sync_1atomic.CompareAndSwapUintptr
 func sync_atomic_CompareAndSwapUintptr(ptr *uintptr, old, new uintptr) bool
 
-//go:linkname sync_atomic_CompareAndSwapPointer sync..z2fatomic.CompareAndSwapPointer
+//go:linkname sync_atomic_CompareAndSwapPointer sync_1atomic.CompareAndSwapPointer
 //go:nosplit
 func sync_atomic_CompareAndSwapPointer(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
        if writeBarrier.enabled {
index b909d478d266153ff70ce5bf4cca6db579da04b8..8e104f14140ca8eaea102b915904f51c2c8df8a9 100644 (file)
@@ -774,7 +774,7 @@ func reflect_chanlen(c *hchan) int {
        return int(c.qcount)
 }
 
-//go:linkname reflectlite_chanlen internal..z2freflectlite.chanlen
+//go:linkname reflectlite_chanlen internal_1reflectlite.chanlen
 func reflectlite_chanlen(c *hchan) int {
        if c == nil {
                return 0
index d39521094ec608e4bea43facc0303b64b9811a61..43f0a6705f5d6603549a0e58c310681830b87037 100644 (file)
@@ -189,7 +189,7 @@ func CPUProfile() []byte {
        panic("CPUProfile no longer available")
 }
 
-//go:linkname runtime_pprof_runtime_cyclesPerSecond runtime..z2fpprof.runtime_cyclesPerSecond
+//go:linkname runtime_pprof_runtime_cyclesPerSecond runtime_1pprof.runtime__cyclesPerSecond
 func runtime_pprof_runtime_cyclesPerSecond() int64 {
        return tickspersecond()
 }
@@ -200,7 +200,7 @@ func runtime_pprof_runtime_cyclesPerSecond() int64 {
 // on has been returned, readProfile returns eof=true.
 // The caller must save the returned data and tags before calling readProfile again.
 //
-//go:linkname runtime_pprof_readProfile runtime..z2fpprof.readProfile
+//go:linkname runtime_pprof_readProfile runtime_1pprof.readProfile
 func runtime_pprof_readProfile() ([]uint64, []unsafe.Pointer, bool) {
        lock(&cpuprof.lock)
        log := cpuprof.log
index 1202e362a5aaddf866d00c8ea8f3c2460974c3b1..ff76580ee659e471d74ffa63b3527510d39ee7d8 100644 (file)
@@ -66,7 +66,7 @@ func NumGoroutine() int {
 // added.
 func Fieldtrack(map[string]bool)
 
-//go:linkname debug_modinfo runtime..z2fdebug.modinfo
+//go:linkname debug_modinfo runtime_1debug.modinfo
 func debug_modinfo() string {
        return modinfo
 }
index e8f16e90fe68b7a711c1693fed4a563e2cbae54d..816d93c6ef0164591337887a07cd6c0ce1371759 100644 (file)
@@ -16,7 +16,7 @@ import (
        "unsafe"
 )
 
-//go:linkname runtime_debug_WriteHeapDump runtime..z2fdebug.WriteHeapDump
+//go:linkname runtime_debug_WriteHeapDump runtime_1debug.WriteHeapDump
 func runtime_debug_WriteHeapDump(fd uintptr) {
        stopTheWorld("write heap dump")
 
index 5667ddb6b95b19c393017ff1da388fffa97490c8..f9df1e0d79a6fb0e1adb83d0a94a7436d0855aef 100644 (file)
@@ -505,7 +505,7 @@ func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
        dst.data = e.data
 }
 
-//go:linkname reflectlite_ifaceE2I internal..z2freflectlite.ifaceE2I
+//go:linkname reflectlite_ifaceE2I internal_1reflectlite.ifaceE2I
 func reflectlite_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
        t := e._type
        if t == nil {
index 8ae4d7b619dcef53214b68d42d7bf6f49c28890d..9fed1a8bff1f2bec10b92ff5580db6bfc8a66b72 100644 (file)
@@ -7,7 +7,7 @@
 #include "runtime.h"
 
 uint32_t Load (uint32_t *ptr)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Load")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Load")
   __attribute__ ((no_split_stack));
 
 uint32_t
@@ -17,7 +17,7 @@ Load (uint32_t *ptr)
 }
 
 void *Loadp (void *ptr)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loadp")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Loadp")
   __attribute__ ((no_split_stack));
 
 void *
@@ -27,7 +27,7 @@ Loadp (void *ptr)
 }
 
 uint8_t Load8 (uint8_t *ptr)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Load8")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Load8")
   __attribute__ ((no_split_stack));
 
 uint8_t
@@ -37,7 +37,7 @@ Load8 (uint8_t *ptr)
 }
 
 uint64_t Load64 (uint64_t *ptr)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Load64")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Load64")
   __attribute__ ((no_split_stack));
 
 uint64_t
@@ -49,7 +49,7 @@ Load64 (uint64_t *ptr)
 }
 
 uint32_t LoadAcq (uint32_t *ptr)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.LoadAcq")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.LoadAcq")
   __attribute__ ((no_split_stack));
 
 uint32_t
@@ -59,7 +59,7 @@ LoadAcq (uint32_t *ptr)
 }
 
 uintptr_t Loaduintptr (uintptr_t *ptr)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loaduintptr")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Loaduintptr")
   __attribute__ ((no_split_stack));
 
 uintptr_t
@@ -69,7 +69,7 @@ Loaduintptr (uintptr_t *ptr)
 }
 
 uintgo Loaduint (uintgo *ptr)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loaduint")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Loaduint")
   __attribute__ ((no_split_stack));
 
 uintgo
@@ -79,7 +79,7 @@ Loaduint (uintgo *ptr)
 }
 
 int64_t Loadint64 (int64_t *ptr)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loadint64")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Loadint64")
   __attribute__ ((no_split_stack));
 
 int64_t
@@ -91,7 +91,7 @@ Loadint64 (int64_t *ptr)
 }
 
 uint32_t Xadd (uint32_t *ptr, int32_t delta)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xadd")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Xadd")
   __attribute__ ((no_split_stack));
 
 uint32_t
@@ -101,7 +101,7 @@ Xadd (uint32_t *ptr, int32_t delta)
 }
 
 uint64_t Xadd64 (uint64_t *ptr, int64_t delta)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xadd64")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Xadd64")
   __attribute__ ((no_split_stack));
 
 uint64_t
@@ -113,7 +113,7 @@ Xadd64 (uint64_t *ptr, int64_t delta)
 }
 
 uintptr_t Xadduintptr (uintptr_t *ptr, uintptr_t delta)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xadduintptr")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Xadduintptr")
   __attribute__ ((no_split_stack));
 
 uintptr_t
@@ -123,7 +123,7 @@ Xadduintptr (uintptr_t *ptr, uintptr_t delta)
 }
 
 int64_t Xaddint64 (int64_t *ptr, int64_t delta)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xaddint64")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Xaddint64")
   __attribute__ ((no_split_stack));
 
 int64_t
@@ -135,7 +135,7 @@ Xaddint64 (int64_t *ptr, int64_t delta)
 }
 
 uint32_t Xchg (uint32_t *ptr, uint32_t new)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xchg")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Xchg")
   __attribute__ ((no_split_stack));
 
 uint32_t
@@ -145,7 +145,7 @@ Xchg (uint32_t *ptr, uint32_t new)
 }
 
 uint64_t Xchg64 (uint64_t *ptr, uint64_t new)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xchg64")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Xchg64")
   __attribute__ ((no_split_stack));
 
 uint64_t
@@ -157,7 +157,7 @@ Xchg64 (uint64_t *ptr, uint64_t new)
 }
 
 uintptr_t Xchguintptr (uintptr_t *ptr, uintptr_t new)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xchguintptr")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Xchguintptr")
   __attribute__ ((no_split_stack));
 
 uintptr_t
@@ -167,7 +167,7 @@ Xchguintptr (uintptr_t *ptr, uintptr_t new)
 }
 
 void And8 (uint8_t *ptr, uint8_t val)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.And8")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.And8")
   __attribute__ ((no_split_stack));
 
 void
@@ -177,7 +177,7 @@ And8 (uint8_t *ptr, uint8_t val)
 }
 
 void Or8 (uint8_t *ptr, uint8_t val)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Or8")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Or8")
   __attribute__ ((no_split_stack));
 
 void
@@ -187,7 +187,7 @@ Or8 (uint8_t *ptr, uint8_t val)
 }
 
 _Bool Cas (uint32_t *ptr, uint32_t old, uint32_t new)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Cas")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Cas")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -197,7 +197,7 @@ Cas (uint32_t *ptr, uint32_t old, uint32_t new)
 }
 
 _Bool Cas64 (uint64_t *ptr, uint64_t old, uint64_t new)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Cas64")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Cas64")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -209,7 +209,7 @@ Cas64 (uint64_t *ptr, uint64_t old, uint64_t new)
 }
 
 _Bool CasRel (uint32_t *ptr, uint32_t old, uint32_t new)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.CasRel")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.CasRel")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -219,7 +219,7 @@ CasRel (uint32_t *ptr, uint32_t old, uint32_t new)
 }
 
 _Bool Casp1 (void **ptr, void *old, void *new)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Casp1")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Casp1")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -229,7 +229,7 @@ Casp1 (void **ptr, void *old, void *new)
 }
 
 _Bool Casuintptr (uintptr_t *ptr, uintptr_t old, uintptr_t new)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Casuintptr")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Casuintptr")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -239,7 +239,7 @@ Casuintptr (uintptr_t *ptr, uintptr_t old, uintptr_t new)
 }
 
 void Store (uint32_t *ptr, uint32_t val)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Store")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Store")
   __attribute__ ((no_split_stack));
 
 void
@@ -249,7 +249,7 @@ Store (uint32_t *ptr, uint32_t val)
 }
 
 void Store8 (uint8_t *ptr, uint8_t val)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Store8")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Store8")
   __attribute__ ((no_split_stack));
 
 void
@@ -259,7 +259,7 @@ Store8 (uint8_t *ptr, uint8_t val)
 }
 
 void Store64 (uint64_t *ptr, uint64_t val)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Store64")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Store64")
   __attribute__ ((no_split_stack));
 
 void
@@ -271,7 +271,7 @@ Store64 (uint64_t *ptr, uint64_t val)
 }
 
 void StoreRel (uint32_t *ptr, uint32_t val)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.StoreRel")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.StoreRel")
   __attribute__ ((no_split_stack));
 
 void
@@ -281,7 +281,7 @@ StoreRel (uint32_t *ptr, uint32_t val)
 }
 
 void Storeuintptr (uintptr_t *ptr, uintptr_t val)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Storeuintptr")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Storeuintptr")
   __attribute__ ((no_split_stack));
 
 void
@@ -291,7 +291,7 @@ Storeuintptr (uintptr_t *ptr, uintptr_t val)
 }
 
 void StorepNoWB (void *ptr, void *val)
-  __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.StorepNoWB")
+  __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.StorepNoWB")
   __attribute__ ((no_split_stack));
 
 void
index 81351eefbb764ba41606f9dc7db7d4f47e24577c..feb043ac2e9600078ec00f32c541f532dca8f92b 100644 (file)
@@ -1220,12 +1220,12 @@ func newobject(typ *_type) unsafe.Pointer {
        return mallocgc(typ.size, typ, true)
 }
 
-//go:linkname reflect_unsafe_New reflect.unsafe_New
+//go:linkname reflect_unsafe_New reflect.unsafe__New
 func reflect_unsafe_New(typ *_type) unsafe.Pointer {
        return mallocgc(typ.size, typ, true)
 }
 
-//go:linkname reflectlite_unsafe_New internal..z2freflectlite.unsafe_New
+//go:linkname reflectlite_unsafe_New internal_1reflectlite.unsafe__New
 func reflectlite_unsafe_New(typ *_type) unsafe.Pointer {
        return mallocgc(typ.size, typ, true)
 }
@@ -1242,7 +1242,7 @@ func newarray(typ *_type, n int) unsafe.Pointer {
        return mallocgc(mem, typ, true)
 }
 
-//go:linkname reflect_unsafe_NewArray reflect.unsafe_NewArray
+//go:linkname reflect_unsafe_NewArray reflect.unsafe__NewArray
 func reflect_unsafe_NewArray(typ *_type, n int) unsafe.Pointer {
        return newarray(typ, n)
 }
index b82977103c07f52065229a9137ec24db233277cb..1155fee861c8176475e40dea7d6c5d7d24e58f1b 100644 (file)
@@ -1417,7 +1417,7 @@ func reflect_maplen(h *hmap) int {
        return h.count
 }
 
-//go:linkname reflectlite_maplen internal..z2freflectlite.maplen
+//go:linkname reflectlite_maplen internal_1reflectlite.maplen
 func reflectlite_maplen(h *hmap) int {
        if h == nil {
                return 0
index 836f85a0330a239604edaa63634f786b571c7f6a..3bd8b34429d2bfe8cca84f625f2705baaa554c28 100644 (file)
@@ -192,7 +192,7 @@ func reflect_typedmemmove(typ *_type, dst, src unsafe.Pointer) {
        typedmemmove(typ, dst, src)
 }
 
-//go:linkname reflectlite_typedmemmove internal..z2freflectlite.typedmemmove
+//go:linkname reflectlite_typedmemmove internal_1reflectlite.typedmemmove
 func reflectlite_typedmemmove(typ *_type, dst, src unsafe.Pointer) {
        reflect_typedmemmove(typ, dst, src)
 }
index 9dd7bff8a805ad6ef6335f2923a9a15caddb5840..72479c2391687b94e6e2882adaf0d8ed606cfc74 100644 (file)
@@ -223,7 +223,7 @@ func gcenable() {
        memstats.enablegc = true // now that runtime is initialized, GC is okay
 }
 
-//go:linkname setGCPercent runtime..z2fdebug.setGCPercent
+//go:linkname setGCPercent runtime_1debug.setGCPercent
 func setGCPercent(in int32) (out int32) {
        // Run on the system stack since we grab the heap lock.
        systemstack(func() {
@@ -2238,7 +2238,7 @@ func gcResetMarkState() {
 
 var poolcleanup func()
 
-//go:linkname sync_runtime_registerPoolCleanup sync.runtime_registerPoolCleanup
+//go:linkname sync_runtime_registerPoolCleanup sync.runtime__registerPoolCleanup
 func sync_runtime_registerPoolCleanup(f func()) {
        poolcleanup = f
 }
index e73ee32efd4f6ffe1001fbd5ff0de2774f89ce47..755efd19772fd427fd9463c21d706f03a692befd 100644 (file)
@@ -1502,7 +1502,7 @@ func (h *mheap) scavengeAll() {
        }
 }
 
-//go:linkname runtime_debug_freeOSMemory runtime..z2fdebug.freeOSMemory
+//go:linkname runtime_debug_freeOSMemory runtime_1debug.freeOSMemory
 func runtime_debug_freeOSMemory() {
        GC()
        systemstack(func() { mheap_.scavengeAll() })
index a4b135d90d02f4cc0a976477e6de8a47ae721663..afacf8fa70f50f388cee156e421e86b239e94c53 100644 (file)
@@ -942,7 +942,7 @@ func ThreadCreateProfile(p []StackRecord) (n int, ok bool) {
        return
 }
 
-//go:linkname runtime_goroutineProfileWithLabels runtime..z2fpprof.runtime_goroutineProfileWithLabels
+//go:linkname runtime_goroutineProfileWithLabels runtime_1pprof.runtime__goroutineProfileWithLabels
 func runtime_goroutineProfileWithLabels(p []StackRecord, labels []unsafe.Pointer) (n int, ok bool) {
        return goroutineProfileWithLabels(p, labels)
 }
index 4e2c66cea1fdc65829bdc1e1c259f48cb7f834e1..85a0861b8cd658c94ca80b2e7685634a4b2e9c22 100644 (file)
@@ -468,7 +468,7 @@ func readmemstats_m(stats *MemStats) {
        stats.StackSys += stats.StackInuse
 }
 
-//go:linkname readGCStats runtime..z2fdebug.readGCStats
+//go:linkname readGCStats runtime_1debug.readGCStats
 func readGCStats(pauses *[]uint64) {
        systemstack(func() {
                readGCStats_m(pauses)
index 907c31975c75f6dc0774cd35043fe4fb60293da7..38ff5a4ccb314d60c3589059ccf584b4b8d92ecb 100644 (file)
@@ -8,12 +8,12 @@ import (
        _ "unsafe"
 )
 
-//go:linkname runtime_ignoreHangup internal..z2fpoll.runtime_ignoreHangup
+//go:linkname runtime_ignoreHangup internal_1poll.runtime__ignoreHangup
 func runtime_ignoreHangup() {
        getg().m.ignoreHangup = true
 }
 
-//go:linkname runtime_unignoreHangup internal..z2fpoll.runtime_unignoreHangup
+//go:linkname runtime_unignoreHangup internal_1poll.runtime__unignoreHangup
 func runtime_unignoreHangup(sig string) {
        getg().m.ignoreHangup = false
 }
index 72a136d363f1927de720a065a093e8c9c52fd2ab..da00b57c276ee1ed89f68a7985af1263e3f1e467 100644 (file)
@@ -113,7 +113,7 @@ var (
        netpollWaiters uint32
 )
 
-//go:linkname poll_runtime_pollServerInit internal..z2fpoll.runtime_pollServerInit
+//go:linkname poll_runtime_pollServerInit internal_1poll.runtime__pollServerInit
 func poll_runtime_pollServerInit() {
        netpollGenericInit()
 }
@@ -134,7 +134,7 @@ func netpollinited() bool {
        return atomic.Load(&netpollInited) != 0
 }
 
-//go:linkname poll_runtime_isPollServerDescriptor internal..z2fpoll.runtime_isPollServerDescriptor
+//go:linkname poll_runtime_isPollServerDescriptor internal_1poll.runtime__isPollServerDescriptor
 
 // poll_runtime_isPollServerDescriptor reports whether fd is a
 // descriptor being used by netpoll.
@@ -142,7 +142,7 @@ func poll_runtime_isPollServerDescriptor(fd uintptr) bool {
        return netpollIsPollDescriptor(fd)
 }
 
-//go:linkname poll_runtime_pollOpen internal..z2fpoll.runtime_pollOpen
+//go:linkname poll_runtime_pollOpen internal_1poll.runtime__pollOpen
 func poll_runtime_pollOpen(fd uintptr) (uintptr, int) {
        pd := pollcache.alloc()
        lock(&pd.lock)
@@ -169,7 +169,7 @@ func poll_runtime_pollOpen(fd uintptr) (uintptr, int) {
        return uintptr(unsafe.Pointer(pd)), int(errno)
 }
 
-//go:linkname poll_runtime_pollClose internal..z2fpoll.runtime_pollClose
+//go:linkname poll_runtime_pollClose internal_1poll.runtime__pollClose
 func poll_runtime_pollClose(ctx uintptr) {
        pd := (*pollDesc)(unsafe.Pointer(ctx))
        if !pd.closing {
@@ -195,7 +195,7 @@ func (c *pollCache) free(pd *pollDesc) {
 // poll_runtime_pollReset, which is internal/poll.runtime_pollReset,
 // prepares a descriptor for polling in mode, which is 'r' or 'w'.
 // This returns an error code; the codes are defined above.
-//go:linkname poll_runtime_pollReset internal..z2fpoll.runtime_pollReset
+//go:linkname poll_runtime_pollReset internal_1poll.runtime__pollReset
 func poll_runtime_pollReset(ctx uintptr, mode int) int {
        pd := (*pollDesc)(unsafe.Pointer(ctx))
        errcode := netpollcheckerr(pd, int32(mode))
@@ -214,7 +214,7 @@ func poll_runtime_pollReset(ctx uintptr, mode int) int {
 // waits for a descriptor to be ready for reading or writing,
 // according to mode, which is 'r' or 'w'.
 // This returns an error code; the codes are defined above.
-//go:linkname poll_runtime_pollWait internal..z2fpoll.runtime_pollWait
+//go:linkname poll_runtime_pollWait internal_1poll.runtime__pollWait
 func poll_runtime_pollWait(ctx uintptr, mode int) int {
        pd := (*pollDesc)(unsafe.Pointer(ctx))
        errcode := netpollcheckerr(pd, int32(mode))
@@ -237,7 +237,7 @@ func poll_runtime_pollWait(ctx uintptr, mode int) int {
        return pollNoError
 }
 
-//go:linkname poll_runtime_pollWaitCanceled internal..z2fpoll.runtime_pollWaitCanceled
+//go:linkname poll_runtime_pollWaitCanceled internal_1poll.runtime__pollWaitCanceled
 func poll_runtime_pollWaitCanceled(ctx uintptr, mode int) {
        pd := (*pollDesc)(unsafe.Pointer(ctx))
        // This function is used only on windows after a failed attempt to cancel
@@ -246,7 +246,7 @@ func poll_runtime_pollWaitCanceled(ctx uintptr, mode int) {
        }
 }
 
-//go:linkname poll_runtime_pollSetDeadline internal..z2fpoll.runtime_pollSetDeadline
+//go:linkname poll_runtime_pollSetDeadline internal_1poll.runtime__pollSetDeadline
 func poll_runtime_pollSetDeadline(ctx uintptr, d int64, mode int) {
        pd := (*pollDesc)(unsafe.Pointer(ctx))
        lock(&pd.lock)
@@ -330,7 +330,7 @@ func poll_runtime_pollSetDeadline(ctx uintptr, d int64, mode int) {
        }
 }
 
-//go:linkname poll_runtime_pollUnblock internal..z2fpoll.runtime_pollUnblock
+//go:linkname poll_runtime_pollUnblock internal_1poll.runtime__pollUnblock
 func poll_runtime_pollUnblock(ctx uintptr) {
        pd := (*pollDesc)(unsafe.Pointer(ctx))
        lock(&pd.lock)
index 625ab7de8c8a80cc872d51ddbed2728bf64ead84..83bf572dd6cbb79331e0d607a866053eebccb440 100644 (file)
@@ -91,35 +91,35 @@ func TestMemoryProfiler(t *testing.T) {
                stk    []string
                legacy string
        }{{
-               stk: []string{"pprof.allocatePersistent1K", "runtime/pprof.TestMemoryProfiler"},
+               stk: []string{"runtime/pprof.allocatePersistent1K", "runtime/pprof.TestMemoryProfiler"},
                legacy: fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f x]+
-#      0x[0-9,a-f]+    pprof\.allocatePersistent1K\+0x[0-9,a-f]+       .*/mprof_test\.go:47
+#      0x[0-9,a-f]+    runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+       .*/mprof_test\.go:47
 #      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:82
 `, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun),
        }, {
-               stk: []string{"pprof.allocateTransient1M", "runtime/pprof.TestMemoryProfiler"},
+               stk: []string{"runtime/pprof.allocateTransient1M", "runtime/pprof.TestMemoryProfiler"},
                legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
-#      0x[0-9,a-f]+    pprof\.allocateTransient1M\+0x[0-9,a-f]+        .*/mprof_test.go:24
+#      0x[0-9,a-f]+    runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+        .*/mprof_test.go:24
 #      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:79
 `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
        }, {
-               stk: []string{"pprof.allocateTransient2M", "runtime/pprof.TestMemoryProfiler"},
+               stk: []string{"runtime/pprof.allocateTransient2M", "runtime/pprof.TestMemoryProfiler"},
                // This should start with "0: 0" but gccgo's imprecise
                // GC means that sometimes the value is not collected.
                legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
-#      0x[0-9,a-f]+    pprof\.allocateTransient2M\+0x[0-9,a-f]+        .*/mprof_test.go:30
+#      0x[0-9,a-f]+    runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+        .*/mprof_test.go:30
 #      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:80
 `, memoryProfilerRun, (2<<20)*memoryProfilerRun, memoryProfilerRun, (2<<20)*memoryProfilerRun),
        }, {
-               stk: []string{"pprof.allocateTransient2MInline", "runtime/pprof.TestMemoryProfiler"},
+               stk: []string{"runtime/pprof.allocateTransient2MInline", "runtime/pprof.TestMemoryProfiler"},
                legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
-#      0x[0-9,a-f]+    pprof\.allocateTransient2MInline\+0x[0-9,a-f]+  .*/mprof_test.go:34
+#      0x[0-9,a-f]+    runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+  .*/mprof_test.go:34
 #      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:81
 `, memoryProfilerRun, (4<<20)*memoryProfilerRun, memoryProfilerRun, (4<<20)*memoryProfilerRun),
        }, {
-               stk: []string{"pprof.allocateReflectTransient"},
+               stk: []string{"runtime/pprof.allocateReflectTransient"},
                legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @( 0x[0-9,a-f]+)+
-#      0x[0-9,a-f]+    pprof\.allocateReflectTransient\+0x[0-9,a-f]+   .*/mprof_test.go:55
+#      0x[0-9,a-f]+    runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+   .*/mprof_test.go:55
 `, memoryProfilerRun, (3<<20)*memoryProfilerRun, memoryProfilerRun, (3<<20)*memoryProfilerRun),
        }}
 
index ff86bce1211f7c618b738fe15946108d09adb693..7adf891afff153d871c5bbbd90f037c42e2a7f67 100644 (file)
@@ -958,8 +958,8 @@ func TestMutexProfile(t *testing.T) {
 
                stks := stacks(p)
                for _, want := range [][]string{
-                       // {"sync.(*Mutex).Unlock", "pprof.blockMutex.func1"},
-                       {"sync.Mutex.Unlock", "pprof.blockMutex..func1"},
+                       // {"sync.(*Mutex).Unlock", "runtime/pprof.blockMutex.func1"},
+                       {"sync.Mutex.Unlock", "runtime/pprof.blockMutex..func1"},
                } {
                        if !containsStack(stks, want) {
                                t.Errorf("No matching stack entry for %+v", want)
index 9a78bcf51b892f2e076ed0c1ca8c7f9072bc1d51..8452076dc7d25ecbd9630aa8f458375cf6a1be1a 100644 (file)
@@ -360,7 +360,7 @@ func isAsyncSafePoint(gp *g, pc uintptr) (bool, uintptr) {
        }
        name := f.Name()
        if hasPrefix(name, "runtime.") ||
-               hasPrefix(name, "runtime..z2finternal..z2f") ||
+               hasPrefix(name, "runtime_1internal_1") ||
                hasPrefix(name, "reflect.") {
                // For now we never async preempt the runtime or
                // anything closely tied to the runtime. Known issues
index 0ca6c02bce85b182ef3d08cc8f9ec8ea7c155ea6..6c720503c44471e28a79cacf49dde149fe971818 100644 (file)
@@ -263,7 +263,7 @@ func main(unsafe.Pointer) {
 }
 
 // os_beforeExit is called from os.Exit(0).
-//go:linkname os_beforeExit os.runtime_beforeExit
+//go:linkname os_beforeExit os.runtime__beforeExit
 func os_beforeExit() {
        if raceenabled {
                racefini()
@@ -3305,7 +3305,7 @@ func beforefork() {
 }
 
 // Called from syscall package before fork.
-//go:linkname syscall_runtime_BeforeFork syscall.runtime_BeforeFork
+//go:linkname syscall_runtime_BeforeFork syscall.runtime__BeforeFork
 //go:nosplit
 func syscall_runtime_BeforeFork() {
        systemstack(beforefork)
@@ -3320,7 +3320,7 @@ func afterfork() {
 }
 
 // Called from syscall package after fork in parent.
-//go:linkname syscall_runtime_AfterFork syscall.runtime_AfterFork
+//go:linkname syscall_runtime_AfterFork syscall.runtime__AfterFork
 //go:nosplit
 func syscall_runtime_AfterFork() {
        systemstack(afterfork)
@@ -3338,7 +3338,7 @@ var inForkedChild bool
 // temporarily sharing address space with the parent process, this must
 // not change any global variables or calling into C code that may do so.
 //
-//go:linkname syscall_runtime_AfterForkInChild syscall.runtime_AfterForkInChild
+//go:linkname syscall_runtime_AfterForkInChild syscall.runtime__AfterForkInChild
 //go:nosplit
 //go:nowritebarrierrec
 func syscall_runtime_AfterForkInChild() {
@@ -3363,7 +3363,7 @@ func syscall_runtime_AfterForkInChild() {
 var pendingPreemptSignals uint32
 
 // Called from syscall package before Exec.
-//go:linkname syscall_runtime_BeforeExec syscall.runtime_BeforeExec
+//go:linkname syscall_runtime_BeforeExec syscall.runtime__BeforeExec
 func syscall_runtime_BeforeExec() {
        // Prevent thread creation during exec.
        execLock.lock()
@@ -3378,7 +3378,7 @@ func syscall_runtime_BeforeExec() {
 }
 
 // Called from syscall package after Exec.
-//go:linkname syscall_runtime_AfterExec syscall.runtime_AfterExec
+//go:linkname syscall_runtime_AfterExec syscall.runtime__AfterExec
 func syscall_runtime_AfterExec() {
        execLock.unlock()
 }
@@ -5165,7 +5165,7 @@ func (l *gList) pop() *g {
        return gp
 }
 
-//go:linkname setMaxThreads runtime..z2fdebug.setMaxThreads
+//go:linkname setMaxThreads runtime_1debug.setMaxThreads
 func setMaxThreads(in int) (out int) {
        lock(&sched.lock)
        out = int(sched.maxmcount)
@@ -5199,32 +5199,32 @@ func procUnpin() {
        _g_.m.locks--
 }
 
-//go:linkname sync_runtime_procPin sync.runtime_procPin
+//go:linkname sync_runtime_procPin sync.runtime__procPin
 //go:nosplit
 func sync_runtime_procPin() int {
        return procPin()
 }
 
-//go:linkname sync_runtime_procUnpin sync.runtime_procUnpin
+//go:linkname sync_runtime_procUnpin sync.runtime__procUnpin
 //go:nosplit
 func sync_runtime_procUnpin() {
        procUnpin()
 }
 
-//go:linkname sync_atomic_runtime_procPin sync..z2fatomic.runtime_procPin
+//go:linkname sync_atomic_runtime_procPin sync_1atomic.runtime__procPin
 //go:nosplit
 func sync_atomic_runtime_procPin() int {
        return procPin()
 }
 
-//go:linkname sync_atomic_runtime_procUnpin sync..z2fatomic.runtime_procUnpin
+//go:linkname sync_atomic_runtime_procUnpin sync_1atomic.runtime__procUnpin
 //go:nosplit
 func sync_atomic_runtime_procUnpin() {
        procUnpin()
 }
 
 // Active spinning for sync.Mutex.
-//go:linkname sync_runtime_canSpin sync.runtime_canSpin
+//go:linkname sync_runtime_canSpin sync.runtime__canSpin
 //go:nosplit
 func sync_runtime_canSpin(i int) bool {
        // sync.Mutex is cooperative, so we are conservative with spinning.
@@ -5241,7 +5241,7 @@ func sync_runtime_canSpin(i int) bool {
        return true
 }
 
-//go:linkname sync_runtime_doSpin sync.runtime_doSpin
+//go:linkname sync_runtime_doSpin sync.runtime__doSpin
 //go:nosplit
 func sync_runtime_doSpin() {
        procyield(active_spin_cnt)
index fc655cc80199e1913048bd196a805a191a975dbb..1e1f3bfab134f1cddaf50db815c04b1e4a1c83bb 100644 (file)
@@ -8,7 +8,7 @@ import "unsafe"
 
 var labelSync uintptr
 
-//go:linkname runtime_setProfLabel runtime..z2fpprof.runtime_setProfLabel
+//go:linkname runtime_setProfLabel runtime_1pprof.runtime__setProfLabel
 func runtime_setProfLabel(labels unsafe.Pointer) {
        // Introduce race edge for read-back via profile.
        // This would more properly use &getg().labels as the sync address,
@@ -34,7 +34,7 @@ func runtime_setProfLabel(labels unsafe.Pointer) {
        getg().labels = labels
 }
 
-//go:linkname runtime_getProfLabel runtime..z2fpprof.runtime_getProfLabel
+//go:linkname runtime_getProfLabel runtime_1pprof.runtime__getProfLabel
 func runtime_getProfLabel() unsafe.Pointer {
        return getg().labels
 }
index 358df111b553741da9c10a0818af4bda01b4b597..9c43ce569070fa17ad94483bd9a77e66275de853 100644 (file)
@@ -11,14 +11,14 @@ import _ "unsafe" // for go:linkname
 // maxstacksize.
 var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real
 
-//go:linkname setMaxStack runtime..z2fdebug.setMaxStack
+//go:linkname setMaxStack runtime_1debug.setMaxStack
 func setMaxStack(in int) (out int) {
        out = int(maxstacksize)
        maxstacksize = uintptr(in)
        return out
 }
 
-//go:linkname setPanicOnFault runtime..z2fdebug.setPanicOnFault
+//go:linkname setPanicOnFault runtime_1debug.setPanicOnFault
 func setPanicOnFault(new bool) (old bool) {
        _g_ := getg()
        old = _g_.paniconfault
index abc5eab00d5052aaa473f004fb0930fba07fc055..5af28aec97488be1762b4415456bb5d4a48e9a06 100644 (file)
@@ -51,13 +51,13 @@ func tickspersecond() int64 {
 var envs []string
 var argslice []string
 
-//go:linkname syscall_runtime_envs syscall.runtime_envs
+//go:linkname syscall_runtime_envs syscall.runtime__envs
 func syscall_runtime_envs() []string { return append([]string{}, envs...) }
 
 //go:linkname syscall_Getpagesize syscall.Getpagesize
 func syscall_Getpagesize() int { return int(physPageSize) }
 
-//go:linkname os_runtime_args os.runtime_args
+//go:linkname os_runtime_args os.runtime__args
 func os_runtime_args() []string { return append([]string{}, argslice...) }
 
 //go:linkname syscall_Exit syscall.Exit
index a8a53d3052c8b60e85225bbcbac25e4bc86d7520..39969d19a7e41df225e45359bc0d1763d4609adb 100644 (file)
@@ -398,7 +398,7 @@ func parsedebugvars() {
        traceback_env = traceback_cache
 }
 
-//go:linkname setTraceback runtime..z2fdebug.SetTraceback
+//go:linkname setTraceback runtime_1debug.SetTraceback
 func setTraceback(level string) {
        var t uint32
        switch level {
index c1418b3da436222dc52277236d254400653053d3..9a288806fa560a009db0d723b9156814859ff456 100644 (file)
@@ -51,27 +51,27 @@ var semtable [semTabSize]struct {
        pad  [cpu.CacheLinePadSize - unsafe.Sizeof(semaRoot{})]byte
 }
 
-//go:linkname sync_runtime_Semacquire sync.runtime_Semacquire
+//go:linkname sync_runtime_Semacquire sync.runtime__Semacquire
 func sync_runtime_Semacquire(addr *uint32) {
        semacquire1(addr, false, semaBlockProfile, 0)
 }
 
-//go:linkname poll_runtime_Semacquire internal..z2fpoll.runtime_Semacquire
+//go:linkname poll_runtime_Semacquire internal_1poll.runtime__Semacquire
 func poll_runtime_Semacquire(addr *uint32) {
        semacquire1(addr, false, semaBlockProfile, 0)
 }
 
-//go:linkname sync_runtime_Semrelease sync.runtime_Semrelease
+//go:linkname sync_runtime_Semrelease sync.runtime__Semrelease
 func sync_runtime_Semrelease(addr *uint32, handoff bool, skipframes int) {
        semrelease1(addr, handoff, skipframes)
 }
 
-//go:linkname sync_runtime_SemacquireMutex sync.runtime_SemacquireMutex
+//go:linkname sync_runtime_SemacquireMutex sync.runtime__SemacquireMutex
 func sync_runtime_SemacquireMutex(addr *uint32, lifo bool, skipframes int) {
        semacquire1(addr, lifo, semaBlockProfile|semaMutexProfile, skipframes)
 }
 
-//go:linkname poll_runtime_Semrelease internal..z2fpoll.runtime_Semrelease
+//go:linkname poll_runtime_Semrelease internal_1poll.runtime__Semrelease
 func poll_runtime_Semrelease(addr *uint32) {
        semrelease(addr)
 }
@@ -475,7 +475,7 @@ func less(a, b uint32) bool {
 // notifyListAdd adds the caller to a notify list such that it can receive
 // notifications. The caller must eventually call notifyListWait to wait for
 // such a notification, passing the returned ticket number.
-//go:linkname notifyListAdd sync.runtime_notifyListAdd
+//go:linkname notifyListAdd sync.runtime__notifyListAdd
 func notifyListAdd(l *notifyList) uint32 {
        // This may be called concurrently, for example, when called from
        // sync.Cond.Wait while holding a RWMutex in read mode.
@@ -484,7 +484,7 @@ func notifyListAdd(l *notifyList) uint32 {
 
 // notifyListWait waits for a notification. If one has been sent since
 // notifyListAdd was called, it returns immediately. Otherwise, it blocks.
-//go:linkname notifyListWait sync.runtime_notifyListWait
+//go:linkname notifyListWait sync.runtime__notifyListWait
 func notifyListWait(l *notifyList, t uint32) {
        lockWithRank(&l.lock, lockRankNotifyList)
 
@@ -518,7 +518,7 @@ func notifyListWait(l *notifyList, t uint32) {
 }
 
 // notifyListNotifyAll notifies all entries in the list.
-//go:linkname notifyListNotifyAll sync.runtime_notifyListNotifyAll
+//go:linkname notifyListNotifyAll sync.runtime__notifyListNotifyAll
 func notifyListNotifyAll(l *notifyList) {
        // Fast-path: if there are no new waiters since the last notification
        // we don't need to acquire the lock.
@@ -550,7 +550,7 @@ func notifyListNotifyAll(l *notifyList) {
 }
 
 // notifyListNotifyOne notifies one entry in the list.
-//go:linkname notifyListNotifyOne sync.runtime_notifyListNotifyOne
+//go:linkname notifyListNotifyOne sync.runtime__notifyListNotifyOne
 func notifyListNotifyOne(l *notifyList) {
        // Fast-path: if there are no new waiters since the last notification
        // we don't need to acquire the lock at all.
@@ -603,7 +603,7 @@ func notifyListNotifyOne(l *notifyList) {
        unlock(&l.lock)
 }
 
-//go:linkname notifyListCheck sync.runtime_notifyListCheck
+//go:linkname notifyListCheck sync.runtime__notifyListCheck
 func notifyListCheck(sz uintptr) {
        if sz != unsafe.Sizeof(notifyList{}) {
                print("runtime: bad notifyList size - sync=", sz, " runtime=", unsafe.Sizeof(notifyList{}), "\n")
@@ -611,7 +611,7 @@ func notifyListCheck(sz uintptr) {
        }
 }
 
-//go:linkname sync_nanotime sync.runtime_nanotime
+//go:linkname sync_nanotime sync.runtime__nanotime
 func sync_nanotime() int64 {
        return nanotime()
 }
index 7d1028eac29623abfd57b88acd16f3a52743e6c7..ed024e1281329a0fe244ebc5da65e3fbf9365cda 100644 (file)
@@ -121,7 +121,7 @@ Send:
 
 // Called to receive the next queued signal.
 // Must only be called from a single goroutine at a time.
-//go:linkname signal_recv os..z2fsignal.signal_recv
+//go:linkname signal_recv os_1signal.signal__recv
 func signal_recv() uint32 {
        for {
                // Serve any signals from local copy.
@@ -169,7 +169,7 @@ func signal_recv() uint32 {
 // the signal(s) in question, and here we are just waiting to make sure
 // that all the signals have been delivered to the user channels
 // by the os/signal package.
-//go:linkname signalWaitUntilIdle os..z2fsignal.signalWaitUntilIdle
+//go:linkname signalWaitUntilIdle os_1signal.signalWaitUntilIdle
 func signalWaitUntilIdle() {
        // Although the signals we care about have been removed from
        // sig.wanted, it is possible that another thread has received
@@ -189,7 +189,7 @@ func signalWaitUntilIdle() {
 }
 
 // Must only be called from a single goroutine at a time.
-//go:linkname signal_enable os..z2fsignal.signal_enable
+//go:linkname signal_enable os_1signal.signal__enable
 func signal_enable(s uint32) {
        if !sig.inuse {
                // This is the first call to signal_enable. Initialize.
@@ -217,7 +217,7 @@ func signal_enable(s uint32) {
 }
 
 // Must only be called from a single goroutine at a time.
-//go:linkname signal_disable os..z2fsignal.signal_disable
+//go:linkname signal_disable os_1signal.signal__disable
 func signal_disable(s uint32) {
        if s >= uint32(len(sig.wanted)*32) {
                return
@@ -230,7 +230,7 @@ func signal_disable(s uint32) {
 }
 
 // Must only be called from a single goroutine at a time.
-//go:linkname signal_ignore os..z2fsignal.signal_ignore
+//go:linkname signal_ignore os_1signal.signal__ignore
 func signal_ignore(s uint32) {
        if s >= uint32(len(sig.wanted)*32) {
                return
@@ -257,7 +257,7 @@ func sigInitIgnored(s uint32) {
 }
 
 // Checked by signal handlers.
-//go:linkname signal_ignored os..z2fsignal.signal_ignored
+//go:linkname signal_ignored os_1signal.signal__ignored
 func signal_ignored(s uint32) bool {
        i := atomic.Load(&sig.ignored[s/32])
        return i&(1<<(s&31)) != 0
index bb0b61d61314a1514621fc18bed05b062ba63f65..22a2b13977dc5c5dfb09597a314a29e199996fc0 100644 (file)
@@ -5,6 +5,7 @@
 package runtime
 
 import (
+       "internal/bytealg"
        _ "unsafe" // for go:linkname
 )
 
@@ -119,7 +120,7 @@ func pcInlineCallers(pc uintptr, locbuf *location, max int32) int32
 // runtime_expandFinalInlineFrame expands the final pc in stk to include all
 // "callers" if pc is inline.
 //
-//go:linkname runtime_expandFinalInlineFrame runtime..z2fpprof.runtime_expandFinalInlineFrame
+//go:linkname runtime_expandFinalInlineFrame runtime_1pprof.runtime__expandFinalInlineFrame
 func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr {
        if len(stk) == 0 {
                return stk
@@ -210,42 +211,62 @@ func hexDigitsToRune(digits []byte, ndig int) rune {
        return rune(result)
 }
 
-// Perform an in-place decoding on the input byte slice. This looks
-// for "..z<hex 2 >", "..u<hex x 4>" and "..U<hex x 8>" and overwrites
-// with the encoded bytes corresponding to the unicode in question.
-// Return value is the number of bytes taken by the result.
-
+// decodeIdentifier performs an in-place decoding on the input byte slice.
+// This undoes the compiler underscore mangling.
+// Returns the number of bytes used by the result.
 func decodeIdentifier(bsl []byte) int {
+       underscoreCodes := map[byte]byte{
+               '_': '_',
+               '0': '.',
+               '1': '/',
+               '2': '*',
+               '3': ',',
+               '4': '{',
+               '5': '}',
+               '6': '[',
+               '7': ']',
+               '8': '(',
+               '9': ')',
+               'a': '"',
+               'b': ' ',
+               'c': ';',
+       }
+
        j := 0
        for i := 0; i < len(bsl); i++ {
                b := bsl[i]
+               if b != '_' || i+1 >= len(bsl) {
+                       bsl[j] = b
+                       j++
+                       continue
+               }
+
+               if d, ok := underscoreCodes[bsl[i+1]]; ok {
+                       i++
+                       bsl[j] = d
+                       j++
+                       continue
+               }
+
+               rlen := 0
+               switch bsl[i+1] {
+               case 'x':
+                       rlen = 2
+               case 'u':
+                       rlen = 4
+               case 'U':
+                       rlen = 8
+               }
 
-               if i+1 < len(bsl) && bsl[i] == '.' && bsl[i+1] == '.' {
-                       if i+4 < len(bsl) && bsl[i+2] == 'z' {
-                               digits := bsl[i+3:]
-                               r := hexDigitsToRune(digits, 2)
-                               nc := encoderune(bsl[j:], r)
-                               j += nc
-                               i += 4
-                               continue
-                       } else if i+6 < len(bsl) && bsl[i+2] == 'u' {
-                               digits := bsl[i+3:]
-                               r := hexDigitsToRune(digits, 4)
-                               nc := encoderune(bsl[j:], r)
-                               j += nc
-                               i += 6
-                               continue
-                       } else if i+10 < len(bsl) && bsl[i+2] == 'U' {
-                               digits := bsl[i+3:]
-                               r := hexDigitsToRune(digits, 8)
-                               nc := encoderune(bsl[j:], r)
-                               j += nc
-                               i += 10
-                               continue
-                       }
+               if rlen > 0 && i+1+rlen < len(bsl) {
+                       r := hexDigitsToRune(bsl[i+2:], rlen)
+                       nc := encoderune(bsl[j:], r)
+                       j += nc
+                       i += rlen + 1
+               } else {
+                       bsl[j] = b
+                       j++
                }
-               bsl[j] = b
-               j += 1
        }
        return j
 }
@@ -254,6 +275,11 @@ func decodeIdentifier(bsl []byte) int {
 // as used in the compiler.
 
 func demangleSymbol(s string) string {
+       if bytealg.IndexByteString(s, '.') < 0 {
+               // A symbol with no '.' is not a Go symbol.
+               return s
+       }
+
        bsl := []byte(s)
        nchars := decodeIdentifier(bsl)
        bsl = bsl[:nchars]
index ce185fc37ceb210c6311d29b0d3a59bcfc28fb8d..b05f30a928a362f30aba8b5ae3f23f58ed092f44 100644 (file)
@@ -1152,7 +1152,7 @@ func traceNextGC() {
 // To access runtime functions from runtime/trace.
 // See runtime/trace/annotation.go
 
-//go:linkname trace_userTaskCreate runtime..z2ftrace.userTaskCreate
+//go:linkname trace_userTaskCreate runtime_1trace.userTaskCreate
 func trace_userTaskCreate(id, parentID uint64, taskType string) {
        if !trace.enabled {
                return
@@ -1170,12 +1170,12 @@ func trace_userTaskCreate(id, parentID uint64, taskType string) {
        traceReleaseBuffer(pid)
 }
 
-//go:linkname trace_userTaskEnd runtime..z2ftrace.userTaskEnd
+//go:linkname trace_userTaskEnd runtime_1trace.userTaskEnd
 func trace_userTaskEnd(id uint64) {
        traceEvent(traceEvUserTaskEnd, 2, id)
 }
 
-//go:linkname trace_userRegion runtime..z2ftrace.userRegion
+//go:linkname trace_userRegion runtime_1trace.userRegion
 func trace_userRegion(id, mode uint64, name string) {
        if !trace.enabled {
                return
@@ -1192,7 +1192,7 @@ func trace_userRegion(id, mode uint64, name string) {
        traceReleaseBuffer(pid)
 }
 
-//go:linkname trace_userLog runtime..z2ftrace.userLog
+//go:linkname trace_userLog runtime_1trace.userLog
 func trace_userLog(id uint64, category, message string) {
        if !trace.enabled {
                return
index 1ba91af76ae170e8f96964ed7ffce2d6b026fb41..ebdbefcb24dd7829ffbaa186607ad6a7b82e0532 100644 (file)
@@ -184,10 +184,10 @@ func showfuncinfo(name string, firstFrame bool) bool {
 // isExportedRuntime reports whether name is an exported runtime function.
 // It is only for runtime functions, so ASCII A-Z is fine. Here also check
 // for mangled functions from runtime/<...>, which will be prefixed with
-// "runtime..z2f".
+// "runtime_1".
 func isExportedRuntime(name string) bool {
        const n = len("runtime.")
-       if hasPrefix(name, "runtime..z2f") {
+       if hasPrefix(name, "runtime_1") {
                return true
        }
        return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z'
index 90a4ff3f9224639a70ea3d4f5bba4f3dd14df50c..71d51aaef473ac20955cade8e565a6e6b514bd7f 100644 (file)
@@ -9,7 +9,7 @@
 #include "runtime.h"
 
 int32_t SwapInt32 (int32_t *, int32_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapInt32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.SwapInt32")
   __attribute__ ((no_split_stack));
 
 int32_t
@@ -19,7 +19,7 @@ SwapInt32 (int32_t *addr, int32_t new)
 }
 
 int64_t SwapInt64 (int64_t *, int64_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapInt64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.SwapInt64")
   __attribute__ ((no_split_stack));
 
 int64_t
@@ -31,7 +31,7 @@ SwapInt64 (int64_t *addr, int64_t new)
 }
 
 uint32_t SwapUint32 (uint32_t *, uint32_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapUint32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.SwapUint32")
   __attribute__ ((no_split_stack));
 
 uint32_t
@@ -41,7 +41,7 @@ SwapUint32 (uint32_t *addr, uint32_t new)
 }
 
 uint64_t SwapUint64 (uint64_t *, uint64_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapUint64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.SwapUint64")
   __attribute__ ((no_split_stack));
 
 uint64_t
@@ -53,7 +53,7 @@ SwapUint64 (uint64_t *addr, uint64_t new)
 }
 
 uintptr_t SwapUintptr (uintptr_t *, uintptr_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapUintptr")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.SwapUintptr")
   __attribute__ ((no_split_stack));
 
 uintptr_t
@@ -63,7 +63,7 @@ SwapUintptr (uintptr_t *addr, uintptr_t new)
 }
 
 _Bool CompareAndSwapInt32 (int32_t *, int32_t, int32_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapInt32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.CompareAndSwapInt32")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -74,7 +74,7 @@ CompareAndSwapInt32 (int32_t *val, int32_t old, int32_t new)
 }
 
 _Bool CompareAndSwapInt64 (int64_t *, int64_t, int64_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapInt64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.CompareAndSwapInt64")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -87,7 +87,7 @@ CompareAndSwapInt64 (int64_t *val, int64_t old, int64_t new)
 }
 
 _Bool CompareAndSwapUint32 (uint32_t *, uint32_t, uint32_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapUint32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.CompareAndSwapUint32")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -98,7 +98,7 @@ CompareAndSwapUint32 (uint32_t *val, uint32_t old, uint32_t new)
 }
 
 _Bool CompareAndSwapUint64 (uint64_t *, uint64_t, uint64_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapUint64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.CompareAndSwapUint64")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -111,7 +111,7 @@ CompareAndSwapUint64 (uint64_t *val, uint64_t old, uint64_t new)
 }
 
 _Bool CompareAndSwapUintptr (uintptr_t *, uintptr_t, uintptr_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapUintptr")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.CompareAndSwapUintptr")
   __attribute__ ((no_split_stack));
 
 _Bool
@@ -122,7 +122,7 @@ CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
 }
 
 int32_t AddInt32 (int32_t *, int32_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddInt32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.AddInt32")
   __attribute__ ((no_split_stack));
 
 int32_t
@@ -132,7 +132,7 @@ AddInt32 (int32_t *val, int32_t delta)
 }
 
 uint32_t AddUint32 (uint32_t *, uint32_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddUint32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.AddUint32")
   __attribute__ ((no_split_stack));
 
 uint32_t
@@ -142,7 +142,7 @@ AddUint32 (uint32_t *val, uint32_t delta)
 }
 
 int64_t AddInt64 (int64_t *, int64_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddInt64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.AddInt64")
   __attribute__ ((no_split_stack));
 
 int64_t
@@ -154,7 +154,7 @@ AddInt64 (int64_t *val, int64_t delta)
 }
 
 uint64_t AddUint64 (uint64_t *, uint64_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddUint64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.AddUint64")
   __attribute__ ((no_split_stack));
 
 uint64_t
@@ -166,7 +166,7 @@ AddUint64 (uint64_t *val, uint64_t delta)
 }
 
 uintptr_t AddUintptr (uintptr_t *, uintptr_t)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddUintptr")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.AddUintptr")
   __attribute__ ((no_split_stack));
 
 uintptr_t
@@ -176,7 +176,7 @@ AddUintptr (uintptr_t *val, uintptr_t delta)
 }
 
 int32_t LoadInt32 (int32_t *addr)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadInt32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.LoadInt32")
   __attribute__ ((no_split_stack));
 
 int32_t
@@ -186,7 +186,7 @@ LoadInt32 (int32_t *addr)
 }
 
 int64_t LoadInt64 (int64_t *addr)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadInt64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.LoadInt64")
   __attribute__ ((no_split_stack));
 
 int64_t
@@ -198,7 +198,7 @@ LoadInt64 (int64_t *addr)
 }
 
 uint32_t LoadUint32 (uint32_t *addr)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUint32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.LoadUint32")
   __attribute__ ((no_split_stack));
 
 uint32_t
@@ -208,7 +208,7 @@ LoadUint32 (uint32_t *addr)
 }
 
 uint64_t LoadUint64 (uint64_t *addr)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUint64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.LoadUint64")
   __attribute__ ((no_split_stack));
 
 uint64_t
@@ -220,7 +220,7 @@ LoadUint64 (uint64_t *addr)
 }
 
 uintptr_t LoadUintptr (uintptr_t *addr)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUintptr")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.LoadUintptr")
   __attribute__ ((no_split_stack));
 
 uintptr_t
@@ -230,7 +230,7 @@ LoadUintptr (uintptr_t *addr)
 }
 
 void *LoadPointer (void **addr)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadPointer")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.LoadPointer")
   __attribute__ ((no_split_stack));
 
 void *
@@ -240,7 +240,7 @@ LoadPointer (void **addr)
 }
 
 void StoreInt32 (int32_t *addr, int32_t val)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreInt32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.StoreInt32")
   __attribute__ ((no_split_stack));
 
 void
@@ -250,7 +250,7 @@ StoreInt32 (int32_t *addr, int32_t val)
 }
 
 void StoreInt64 (int64_t *addr, int64_t val)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreInt64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.StoreInt64")
   __attribute__ ((no_split_stack));
 
 void
@@ -262,7 +262,7 @@ StoreInt64 (int64_t *addr, int64_t val)
 }
 
 void StoreUint32 (uint32_t *addr, uint32_t val)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreUint32")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.StoreUint32")
   __attribute__ ((no_split_stack));
 
 void
@@ -272,7 +272,7 @@ StoreUint32 (uint32_t *addr, uint32_t val)
 }
 
 void StoreUint64 (uint64_t *addr, uint64_t val)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreUint64")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.StoreUint64")
   __attribute__ ((no_split_stack));
 
 void
@@ -284,7 +284,7 @@ StoreUint64 (uint64_t *addr, uint64_t val)
 }
 
 void StoreUintptr (uintptr_t *addr, uintptr_t val)
-  __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreUintptr")
+  __asm__ (GOSYM_PREFIX "sync_1atomic.StoreUintptr")
   __attribute__ ((no_split_stack));
 
 void
index b030f5e918ed3d5f4328f53d83ba03da38f91799..1ec5f87870cd64f7f605fe5bcef3f4d8d23efb49 100644 (file)
    the libffi type values.  */
 
 ffi_type *go_ffi_type_pointer(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_pointer(void) __asm__ ("runtime.ffi_type_pointer");
+ffi_type *go_ffi_type_pointer(void) __asm__ ("runtime.ffi__type__pointer");
 ffi_type *go_ffi_type_sint8(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_sint8(void) __asm__ ("runtime.ffi_type_sint8");
+ffi_type *go_ffi_type_sint8(void) __asm__ ("runtime.ffi__type__sint8");
 ffi_type *go_ffi_type_sint16(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_sint16(void) __asm__ ("runtime.ffi_type_sint16");
+ffi_type *go_ffi_type_sint16(void) __asm__ ("runtime.ffi__type__sint16");
 ffi_type *go_ffi_type_sint32(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_sint32(void) __asm__ ("runtime.ffi_type_sint32");
+ffi_type *go_ffi_type_sint32(void) __asm__ ("runtime.ffi__type__sint32");
 ffi_type *go_ffi_type_sint64(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_sint64(void) __asm__ ("runtime.ffi_type_sint64");
+ffi_type *go_ffi_type_sint64(void) __asm__ ("runtime.ffi__type__sint64");
 ffi_type *go_ffi_type_uint8(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_uint8(void) __asm__ ("runtime.ffi_type_uint8");
+ffi_type *go_ffi_type_uint8(void) __asm__ ("runtime.ffi__type__uint8");
 ffi_type *go_ffi_type_uint16(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_uint16(void) __asm__ ("runtime.ffi_type_uint16");
+ffi_type *go_ffi_type_uint16(void) __asm__ ("runtime.ffi__type__uint16");
 ffi_type *go_ffi_type_uint32(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_uint32(void) __asm__ ("runtime.ffi_type_uint32");
+ffi_type *go_ffi_type_uint32(void) __asm__ ("runtime.ffi__type__uint32");
 ffi_type *go_ffi_type_uint64(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_uint64(void) __asm__ ("runtime.ffi_type_uint64");
+ffi_type *go_ffi_type_uint64(void) __asm__ ("runtime.ffi__type__uint64");
 ffi_type *go_ffi_type_float(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_float(void) __asm__ ("runtime.ffi_type_float");
+ffi_type *go_ffi_type_float(void) __asm__ ("runtime.ffi__type__float");
 ffi_type *go_ffi_type_double(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_double(void) __asm__ ("runtime.ffi_type_double");
+ffi_type *go_ffi_type_double(void) __asm__ ("runtime.ffi__type__double");
 ffi_type *go_ffi_type_complex_float(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_complex_float(void) __asm__ ("runtime.ffi_type_complex_float");
+ffi_type *go_ffi_type_complex_float(void) __asm__ ("runtime.ffi__type__complex__float");
 ffi_type *go_ffi_type_complex_double(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_complex_double(void) __asm__ ("runtime.ffi_type_complex_double");
+ffi_type *go_ffi_type_complex_double(void) __asm__ ("runtime.ffi__type__complex__double");
 ffi_type *go_ffi_type_void(void) __attribute__ ((no_split_stack));
-ffi_type *go_ffi_type_void(void) __asm__ ("runtime.ffi_type_void");
+ffi_type *go_ffi_type_void(void) __asm__ ("runtime.ffi__type__void");
 
 _Bool go_ffi_supports_complex(void) __attribute__ ((no_split_stack));
-_Bool go_ffi_supports_complex(void) __asm__ ("runtime.ffi_supports_complex");
+_Bool go_ffi_supports_complex(void) __asm__ ("runtime.ffi__supports__complex");
 
 ffi_type *
 go_ffi_type_pointer(void)
index 81b1775d2c903a74ba5e3c0384cec40796b27789..08987def8af8d25cc7aacb1bdb7ff4d974047586 100644 (file)
@@ -13,7 +13,7 @@
 
 /* Set the C environment from Go.  This is called by syscall.Setenv.  */
 
-void setenv_c (String, String) __asm__ (GOSYM_PREFIX "syscall.setenv_c");
+void setenv_c (String, String) __asm__ (GOSYM_PREFIX "syscall.setenv__c");
 
 void
 setenv_c (String k, String v)
index 364878ebcfee923594887474d73bbe36927e3db6..e24bfb25d1e256e02d0c8c1c6d738c3a20928fa1 100644 (file)
@@ -72,7 +72,7 @@ const struct _type unsafe_Pointer =
    it to be defined elsewhere.  */
 
 extern const struct ptrtype pointer_unsafe_Pointer
-  __asm__ (GOSYM_PREFIX "type...1unsafe.Pointer");
+  __asm__ (GOSYM_PREFIX "unsafe.Pointer..p");
 
 /* The reflection string.  */
 #define PREFLECTION "*unsafe.Pointer"
@@ -83,7 +83,7 @@ static const String preflection_string =
 };
 
 extern const byte pointer_unsafe_Pointer_gc[]
-  __asm__ (GOSYM_PREFIX "type...1unsafe.Pointer..g");
+  __asm__ (GOSYM_PREFIX "unsafe.Pointer..p..g");
 
 const byte pointer_unsafe_Pointer_gc[] = { 1 };
 
index 21359975f2b3e9053496482ef853ddf4192bab0b..4b5058a220fb14751f0015c65fb0a2d51f91a2e3 100644 (file)
@@ -14,7 +14,7 @@
 /* Unset an environment variable from Go.  This is called by
    syscall.Unsetenv.  */
 
-void unsetenv_c (String) __asm__ (GOSYM_PREFIX "syscall.unsetenv_c");
+void unsetenv_c (String) __asm__ (GOSYM_PREFIX "syscall.unsetenv__c");
 
 void
 unsetenv_c (String k)
index f46eaea07b9af77f046fff14e6f1d5c9f78b7a58..3a65d44f349ac5c188e38a6576dd54bd1de4dbd2 100644 (file)
@@ -440,7 +440,7 @@ void        runtime_freedefer(Defer*);
 
 extern void _cgo_wait_runtime_init_done (void);
 extern void _cgo_notify_runtime_init_done (void)
-  __asm__ (GOSYM_PREFIX "runtime._cgo_notify_runtime_init_done");
+  __asm__ (GOSYM_PREFIX "runtime.__cgo__notify__runtime__init__done");
 extern _Bool runtime_iscgo;
 extern uintptr __go_end __attribute__ ((weak));
 extern void *getitab(const struct _type *, const struct _type *, _Bool)
index 0fd64194360e2fa5a3832f05b134ae044a83e219..8c3c5ca1b32375fc3f7a9e6a5d5044be8722be78 100755 (executable)
@@ -496,7 +496,8 @@ testname() {
 localname() {
        # The package main has been renamed to __main__ when imported.
        # Adjust its uses.
-       echo $1 | sed 's/^main\./__main__./'
+       # Also demangle underscores.
+       echo $1 | sed 's/^main\./__main__./' | sed 's/__/_/'
 }
 
 # Takes a list of tests derived from 'nm' output (whose symbols are mangled)
@@ -504,7 +505,7 @@ localname() {
 # Example:
 #
 #    Original symbol:   foo/bar/leaf.Mumble
-#    Mangled symbol:    foo..z2fbar..z2fleaf.Mumble
+#    Mangled symbol:    foo_1fbar_1leaf.Mumble
 #    Returned:          leaf.Mumble
 #
 symtogo() {
@@ -522,7 +523,7 @@ symtogo() {
     if expr "$tp" : '^type\.\.' >/dev/null 2>&1; then
       continue
     fi
-    s=$(echo "$tp" | sed -e 's/\.\.z2f/%/g' | sed -e 's/.*%//')
+    s=$(echo "$tp" | sed -e 's/_1/%/g' | sed -e 's/.*%//')
     # Screen out methods (X.Y.Z).
     if ! expr "$s" : '^[^.]*\.[^.]*$' >/dev/null 2>&1; then
       continue