// struct tag, the brace or backslash will be backslash quoted, before
// underscore encoding.
//
+// Many of these names will be visible in the debugger. The debugger
+// will be given these names before applying any underscore encoding.
+// These user names do not have to be unique--they are only used by
+// the debugger, not the linker--so this is OK. However, there is an
+// exception: if the name would otherwise include characters that
+// can't normally appear in an identifier, then the user name will
+// also be underscore encoded. This avoids problems with
+// communicating the debug info to the assembler and with handling the
+// debug info in the debugger. A Go-aware debugger will need to know
+// whether to apply underscore decoding to a name before showing it to
+// the user. We indicate this by adding a prefix of "g.", and
+// assuming that cases of a package path of "g" are unusual. This
+// prefix will only appear in the user name, not the assembler name.
+//
// 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
if (rtype != NULL)
{
Backend_name bname;
- rtype->backend_name(this, &bname);
+ rtype->deref()->backend_name(this, &bname);
ret = bname.name();
ret.append(1, '.');
}
}
std::string name;
+ bool is_non_identifier = false;
// The do_symbol_name virtual function will set RET to the mangled
// name before encoding.
- this->do_mangled_name(gogo, &name);
+ this->do_mangled_name(gogo, &name, &is_non_identifier);
bname->add(name);
+ if (is_non_identifier)
+ bname->set_is_non_identifier();
}
// The mangled name is implemented as a method on each instance of
// Type.
void
-Error_type::do_mangled_name(Gogo*, std::string* ret) const
+Error_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("{error}");
+ *is_non_identifier = true;
}
void
-Void_type::do_mangled_name(Gogo*, std::string* ret) const
+Void_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("{void}");
+ *is_non_identifier = true;
}
void
-Boolean_type::do_mangled_name(Gogo*, std::string* ret) const
+Boolean_type::do_mangled_name(Gogo*, std::string* ret, bool*) const
{
ret->append("bool");
}
void
-Integer_type::do_mangled_name(Gogo*, std::string* ret) const
+Integer_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
char buf[100];
snprintf(buf, sizeof buf, "%s%si%d",
this->is_unsigned_ ? "u" : "",
this->bits_);
ret->append(buf);
+ if (this->is_abstract_)
+ *is_non_identifier = true;
}
void
-Float_type::do_mangled_name(Gogo*, std::string* ret) const
+Float_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
char buf[100];
snprintf(buf, sizeof buf, "%sfloat%d",
this->is_abstract_ ? "{abstract}" : "",
this->bits_);
ret->append(buf);
+ if (this->is_abstract_)
+ *is_non_identifier = true;
}
void
-Complex_type::do_mangled_name(Gogo*, std::string* ret) const
+Complex_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
char buf[100];
snprintf(buf, sizeof buf, "%sc%d",
this->is_abstract_ ? "{abstract}" : "",
this->bits_);
ret->append(buf);
+ if (this->is_abstract_)
+ *is_non_identifier = true;
}
void
-String_type::do_mangled_name(Gogo*, std::string* ret) const
+String_type::do_mangled_name(Gogo*, std::string* ret, bool*) const
{
ret->append("string");
}
void
-Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Function_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("func");
if (this->receiver_ != NULL)
{
ret->push_back('(');
- this->append_mangled_name(this->receiver_->type(), gogo, ret);
+ this->append_mangled_name(this->receiver_->type(), gogo, ret,
+ is_non_identifier);
ret->append(")");
}
ret->push_back(',');
if (this->is_varargs_ && p + 1 == params->end())
ret->append("...");
- this->append_mangled_name(p->type(), gogo, ret);
+ this->append_mangled_name(p->type(), gogo, ret,
+ is_non_identifier);
}
}
ret->push_back(')');
first = false;
else
ret->append(",");
- this->append_mangled_name(p->type(), gogo, ret);
+ this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
}
}
ret->push_back(')');
+
+ *is_non_identifier = true;
}
void
-Pointer_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Pointer_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->push_back('*');
- this->append_mangled_name(this->to_type_, gogo, ret);
+ this->append_mangled_name(this->to_type_, gogo, ret, is_non_identifier);
+ *is_non_identifier = true;
}
void
-Nil_type::do_mangled_name(Gogo*, std::string* ret) const
+Nil_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("{nil}");
+ *is_non_identifier = true;
}
void
-Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Struct_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("struct{");
if (p->is_anonymous()
&& p->type()->named_type() != NULL
&& p->type()->named_type()->is_alias())
- p->type()->named_type()->append_symbol_type_name(gogo, true, ret);
+ p->type()->named_type()->append_symbol_type_name(gogo, true, ret,
+ is_non_identifier);
else
- this->append_mangled_name(p->type(), gogo, ret);
+ this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
if (p->has_tag())
{
}
ret->push_back('}');
+
+ *is_non_identifier = true;
}
void
-Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Array_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->push_back('[');
if (this->length_ != NULL)
ret->append("x");
}
ret->push_back(']');
- this->append_mangled_name(this->element_type_, gogo, ret);
+ this->append_mangled_name(this->element_type_, gogo, ret, is_non_identifier);
+ *is_non_identifier = true;
}
void
-Map_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Map_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("map[");
- this->append_mangled_name(this->key_type_, gogo, ret);
+ this->append_mangled_name(this->key_type_, gogo, ret, is_non_identifier);
ret->push_back(']');
- this->append_mangled_name(this->val_type_, gogo, ret);
+ this->append_mangled_name(this->val_type_, gogo, ret, is_non_identifier);
+ *is_non_identifier = true;
}
void
-Channel_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Channel_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
if (!this->may_send_)
ret->append("<-");
if (!this->may_receive_)
ret->append("<-");
ret->push_back(' ');
- this->append_mangled_name(this->element_type_, gogo, ret);
+ this->append_mangled_name(this->element_type_, gogo, ret, is_non_identifier);
+ *is_non_identifier = true;
}
void
-Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Interface_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
go_assert(this->methods_are_finalized_);
ret->push_back(' ');
}
- this->append_mangled_name(p->type(), gogo, ret);
+ this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
}
this->seen_ = false;
}
ret->push_back('}');
+
+ *is_non_identifier = true;
}
void
-Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Named_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
- this->append_symbol_type_name(gogo, false, ret);
+ this->append_symbol_type_name(gogo, false, ret, is_non_identifier);
}
void
-Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool *is_non_identifier) const
{
if (this->is_defined())
- this->append_mangled_name(this->real_type(), gogo, ret);
+ this->append_mangled_name(this->real_type(), gogo, ret, is_non_identifier);
else
{
const Named_object* no = this->named_object();
void
Named_type::append_symbol_type_name(Gogo* gogo, bool use_alias,
- std::string* ret) const
+ std::string* ret,
+ bool* is_non_identifier) const
{
if (this->is_error_)
return;
if (this->seen_alias_)
return;
this->seen_alias_ = true;
- this->append_mangled_name(this->type_, gogo, ret);
+ this->append_mangled_name(this->type_, gogo, ret, is_non_identifier);
this->seen_alias_ = false;
return;
}
Backend_name bname;
rcvr->type()->deref()->backend_name(gogo, &bname);
ret->append(bname.name());
+ if (bname.is_non_identifier())
+ *is_non_identifier = true;
}
else if (this->in_function_->package() == NULL)
ret->append(gogo->pkgpath());
{
if (this->is_asm_name_)
return this->components_[0];
+
+ // If there is some character in the name that can't appear in an
+ // identifier, use the assembler name as the user name. This avoids
+ // possible problems in the assembler or debugger. The usual
+ // demangling scheme will still work. We use a prefix of "g." to
+ // tell the debugger about this.
+ if (this->is_non_identifier_)
+ return "g." + this->asm_name();
+
std::string ret;
if (this->prefix_ != NULL)
ret.append(this->prefix_);
{
if (this->is_asm_name_)
return "";
+ if (this->is_non_identifier_)
+ return this->asm_name();
for (int i = 0; i < this->count_; i++)
if (go_id_needs_encoding(this->components_[i]))
return this->asm_name();
do_reflection(Gogo*, std::string*) const = 0;
virtual void
- do_mangled_name(Gogo*, std::string*) const = 0;
+ do_mangled_name(Gogo*, std::string*, bool*) const = 0;
virtual void
do_export(Export*) const;
// For the benefit of child class mangling.
void
- append_mangled_name(const Type* type, Gogo* gogo, std::string* ret) const
- { type->do_mangled_name(gogo, ret); }
+ append_mangled_name(const Type* type, Gogo* gogo, std::string* ret,
+ bool *is_non_identifier) const
+ { type->do_mangled_name(gogo, ret, is_non_identifier); }
// Return the backend representation for the underlying type of a
// named type.
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The void type.
{ }
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The boolean type.
{ ret->append("bool"); }
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The type of an integer.
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
private:
Integer_type(bool is_abstract, bool is_unsigned, int bits,
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
private:
Float_type(bool is_abstract, int bits, int runtime_type_kind)
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
private:
Complex_type(bool is_abstract, int bits, int runtime_type_kind)
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
private:
// The named string type.
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
{ go_unreachable(); }
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The type of a field in a struct.
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
// 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_symbol_type_name(Gogo*, bool use_alias, std::string*) const;
+ append_symbol_type_name(Gogo*, bool use_alias, std::string*,
+ bool* is_non_identifier) const;
// Import a named type.
static void
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;