From a01dda3c23b836754814fab1cab949a1bbc641e8 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 16 Nov 2020 20:06:53 -0800 Subject: [PATCH] compiler, libgo: change mangling scheme 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 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/ast-dump.cc | 6 +- gcc/go/gofrontend/export.cc | 8 +- gcc/go/gofrontend/expressions.cc | 38 +- gcc/go/gofrontend/go-encode-id.cc | 289 ++++--- gcc/go/gofrontend/go-encode-id.h | 13 - gcc/go/gofrontend/gogo.cc | 252 +++--- gcc/go/gofrontend/gogo.h | 173 +++- gcc/go/gofrontend/names.cc | 759 ++++++++++-------- gcc/go/gofrontend/runtime.def | 34 +- gcc/go/gofrontend/types.cc | 105 +-- gcc/go/gofrontend/types.h | 20 +- libgo/configure | 2 +- libgo/configure.ac | 2 +- libgo/go/cmd/cgo/out.go | 23 +- libgo/go/cmd/internal/pkgpath/pkgpath.go | 68 +- libgo/go/cmd/internal/pkgpath/pkgpath_test.go | 22 +- .../go/go/internal/srcimporter/srcimporter.go | 2 +- libgo/go/internal/bytealg/bytealg.c | 10 +- libgo/go/internal/cpu/cpu_gccgo.c | 20 +- libgo/go/log/syslog/syslog_c.c | 2 +- libgo/go/runtime/atomic_pointer.go | 12 +- libgo/go/runtime/chan.go | 2 +- libgo/go/runtime/cpuprof.go | 4 +- libgo/go/runtime/debug.go | 2 +- libgo/go/runtime/heapdump.go | 2 +- libgo/go/runtime/iface.go | 2 +- libgo/go/runtime/internal/atomic/atomic.c | 56 +- libgo/go/runtime/malloc.go | 6 +- libgo/go/runtime/map.go | 2 +- libgo/go/runtime/mbarrier.go | 2 +- libgo/go/runtime/mgc.go | 4 +- libgo/go/runtime/mheap.go | 2 +- libgo/go/runtime/mprof.go | 2 +- libgo/go/runtime/mstats.go | 2 +- libgo/go/runtime/net_plan9.go | 4 +- libgo/go/runtime/netpoll.go | 18 +- libgo/go/runtime/pprof/mprof_test.go | 20 +- libgo/go/runtime/pprof/pprof_test.go | 4 +- libgo/go/runtime/preempt.go | 2 +- libgo/go/runtime/proc.go | 26 +- libgo/go/runtime/proflabel.go | 4 +- libgo/go/runtime/rdebug.go | 4 +- libgo/go/runtime/runtime.go | 4 +- libgo/go/runtime/runtime1.go | 2 +- libgo/go/runtime/sema.go | 22 +- libgo/go/runtime/sigqueue.go | 12 +- libgo/go/runtime/symtab.go | 88 +- libgo/go/runtime/trace.go | 8 +- libgo/go/runtime/traceback_gccgo.go | 4 +- libgo/go/sync/atomic/atomic.c | 52 +- libgo/runtime/go-ffi.c | 30 +- libgo/runtime/go-setenv.c | 2 +- libgo/runtime/go-unsafe-pointer.c | 4 +- libgo/runtime/go-unsetenv.c | 2 +- libgo/runtime/runtime.h | 2 +- libgo/testsuite/gotest | 7 +- 57 files changed, 1327 insertions(+), 944 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 1f3c25ce710..9545a598738 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/gcc/go/gofrontend/ast-dump.cc b/gcc/go/gofrontend/ast-dump.cc index a3cbda9debc..eca0bf1fad2 100644 --- a/gcc/go/gofrontend/ast-dump.cc +++ b/gcc/go/gofrontend/ast-dump.cc @@ -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 diff --git a/gcc/go/gofrontend/export.cc b/gcc/go/gofrontend/export.cc index 90a5f6dbcec..e99c680f709 100644 --- a/gcc/go/gofrontend/export.cc +++ b/gcc/go/gofrontend/export.cc @@ -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(); } }; diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index e76bc6997c1..6bc93488939 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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); diff --git a/gcc/go/gofrontend/go-encode-id.cc b/gcc/go/gofrontend/go-encode-id.cc index 550da9759f6..7ab65f513b3 100644 --- a/gcc/go/gofrontend/go-encode-id.cc +++ b/gcc/go/gofrontend/go-encode-id.cc @@ -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; -} diff --git a/gcc/go/gofrontend/go-encode-id.h b/gcc/go/gofrontend/go-encode-id.h index 2d09b0c545d..cbafd5447d6 100644 --- a/gcc/go/gofrontend/go-encode-id.h +++ b/gcc/go/gofrontend/go-encode-id.h @@ -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) diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index f40f13129e6..93a4a5773a2 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -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& 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) { diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 45be1732aa0..f22d47656db 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -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 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&, std::vector&, diff --git a/gcc/go/gofrontend/names.cc b/gcc/go/gofrontend/names.cc index 1f0a54502db..0097417cff0 100644 --- a/gcc/go/gofrontend/names.cc +++ b/gcc/go/gofrontend/names.cc @@ -15,53 +15,68 @@ // 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 @@ -91,46 +106,51 @@ // 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 @@ -147,7 +167,7 @@ // 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 @@ -161,109 +181,109 @@ // 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 ""; } diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def index 0796cbaadce..b608766cdaf 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -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. diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index f3bcf2eabd4..c4570b41a71 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -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; diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 9ac851699d2..5965d5a3fde 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -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 diff --git a/libgo/configure b/libgo/configure index e7379f87047..1d7d007f88e 100755 --- a/libgo/configure +++ b/libgo/configure @@ -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 diff --git a/libgo/configure.ac b/libgo/configure.ac index 80537f5f440..5013f4142a6 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -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(, ..) diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go index 2ab8425999f..05441398d7a 100644 --- a/libgo/go/cmd/cgo/out.go +++ b/libgo/go/cmd/cgo/out.go @@ -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 = ` diff --git a/libgo/go/cmd/internal/pkgpath/pkgpath.go b/libgo/go/cmd/internal/pkgpath/pkgpath.go index 0b24468be64..40a040a81af 100644 --- a/libgo/go/cmd/internal/pkgpath/pkgpath.go +++ b/libgo/go/cmd/internal/pkgpath/pkgpath.go @@ -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) +} diff --git a/libgo/go/cmd/internal/pkgpath/pkgpath_test.go b/libgo/go/cmd/internal/pkgpath/pkgpath_test.go index 7355f81baec..232e803a601 100644 --- a/libgo/go/cmd/internal/pkgpath/pkgpath_test.go +++ b/libgo/go/cmd/internal/pkgpath/pkgpath_test.go @@ -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) + } + } +} diff --git a/libgo/go/go/internal/srcimporter/srcimporter.go b/libgo/go/go/internal/srcimporter/srcimporter.go index 90bb3a9bc11..3a2ca9aba81 100644 --- a/libgo/go/go/internal/srcimporter/srcimporter.go +++ b/libgo/go/go/internal/srcimporter/srcimporter.go @@ -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) diff --git a/libgo/go/internal/bytealg/bytealg.c b/libgo/go/internal/bytealg/bytealg.c index 969732dfebc..6c08340b38f 100644 --- a/libgo/go/internal/bytealg/bytealg.c +++ b/libgo/go/internal/bytealg/bytealg.c @@ -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) diff --git a/libgo/go/internal/cpu/cpu_gccgo.c b/libgo/go/internal/cpu/cpu_gccgo.c index 6b40f0137a4..da26f4d7407 100644 --- a/libgo/go/internal/cpu/cpu_gccgo.c +++ b/libgo/go/internal/cpu/cpu_gccgo.c @@ -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() { diff --git a/libgo/go/log/syslog/syslog_c.c b/libgo/go/log/syslog/syslog_c.c index 36e76942ba9..329df404efd 100644 --- a/libgo/go/log/syslog/syslog_c.c +++ b/libgo/go/log/syslog/syslog_c.c @@ -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) diff --git a/libgo/go/runtime/atomic_pointer.go b/libgo/go/runtime/atomic_pointer.go index 49b0f2b84fd..029591394b4 100644 --- a/libgo/go/runtime/atomic_pointer.go +++ b/libgo/go/runtime/atomic_pointer.go @@ -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 { diff --git a/libgo/go/runtime/chan.go b/libgo/go/runtime/chan.go index b909d478d26..8e104f14140 100644 --- a/libgo/go/runtime/chan.go +++ b/libgo/go/runtime/chan.go @@ -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 diff --git a/libgo/go/runtime/cpuprof.go b/libgo/go/runtime/cpuprof.go index d39521094ec..43f0a6705f5 100644 --- a/libgo/go/runtime/cpuprof.go +++ b/libgo/go/runtime/cpuprof.go @@ -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 diff --git a/libgo/go/runtime/debug.go b/libgo/go/runtime/debug.go index 1202e362a5a..ff76580ee65 100644 --- a/libgo/go/runtime/debug.go +++ b/libgo/go/runtime/debug.go @@ -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 } diff --git a/libgo/go/runtime/heapdump.go b/libgo/go/runtime/heapdump.go index e8f16e90fe6..816d93c6ef0 100644 --- a/libgo/go/runtime/heapdump.go +++ b/libgo/go/runtime/heapdump.go @@ -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") diff --git a/libgo/go/runtime/iface.go b/libgo/go/runtime/iface.go index 5667ddb6b95..f9df1e0d79a 100644 --- a/libgo/go/runtime/iface.go +++ b/libgo/go/runtime/iface.go @@ -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 { diff --git a/libgo/go/runtime/internal/atomic/atomic.c b/libgo/go/runtime/internal/atomic/atomic.c index 8ae4d7b619d..9fed1a8bff1 100644 --- a/libgo/go/runtime/internal/atomic/atomic.c +++ b/libgo/go/runtime/internal/atomic/atomic.c @@ -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 diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go index 81351eefbb7..feb043ac2e9 100644 --- a/libgo/go/runtime/malloc.go +++ b/libgo/go/runtime/malloc.go @@ -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) } diff --git a/libgo/go/runtime/map.go b/libgo/go/runtime/map.go index b82977103c0..1155fee861c 100644 --- a/libgo/go/runtime/map.go +++ b/libgo/go/runtime/map.go @@ -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 diff --git a/libgo/go/runtime/mbarrier.go b/libgo/go/runtime/mbarrier.go index 836f85a0330..3bd8b34429d 100644 --- a/libgo/go/runtime/mbarrier.go +++ b/libgo/go/runtime/mbarrier.go @@ -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) } diff --git a/libgo/go/runtime/mgc.go b/libgo/go/runtime/mgc.go index 9dd7bff8a80..72479c23916 100644 --- a/libgo/go/runtime/mgc.go +++ b/libgo/go/runtime/mgc.go @@ -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 } diff --git a/libgo/go/runtime/mheap.go b/libgo/go/runtime/mheap.go index e73ee32efd4..755efd19772 100644 --- a/libgo/go/runtime/mheap.go +++ b/libgo/go/runtime/mheap.go @@ -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() }) diff --git a/libgo/go/runtime/mprof.go b/libgo/go/runtime/mprof.go index a4b135d90d0..afacf8fa70f 100644 --- a/libgo/go/runtime/mprof.go +++ b/libgo/go/runtime/mprof.go @@ -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) } diff --git a/libgo/go/runtime/mstats.go b/libgo/go/runtime/mstats.go index 4e2c66cea1f..85a0861b8cd 100644 --- a/libgo/go/runtime/mstats.go +++ b/libgo/go/runtime/mstats.go @@ -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) diff --git a/libgo/go/runtime/net_plan9.go b/libgo/go/runtime/net_plan9.go index 907c31975c7..38ff5a4ccb3 100644 --- a/libgo/go/runtime/net_plan9.go +++ b/libgo/go/runtime/net_plan9.go @@ -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 } diff --git a/libgo/go/runtime/netpoll.go b/libgo/go/runtime/netpoll.go index 72a136d363f..da00b57c276 100644 --- a/libgo/go/runtime/netpoll.go +++ b/libgo/go/runtime/netpoll.go @@ -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) diff --git a/libgo/go/runtime/pprof/mprof_test.go b/libgo/go/runtime/pprof/mprof_test.go index 625ab7de8c8..83bf572dd6c 100644 --- a/libgo/go/runtime/pprof/mprof_test.go +++ b/libgo/go/runtime/pprof/mprof_test.go @@ -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), }} diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go index ff86bce1211..7adf891afff 100644 --- a/libgo/go/runtime/pprof/pprof_test.go +++ b/libgo/go/runtime/pprof/pprof_test.go @@ -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) diff --git a/libgo/go/runtime/preempt.go b/libgo/go/runtime/preempt.go index 9a78bcf51b8..8452076dc7d 100644 --- a/libgo/go/runtime/preempt.go +++ b/libgo/go/runtime/preempt.go @@ -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 diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go index 0ca6c02bce8..6c720503c44 100644 --- a/libgo/go/runtime/proc.go +++ b/libgo/go/runtime/proc.go @@ -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) diff --git a/libgo/go/runtime/proflabel.go b/libgo/go/runtime/proflabel.go index fc655cc8019..1e1f3bfab13 100644 --- a/libgo/go/runtime/proflabel.go +++ b/libgo/go/runtime/proflabel.go @@ -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 } diff --git a/libgo/go/runtime/rdebug.go b/libgo/go/runtime/rdebug.go index 358df111b55..9c43ce56907 100644 --- a/libgo/go/runtime/rdebug.go +++ b/libgo/go/runtime/rdebug.go @@ -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 diff --git a/libgo/go/runtime/runtime.go b/libgo/go/runtime/runtime.go index abc5eab00d5..5af28aec974 100644 --- a/libgo/go/runtime/runtime.go +++ b/libgo/go/runtime/runtime.go @@ -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 diff --git a/libgo/go/runtime/runtime1.go b/libgo/go/runtime/runtime1.go index a8a53d3052c..39969d19a7e 100644 --- a/libgo/go/runtime/runtime1.go +++ b/libgo/go/runtime/runtime1.go @@ -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 { diff --git a/libgo/go/runtime/sema.go b/libgo/go/runtime/sema.go index c1418b3da43..9a288806fa5 100644 --- a/libgo/go/runtime/sema.go +++ b/libgo/go/runtime/sema.go @@ -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() } diff --git a/libgo/go/runtime/sigqueue.go b/libgo/go/runtime/sigqueue.go index 7d1028eac29..ed024e12813 100644 --- a/libgo/go/runtime/sigqueue.go +++ b/libgo/go/runtime/sigqueue.go @@ -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 diff --git a/libgo/go/runtime/symtab.go b/libgo/go/runtime/symtab.go index bb0b61d6131..22a2b13977d 100644 --- a/libgo/go/runtime/symtab.go +++ b/libgo/go/runtime/symtab.go @@ -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", "..u" and "..U" 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] diff --git a/libgo/go/runtime/trace.go b/libgo/go/runtime/trace.go index ce185fc37ce..b05f30a928a 100644 --- a/libgo/go/runtime/trace.go +++ b/libgo/go/runtime/trace.go @@ -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 diff --git a/libgo/go/runtime/traceback_gccgo.go b/libgo/go/runtime/traceback_gccgo.go index 1ba91af76ae..ebdbefcb24d 100644 --- a/libgo/go/runtime/traceback_gccgo.go +++ b/libgo/go/runtime/traceback_gccgo.go @@ -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' diff --git a/libgo/go/sync/atomic/atomic.c b/libgo/go/sync/atomic/atomic.c index 90a4ff3f922..71d51aaef47 100644 --- a/libgo/go/sync/atomic/atomic.c +++ b/libgo/go/sync/atomic/atomic.c @@ -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 diff --git a/libgo/runtime/go-ffi.c b/libgo/runtime/go-ffi.c index b030f5e918e..1ec5f87870c 100644 --- a/libgo/runtime/go-ffi.c +++ b/libgo/runtime/go-ffi.c @@ -16,36 +16,36 @@ 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) diff --git a/libgo/runtime/go-setenv.c b/libgo/runtime/go-setenv.c index 81b1775d2c9..08987def8af 100644 --- a/libgo/runtime/go-setenv.c +++ b/libgo/runtime/go-setenv.c @@ -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) diff --git a/libgo/runtime/go-unsafe-pointer.c b/libgo/runtime/go-unsafe-pointer.c index 364878ebcfe..e24bfb25d1e 100644 --- a/libgo/runtime/go-unsafe-pointer.c +++ b/libgo/runtime/go-unsafe-pointer.c @@ -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 }; diff --git a/libgo/runtime/go-unsetenv.c b/libgo/runtime/go-unsetenv.c index 21359975f2b..4b5058a220f 100644 --- a/libgo/runtime/go-unsetenv.c +++ b/libgo/runtime/go-unsetenv.c @@ -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) diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index f46eaea07b9..3a65d44f349 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -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) diff --git a/libgo/testsuite/gotest b/libgo/testsuite/gotest index 0fd64194360..8c3c5ca1b32 100755 --- a/libgo/testsuite/gotest +++ b/libgo/testsuite/gotest @@ -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 -- 2.30.2