-c948c2d770122932a05b62f653efa2c51f72d3ae
+b483d0e0a289ba5fcdbd0388cbc75393367ca870
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
// 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
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.
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();
}
};
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()
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();
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();
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;
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);
&& 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);
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,
{
// 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());
}
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);
#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)
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;
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.
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)
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;
}
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)
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;
-}
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)
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;
}
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
{
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));
}
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"));
// 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_);
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);
}
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);
}
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;
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*
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.
&& !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;
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.
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*
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_;
type = Type::make_pointer_type(type);
}
- const std::string n = Gogo::unpack_hidden_name(name);
Btype* btype = type->get_backend(gogo);
Bvariable* bvar;
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
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,
}
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());
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);
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)
{
// 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.
// 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
// 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
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
// 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&);
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
Named_object*
write_barrier_variable();
+ static bool
+ is_digits(const std::string&);
+
// Type used to map import names to packages.
typedef std::map<std::string, Package*> Imports;
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)
{ }
};
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);
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
Bvariable*
get_backend_variable(Gogo*, Named_object* function);
- // Return the external identifier for this object.
- std::string
- get_id(Gogo*);
-
// Get the backend representation of this object.
void
get_backend(Gogo*, std::vector<Bexpression*>&, std::vector<Btype*>&,
// assembly code. This is not used for names that appear only in the
// debug info.
-// Our external names contain only ASCII alphanumeric characters,
+// Our external names may contain only ASCII alphanumeric characters,
// underscore, and dot. (According to the GCC sources, dot is not
// permitted in assembler symbols on VxWorks and MMIX. We will not
-// support those systems.) Go names can not contain dot, so we rely
-// on using dot to encode Unicode characters, and to separate Go
-// symbols by package, and so forth. We assume that none of the
-// non-Go symbols in the final link will contain a dot, so we don't
-// worry about conflicts.
+// support those systems.) Go identifiers cannot contain dot, but Go
+// package paths can. Both Go identifiers and package paths can, of
+// course, contain all sorts of Unicode characters.
+//
+// The gc compiler uses names like "pkg.F", and it seems convenient to
+// emulate that. Therefore, we will use dot to separate different
+// components of names.
+//
+// Since package paths can contain dot, to avoid ambiguity we must
+// encode package paths such that they do not contain any dot. The
+// natural way to do this is to encode forbidden characters, including
+// dot, using a notation based on underscore. We will, of course,
+// have to encode underscore itself.
+//
+// Since we will be using an underscore encoding for the package path,
+// it seems reasonable to use the same encoding for Go identifiers.
+// This has the disadvantage that encoded Go identifiers will appear
+// to be valid Go identifiers with funny spellings, but it seems like
+// the best available approach.
+//
+// Therefore, in the following discussion we may assume that none of
+// the names under discussion contain a dot. All of the names we
+// generate for Go identifiers (that don't use //export or
+// //go:linkname) will contain at least one dot, as discussed below.
+// We assume that none of the non-Go symbols in the final link will
+// contain a dot, so we don't worry about conflicts.
//
// We first describe the basic symbol names, used to represent Go
-// functions and variables. These never start with a dot, never end
-// with a dot, never contain two consecutive dots, and never contain a
-// dot followed by a digit.
+// functions and variables.
//
// The external name for a normal Go symbol NAME, a function or
// variable, is simply "PKGPATH.NAME". Note that NAME is not the
// packed form used for the "hidden" name internally in the compiler;
-// it is the name that appears in the source code. PKGPATH is the
-// -fgo-pkgpath option as adjusted by Gogo::pkgpath_for_symbol. Note
-// that PKGPATH can not contain a dot and neither can NAME. Also,
-// NAME may not begin with a digit. NAME may require further encoding
-// for non-ASCII characters as described below, but until that
-// encoding these symbols contain exactly one dot, and they do not
-// start with a dot.
+// it is the name that appears in the source code. Both PKGPATH and
+// NAME will be encoded as described below. The encoding process
+// ensures that neither encoded string can contain a dot, and neither
+// will start with a digit (NAME is a Go identifier that can't contain
+// a dot or start with a digit anyhow). The encoding process means
+// that these external names contain exactly one dot and do not start
+// with a dot.
//
// The external name for a method NAME for a named type TYPE is
-// "PKGPATH.TYPE.NAME". Unlike the gc compiler, the external name
-// does not indicate whether this is a pointer method or a value
-// method; a named type can not have both a pointer and value method
-// with the same name, so there is no ambiguity. PKGPATH is the
-// package path of the package in which TYPE is defined. Here none of
-// PKGPATH, TYPE, or NAME can be empty or contain a dot, and neither
-// TYPE nor NAME may begin with a digit. Before encoding these names
-// contain exactly two dots, not consecutive, and they do not start
-// with a dot.
+// "PKGPATH.TYPE.NAME". Both NAME and TYPE are simple Go identifiers.
+// Unlike the gc compiler, the external name does not indicate whether
+// this is a pointer method or a value method; a named type can not
+// have both a pointer and value method with the same name, so there
+// is no ambiguity. PKGPATH is the package path of the package in
+// which TYPE is defined. PKGPATH, TYPE, and NAME are encoded, and
+// cannot be empty or contain a dot or start with a digit. These
+// external names contain exactly two dots, not consecutive, and they
+// do not start with a dot.
//
// It's uncommon, but the use of type literals with embedded fields
// can cause us to have methods on unnamed types. The external names
-// for these are also PKGPATH.TYPE.NAME, where TYPE is an
+// for these are also PKGPATH.TYPELIT.NAME, where TYPELIT is an
// approximately readable version of the type literal, described
-// below. As the type literal encoding always contains multiple dots,
-// these names always contain more than two dots. Although the type
-// literal encoding contains dots, neither PKGPATH nor NAME can
-// contain a dot, and neither TYPE nor NAME can begin with a digit.
-// The effect is that PKGPATH is always the portion of the name before
-// the first dot and NAME is always the portion after the last dot.
-// There is no ambiguity as long as encoded type literals are
+// below. A TYPELIT will always contain characters that cannot appear
+// in a Go identifier, so TYPELIT can never be confused with a TYPE
+// name. There is no ambiguity as long as encoded type literals are
// unambiguous.
//
// Also uncommon is an external name that must refer to a named type
// the function with an added suffix "..f".
//
// A thunk for a go or defer statement is treated as a function whose
-// name is ".thunkNN" where NN is a sequence of digits (these
-// functions are never globally visible). Thus the final name of a
-// thunk will be PKGPATH..thunkNN.
+// name is ".thunkNN", unencoded, where NN is a sequence of digits
+// (these functions are never globally visible). Thus the final name
+// of a thunk will be PKGPATH..thunkNN (PKGPATH is encoded).
//
-// An init function is treated as a function whose name is ".initNN"
-// where NN is a sequence of digits (these functions are never
-// globally visible). Thus the final name of an init function will be
-// PKGPATH..initNN.
+// An init function is treated as a function whose name is ".initNN",
+// unencoded, where NN is a sequence of digits (these functions are
+// never globally visible). Thus the final name of an init function
+// will be PKGPATH..initNN (PKGPATH is encoded).
//
// A nested function is given the name of outermost enclosing function
-// or method with an added suffix "..funcNN" where NN is a sequence of
-// digits. Note that the function descriptor of a nested function, if
-// needed, will end with "..funcNN..f".
+// or method with an added suffix "..funcNN", unencoded, where NN is a
+// sequence of digits. Note that the function descriptor of a nested
+// function, if needed, will end with "..funcNN..f".
//
// A recover thunk is the same as the name of the function with an
// added suffix "..r".
//
-// The name of a type descriptor for a named type is PKGPATH.TYPE..d.
+// The name of a type descriptor for a named type is
+// PKGPATH.TYPENAME..d (PKGPATH and TYPENAME are encoded).
//
-// The name of a type descriptor for an unnamed type is type..TYPE.
-// That is, the string "type.." followed by the type literal encoding.
+// The name of a type descriptor for a pointer to a named type is
+// PKGPATH.TYPENAME..p (PKGPATH and TYPENAME are encoded).
+//
+// The name of a type descriptor for an unnamed type is type..TYPELIT.
+// That is, the string "type.." followed by the encoded type literal.
// These names are common symbols, in the linker's sense of the word
// common: in the final executable there is only one instance of the
-// type descriptor for a given unnamed type. The type literal
-// encoding can never start with a digit or with 'u' or 'U'.
+// type descriptor for a given unnamed type.
//
-// The name of the GC symbol for a named type is PKGPATH.TYPE..g.
+// The name of the GC symbol for a named type is PKGPATH.TYPE..g
+// (PKGPATH and TYPE are encoded).
//
-// The name of the GC symbol for an unnamed type is typeg..TYPE.
+// The name of the GC symbol for an unnamed type is type..TYPELIT..g.
// These are common symbols.
//
// The name of a ptrmask symbol is gcbits..B32 where B32 is an
-// encoding of the ptrmask bits using only ASCII letters without 'u'
-// or 'U'. These are common symbols.
+// encoding of the ptrmask bits using only ASCII letters. These are
+// common symbols.
//
// An interface method table for assigning the non-interface type TYPE
// to the interface type ITYPE is named imt..ITYPE..TYPE. If ITYPE or
-// TYPE is a named type, they are written as PKGPATH.TYPE. Otherwise
-// they are written as a type literal. An interface method table for
-// a pointer method set uses pimt instead of imt.
+// TYPE is a named type, they are written as PKGPATH.TYPE (where both
+// PKGPATH and TYPE are encoded). Otherwise they are written as a
+// type literal. An interface method table for a pointer method set
+// uses pimt instead of imt.
//
// The names of composite literal initializers, including the GC root
// variable, are not referenced. They must not conflict with any C
// PKGPATH..import. If a package doesn't need an init function, it
// will have a dummy one, named ~PKGPATH.
//
-// In each pacakge there is a list of all the type descriptors defined
+// In each package there is a list of all the type descriptors defined
// in this package. The name of the list is PKGPATH..types.
//
// In the main package it gathers all the type descriptor lists in a
// The type literal encoding is not quite valid Go, as some aspects of
// compiler generated types can not be represented. For example,
// incomparable struct types have an extra field "{x}". Struct tags
-// are quoted inside curly braces, rather than introduce an encoding
-// for quotes. Struct tags can contain any character, so any single
-// byte Unicode character that is not alphanumeric or underscore is
-// replaced with .xNN where NN is the hex encoding.
+// can contain any character, which will be underscore encoded as
+// usual. In the unusual case of a curly brace or a backslash in a
+// struct tag, the brace or backslash will be backslash quoted, before
+// underscore encoding.
+//
+// The underscore encoding is, naturally, an underscore followed by
+// other characters. As there are various characters that commonly
+// appear in type literals and in package paths, we have a set of
+// short encodings. Then we have general encodings for other
+// characters.
//
-// There is a simple encoding for glue characters in type literals:
-// .0 - ' '
-// .1 - '*'
-// .2 - ';'
-// .3 - ','
-// .4 - '{'
-// .5 - '}'
-// .6 - '['
-// .7 - ']'
-// .8 - '('
-// .9 - ')'
-// This is unambiguous as, although the type literal can contain a dot
-// as shown above, those dots are always followed by a name and names
-// can not begin with a digit. A dot is always followed by a name or
-// a digit, and a type literal can neither start nor end with a dot,
-// so this never introduces consecutive dots.
+// __ - '_'
+// _0 - '.'
+// _1 - '/'
+// _2 - '*'
+// _3 - ','
+// _4 - '{'
+// _5 - '}'
+// _6 - '['
+// _7 - ']'
+// _8 - '('
+// _9 - ')'
+// _a - '"'
+// _b - ' '
+// _c - ';'
//
-// Struct tags can contain any character, so they need special
-// treatment. Alphanumerics, underscores, and Unicode characters that
-// require more than a single byte are left alone (Unicode characters
-// will be encoded later, as described below). Other single bytes
-// characters are replace with .xNN where NN is the hex encoding.
+// Other non-alphanumeric ASCII characters are encoded as _xNN, where
+// NN is the hex value for the character. If an encoded name would
+// otherwise start with a digit, this encoding is also used for the
+// leading digit.
//
-// Since Go identifiers can contain Unicode characters, we must encode
-// them into ASCII. We do this last, after the name is generated as
-// described above and after type literals are encoded. To make the
-// encoding unambiguous, we introduce it with two consecutive dots.
-// This is followed by the letter u and four hex digits or the letter
-// U and eight digits, just as in the language only using ..u and ..U
-// instead of \u and \U. The compiler also produces identifiers that
-// are qualified by package path, which means that there may also be ASCII
-// characters that are not assembler-friendly (ex: '=', '/'). The encoding
-// scheme translates such characters into the "..zNN" where NN is the
-// hex value for the character. Since before this encoding names can never
-// contain consecutive dots followed by 'z', 'u' or 'U', and after this
-// encoding "..z", "..u" and "..U" are followed by a known number of
-// characters, this is unambiguous.
+// Non-ASCII Unicode characters are encoded as _u and four hex digits
+// or _U and eight digits, just as in the language only using _u and
+// _U instead of \u and \U.
//
// Demangling these names is straightforward:
-// - replace ..zXX with an ASCII character
-// - replace ..uXXXX with a unicode character
-// - replace ..UXXXXXXXX with a unicode character
-// - replace .D, where D is a digit, with the character from the above
+// - replace _xXX with an ASCII character
+// - replace _uXXXX with a unicode character
+// - replace _UXXXXXXXX with a unicode character
+// - replace _C per the table above
// That will get you as close as possible to a readable name.
-// Return the assembler name to use for an exported function, a
-// method, or a function/method declaration. This is not called if
-// the function has been given an explicit name via a magic //extern
-// or //go:linkname comment. GO_NAME is the name that appears in the
-// Go code. PACKAGE is the package where the function is defined, and
-// is NULL for the package being compiled. For a method, RTYPE is
+// Set BNAME to the name to use for an exported function, a method, or
+// a function/method declaration. GO_NAME is the name that appears in
+// the Go code. PACKAGE is the package where the function is defined,
+// and is NULL for the package being compiled. For a method, RTYPE is
// the method's receiver type; for a function, RTYPE is NULL.
-std::string
-Gogo::function_asm_name(const std::string& go_name, const Package* package,
- const Type* rtype)
+void
+Gogo::function_backend_name(const std::string& go_name,
+ const Package* package, const Type* rtype,
+ Backend_name* bname)
{
- std::string ret;
if (rtype != NULL)
- ret = rtype->deref()->mangled_name(this);
+ rtype->deref()->backend_name(this, bname);
else if (package == NULL)
- ret = this->pkgpath();
+ bname->add(this->pkgpath());
else
- ret = package->pkgpath();
- ret.push_back('.');
- // Check for special names that will break if we use
- // Gogo::unpack_hidden_name.
- if (Gogo::is_special_name(go_name))
- ret.append(go_name);
+ bname->add(package->pkgpath());
+
+ size_t pos = Gogo::special_name_pos(go_name);
+ if (pos == std::string::npos)
+ bname->add(Gogo::unpack_hidden_name(go_name));
else
- ret.append(Gogo::unpack_hidden_name(go_name));
- return go_encode_id(ret);
+ {
+ if (pos > 0)
+ bname->add(go_name.substr(0, pos));
+ bname->set_suffix(go_name.substr(pos));
+ }
}
-// Return the name to use for a function descriptor. These symbols
-// are globally visible.
+// Set BNAME to the name to use for a function descriptor. These
+// symbols are globally visible.
-std::string
-Gogo::function_descriptor_name(Named_object* no)
+void
+Gogo::function_descriptor_backend_name(Named_object* no,
+ Backend_name* bname)
{
- if (no->is_function() && !no->func_value()->asm_name().empty())
- return no->func_value()->asm_name() + "..f";
- else if (no->is_function_declaration()
- && !no->func_declaration_value()->asm_name().empty())
- return no->func_declaration_value()->asm_name() + "..f";
- std::string ret = this->function_asm_name(no->name(), no->package(), NULL);
- ret.append("..f");
- return ret;
+ if (no->is_function())
+ no->func_value()->backend_name(this, no, bname);
+ else if (no->is_function_declaration())
+ no->func_declaration_value()->backend_name(this, no, bname);
+ else
+ go_unreachable();
+ bname->append_suffix("..f");
}
-// Return the name to use for a generated stub method. MNAME is the
-// method name. PACKAGE is the package where the type that needs this
-// stub method is defined. These functions are globally visible.
-// Note that this is the function name that corresponds to the name
-// used for the method in Go source code, if this stub method were
-// written in Go. The assembler name will be generated by
-// Gogo::function_asm_name, and because this is a method that name
-// will include the receiver type.
+// Return the name to use for a generated stub method. A stub method
+// is used as the method table entry for a promoted method of an
+// embedded type. MNAME is the method name. PACKAGE is the package
+// where the type that needs this stub method is defined. These
+// functions are globally visible.
+//
+// This returns a name that acts like a Go identifier, as though the
+// stub method were written in Go as an explicitly defined method that
+// simply calls the promoted method. The name we return here will
+// eventually be passed to function_backend_name, which will return a
+// name that includes the receiver type.
+//
+// We construct a unique method name and append "..stub".
+// function_backend_name will look for the "..stub" and turn that into
+// an unencoded suffix. The rest of the name will be encoded as
+// usual.
std::string
Gogo::stub_method_name(const Package* package, const std::string& mname)
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()
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()
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;
}
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
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)
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()));
}
// 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)
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));
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()
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()
// 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] == '~')
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
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);
}
}
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('}');
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);
}
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
}
}
-// 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;
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
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)
{
// 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()
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)
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 "";
}
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",
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
// 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.
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.
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);
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;
// 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_;
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);
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;
}
// 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();
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);
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();
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;
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();
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);
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_;
// 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_;
}
}
-// 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
{
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;
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,
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;
class Translate_context;
class Export;
class Import;
+class Backend_name;
class Btype;
class Bexpression;
class Bvariable;
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
// 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.
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
ac_config_headers="$ac_config_headers config.h"
-libtool_VERSION=17:0:0
+libtool_VERSION=18:0:0
# Default to --enable-multilib
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(, ..)
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")
}
// 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")
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
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")
}
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"
}
`
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 = `
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
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.
}
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)
+}
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)
env: "v2",
mangled: "p..u00e4..u4e16..U0001f703",
},
+ {
+ env: "v3",
+ mangled: "p_u00e4_u4e16_U0001f703",
+ },
{
env: "error",
fail: true,
}
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",
},
}
}
}
}
+
+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)
+ }
+ }
+}
return filepath.Join(elem...)
}
-//go:linkname setUsesCgo go/types.srcimporter_setUsesCgo
+//go:linkname setUsesCgo go_1types.srcimporter__setUsesCgo
func setUsesCgo(conf *types.Config)
#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)
}
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)
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)
}
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)
}
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)
};
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) {
};
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
};
struct facilityList stfle(void)
- __asm__(GOSYM_PREFIX "internal..z2fcpu.stfle")
+ __asm__(GOSYM_PREFIX "internal_1cpu.stfle")
__attribute__((no_split_stack));
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() {
}
struct queryResult kmcQuery(void)
- __asm__(GOSYM_PREFIX "internal..z2fcpu.kmcQuery")
+ __asm__(GOSYM_PREFIX "internal_1cpu.kmcQuery")
__attribute__((no_split_stack));
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() {
}
struct queryResult kmaQuery(void)
- __asm__(GOSYM_PREFIX "internal..z2fcpu.kmaQuery")
+ __asm__(GOSYM_PREFIX "internal_1cpu.kmaQuery")
__attribute__((no_split_stack));
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() {
}
struct queryResult klmdQuery(void)
- __asm__(GOSYM_PREFIX "internal..z2fcpu.klmdQuery")
+ __asm__(GOSYM_PREFIX "internal_1cpu.klmdQuery")
__attribute__((no_split_stack));
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() {
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)
// 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 {
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 {
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 {
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
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()
}
// 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
// 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
}
"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")
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 {
#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
}
void *Loadp (void *ptr)
- __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loadp")
+ __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Loadp")
__attribute__ ((no_split_stack));
void *
}
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
}
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
}
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
}
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
}
uintgo Loaduint (uintgo *ptr)
- __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loaduint")
+ __asm__ (GOSYM_PREFIX "runtime_1internal_1atomic.Loaduint")
__attribute__ ((no_split_stack));
uintgo
}
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
}
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
}
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
}
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
}
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
}
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
}
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
}
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
}
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
}
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
}
_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
}
_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
}
_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
}
_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
}
_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
}
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
}
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
}
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
}
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
}
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
}
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
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)
}
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)
}
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
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)
}
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() {
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
}
}
}
-//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() })
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)
}
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)
_ "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
}
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()
}
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.
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)
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 {
// 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))
// 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))
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
}
}
-//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)
}
}
-//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)
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),
}}
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)
}
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
}
// 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()
}
// 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)
}
// 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)
// 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() {
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()
}
// 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()
}
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)
_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.
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)
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,
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
}
// 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
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
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 {
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)
}
// 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.
// 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)
}
// 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.
}
// 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.
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")
}
}
-//go:linkname sync_nanotime sync.runtime_nanotime
+//go:linkname sync_nanotime sync.runtime__nanotime
func sync_nanotime() int64 {
return nanotime()
}
// 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.
// 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
}
// 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.
}
// 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
}
// 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
}
// 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
package runtime
import (
+ "internal/bytealg"
_ "unsafe" // for go:linkname
)
// 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
return rune(result)
}
-// Perform an in-place decoding on the input byte slice. This looks
-// for "..z<hex 2 >", "..u<hex x 4>" and "..U<hex x 8>" and overwrites
-// with the encoded bytes corresponding to the unicode in question.
-// Return value is the number of bytes taken by the result.
-
+// decodeIdentifier performs an in-place decoding on the input byte slice.
+// This undoes the compiler underscore mangling.
+// Returns the number of bytes used by the result.
func decodeIdentifier(bsl []byte) int {
+ underscoreCodes := map[byte]byte{
+ '_': '_',
+ '0': '.',
+ '1': '/',
+ '2': '*',
+ '3': ',',
+ '4': '{',
+ '5': '}',
+ '6': '[',
+ '7': ']',
+ '8': '(',
+ '9': ')',
+ 'a': '"',
+ 'b': ' ',
+ 'c': ';',
+ }
+
j := 0
for i := 0; i < len(bsl); i++ {
b := bsl[i]
+ if b != '_' || i+1 >= len(bsl) {
+ bsl[j] = b
+ j++
+ continue
+ }
+
+ if d, ok := underscoreCodes[bsl[i+1]]; ok {
+ i++
+ bsl[j] = d
+ j++
+ continue
+ }
+
+ rlen := 0
+ switch bsl[i+1] {
+ case 'x':
+ rlen = 2
+ case 'u':
+ rlen = 4
+ case 'U':
+ rlen = 8
+ }
- if i+1 < len(bsl) && bsl[i] == '.' && bsl[i+1] == '.' {
- if i+4 < len(bsl) && bsl[i+2] == 'z' {
- digits := bsl[i+3:]
- r := hexDigitsToRune(digits, 2)
- nc := encoderune(bsl[j:], r)
- j += nc
- i += 4
- continue
- } else if i+6 < len(bsl) && bsl[i+2] == 'u' {
- digits := bsl[i+3:]
- r := hexDigitsToRune(digits, 4)
- nc := encoderune(bsl[j:], r)
- j += nc
- i += 6
- continue
- } else if i+10 < len(bsl) && bsl[i+2] == 'U' {
- digits := bsl[i+3:]
- r := hexDigitsToRune(digits, 8)
- nc := encoderune(bsl[j:], r)
- j += nc
- i += 10
- continue
- }
+ if rlen > 0 && i+1+rlen < len(bsl) {
+ r := hexDigitsToRune(bsl[i+2:], rlen)
+ nc := encoderune(bsl[j:], r)
+ j += nc
+ i += rlen + 1
+ } else {
+ bsl[j] = b
+ j++
}
- bsl[j] = b
- j += 1
}
return j
}
// 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]
// 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
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
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
// 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'
#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
}
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
}
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
}
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
}
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
}
_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
}
_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
}
_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
}
_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
}
_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
}
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
}
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
}
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
}
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
}
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
}
int32_t LoadInt32 (int32_t *addr)
- __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadInt32")
+ __asm__ (GOSYM_PREFIX "sync_1atomic.LoadInt32")
__attribute__ ((no_split_stack));
int32_t
}
int64_t LoadInt64 (int64_t *addr)
- __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadInt64")
+ __asm__ (GOSYM_PREFIX "sync_1atomic.LoadInt64")
__attribute__ ((no_split_stack));
int64_t
}
uint32_t LoadUint32 (uint32_t *addr)
- __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUint32")
+ __asm__ (GOSYM_PREFIX "sync_1atomic.LoadUint32")
__attribute__ ((no_split_stack));
uint32_t
}
uint64_t LoadUint64 (uint64_t *addr)
- __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUint64")
+ __asm__ (GOSYM_PREFIX "sync_1atomic.LoadUint64")
__attribute__ ((no_split_stack));
uint64_t
}
uintptr_t LoadUintptr (uintptr_t *addr)
- __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUintptr")
+ __asm__ (GOSYM_PREFIX "sync_1atomic.LoadUintptr")
__attribute__ ((no_split_stack));
uintptr_t
}
void *LoadPointer (void **addr)
- __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadPointer")
+ __asm__ (GOSYM_PREFIX "sync_1atomic.LoadPointer")
__attribute__ ((no_split_stack));
void *
}
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
}
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
}
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
}
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
}
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
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)
/* 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)
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"
};
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 };
/* 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)
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)
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)
# Example:
#
# Original symbol: foo/bar/leaf.Mumble
-# Mangled symbol: foo..z2fbar..z2fleaf.Mumble
+# Mangled symbol: foo_1fbar_1leaf.Mumble
# Returned: leaf.Mumble
#
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