Skip to content

Commit 7baff57

Browse files
committed
Improve name mangling for gdb
Remove __extensions__ from method symbols as well as the meth_XXX. The XXX is now used to append a few characters at the end of the name of the symbol. Closes #6602
1 parent 36a4af4 commit 7baff57

File tree

5 files changed

+99
-58
lines changed

5 files changed

+99
-58
lines changed

src/librustc/back/link.rs

+54-23
Original file line numberDiff line numberDiff line change
@@ -663,8 +663,7 @@ pub fn truncated_hash_result(symbol_hasher: &mut hash::State) -> ~str {
663663
pub fn symbol_hash(tcx: ty::ctxt,
664664
symbol_hasher: &mut hash::State,
665665
t: ty::t,
666-
link_meta: LinkMeta)
667-
-> @str {
666+
link_meta: LinkMeta) -> @str {
668667
// NB: do *not* use abbrevs here as we want the symbol names
669668
// to be independent of one another in the crate.
670669

@@ -719,7 +718,7 @@ pub fn sanitize(s: &str) -> ~str {
719718
'a' .. 'z'
720719
| 'A' .. 'Z'
721720
| '0' .. '9'
722-
| '_' => result.push_char(c),
721+
| '_' | '.' => result.push_char(c),
723722

724723
_ => {
725724
let mut tstr = ~"";
@@ -740,22 +739,37 @@ pub fn sanitize(s: &str) -> ~str {
740739
return result;
741740
}
742741

743-
pub fn mangle(sess: Session, ss: path) -> ~str {
742+
pub fn mangle(sess: Session, ss: path,
743+
hash: Option<&str>, vers: Option<&str>) -> ~str {
744744
// Follow C++ namespace-mangling style, see
745745
// http://en.wikipedia.org/wiki/Name_mangling for more info.
746+
//
747+
// It turns out that on OSX you can actually have arbitrary symbols in
748+
// function names (at least when given to LLVM), but this is not possible
749+
// when using unix's linker. Perhaps one day when we just a linker from LLVM
750+
// we won't need to do this name mangling. The problem with name mangling is
751+
// that it seriously limits the available characters. For example we can't
752+
// have things like @T or ~[T] in symbol names when one would theoretically
753+
// want them for things like impls of traits on that type.
754+
//
755+
// To be able to work on all platforms and get *some* reasonable output, we
756+
// use C++ name-mangling.
746757

747758
let mut n = ~"_ZN"; // _Z == Begin name-sequence, N == nested
748759

760+
let push = |s: &str| {
761+
let sani = sanitize(s);
762+
n.push_str(fmt!("%u%s", sani.len(), sani));
763+
};
764+
749765
// First, connect each component with <len, name> pairs.
750766
for s in ss.iter() {
751767
match *s {
752768
path_name(s) | path_mod(s) | path_pretty_name(s, _) => {
753-
let sani = sanitize(sess.str_of(s));
754-
n.push_str(fmt!("%u%s", sani.len(), sani));
769+
push(sess.str_of(s))
755770
}
756771
}
757772
}
758-
n.push_char('E'); // End name-sequence.
759773

760774
// next, if any identifiers are "pretty" and need extra information tacked
761775
// on, then use the hash to generate two unique characters. For now
@@ -764,28 +778,43 @@ pub fn mangle(sess: Session, ss: path) -> ~str {
764778
"abcdefghijklmnopqrstuvwxyz\
765779
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
766780
0123456789";
781+
let mut hash = match hash { Some(s) => s.to_owned(), None => ~"" };
767782
for s in ss.iter() {
768783
match *s {
769784
path_pretty_name(_, extra) => {
770785
let hi = (extra >> 32) as u32 as uint;
771786
let lo = extra as u32 as uint;
772-
n.push_char(EXTRA_CHARS[hi % EXTRA_CHARS.len()] as char);
773-
n.push_char(EXTRA_CHARS[lo % EXTRA_CHARS.len()] as char);
787+
hash.push_char(EXTRA_CHARS[hi % EXTRA_CHARS.len()] as char);
788+
hash.push_char(EXTRA_CHARS[lo % EXTRA_CHARS.len()] as char);
774789
}
775790
_ => {}
776791
}
777792
}
793+
if hash.len() > 0 {
794+
push(hash);
795+
}
796+
match vers {
797+
Some(s) => push(s),
798+
None => {}
799+
}
800+
801+
n.push_char('E'); // End name-sequence.
778802
n
779803
}
780804

781805
pub fn exported_name(sess: Session,
782806
path: path,
783807
hash: &str,
784808
vers: &str) -> ~str {
785-
mangle(sess,
786-
vec::append_one(
787-
vec::append_one(path, path_name(sess.ident_of(hash))),
788-
path_name(sess.ident_of(vers))))
809+
// The version will get mangled to have a leading '_', but it makes more
810+
// sense to lead with a 'v' b/c this is a version...
811+
let vers = if vers.len() > 0 && !char::is_XID_start(vers.char_at(0)) {
812+
"v" + vers
813+
} else {
814+
vers.to_owned()
815+
};
816+
817+
mangle(sess, path, Some(hash), Some(vers.as_slice()))
789818
}
790819

791820
pub fn mangle_exported_name(ccx: &mut CrateContext,
@@ -803,31 +832,33 @@ pub fn mangle_internal_name_by_type_only(ccx: &mut CrateContext,
803832
let s = ppaux::ty_to_short_str(ccx.tcx, t);
804833
let hash = get_symbol_hash(ccx, t);
805834
return mangle(ccx.sess,
806-
~[path_name(ccx.sess.ident_of(name)),
807-
path_name(ccx.sess.ident_of(s)),
808-
path_name(ccx.sess.ident_of(hash))]);
835+
~[path_name(ccx.sess.ident_of(name)),
836+
path_name(ccx.sess.ident_of(s))],
837+
Some(hash.as_slice()),
838+
None);
809839
}
810840

811841
pub fn mangle_internal_name_by_type_and_seq(ccx: &mut CrateContext,
812-
t: ty::t,
813-
name: &str) -> ~str {
842+
t: ty::t,
843+
name: &str) -> ~str {
814844
let s = ppaux::ty_to_str(ccx.tcx, t);
815845
let hash = get_symbol_hash(ccx, t);
816846
return mangle(ccx.sess,
817-
~[path_name(ccx.sess.ident_of(s)),
818-
path_name(ccx.sess.ident_of(hash)),
819-
path_name(gensym_name(name))]);
847+
~[path_name(ccx.sess.ident_of(s)),
848+
path_name(gensym_name(name))],
849+
Some(hash.as_slice()),
850+
None);
820851
}
821852

822853
pub fn mangle_internal_name_by_path_and_seq(ccx: &mut CrateContext,
823854
mut path: path,
824855
flav: &str) -> ~str {
825856
path.push(path_name(gensym_name(flav)));
826-
mangle(ccx.sess, path)
857+
mangle(ccx.sess, path, None, None)
827858
}
828859

829860
pub fn mangle_internal_name_by_path(ccx: &mut CrateContext, path: path) -> ~str {
830-
mangle(ccx.sess, path)
861+
mangle(ccx.sess, path, None, None)
831862
}
832863

833864
pub fn mangle_internal_name_by_seq(_ccx: &mut CrateContext, flav: &str) -> ~str {

src/librustc/middle/trans/base.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ use std::local_data;
7777
use extra::time;
7878
use extra::sort;
7979
use syntax::ast::Ident;
80-
use syntax::ast_map::{path, path_elt_to_str, path_name};
80+
use syntax::ast_map::{path, path_elt_to_str, path_name, path_pretty_name};
8181
use syntax::ast_util::{local_def};
8282
use syntax::attr;
8383
use syntax::attr::AttrMetaMethods;
@@ -2646,8 +2646,7 @@ pub fn register_method(ccx: @mut CrateContext,
26462646
let mty = ty::node_id_to_type(ccx.tcx, id);
26472647

26482648
let mut path = (*path).clone();
2649-
path.push(path_name(gensym_name("meth")));
2650-
path.push(path_name(m.ident));
2649+
path.push(path_pretty_name(m.ident, token::gensym("meth") as u64));
26512650

26522651
let sym = exported_name(ccx, path, mty, m.attrs);
26532652

src/libsyntax/ast_map.rs

+40-29
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@ use ast_util;
1616
use codemap::Span;
1717
use codemap;
1818
use diagnostic::span_handler;
19+
use parse::token::get_ident_interner;
1920
use parse::token::ident_interner;
2021
use parse::token::special_idents;
2122
use print::pprust;
2223
use visit::{Visitor, fn_kind};
2324
use visit;
2425

25-
use std::hash;
2626
use std::hashmap::HashMap;
2727
use std::vec;
2828

2929
#[deriving(Clone, Eq)]
3030
pub enum path_elt {
3131
path_mod(Ident),
32-
path_name(Ident)
32+
path_name(Ident),
3333

3434
// A pretty name can come from an `impl` block. We attempt to select a
3535
// reasonable name for debuggers to see, but to guarantee uniqueness with
@@ -98,8 +98,8 @@ pub struct Ctx {
9898
}
9999

100100
impl Ctx {
101-
fn extend(&self, elt: Ident) -> @path {
102-
@vec::append(self.path.clone(), [path_name(elt)])
101+
fn extend(&self, elt: path_elt) -> @path {
102+
@vec::append(self.path.clone(), [elt])
103103
}
104104

105105
fn map_method(&mut self,
@@ -120,7 +120,7 @@ impl Ctx {
120120
struct_def: @ast::struct_def,
121121
parent_node: ast_node,
122122
ident: ast::Ident) {
123-
let p = self.extend(ident);
123+
let p = self.extend(path_name(ident));
124124

125125
// If this is a tuple-like struct, register the constructor.
126126
match struct_def.ctor_id {
@@ -196,6 +196,28 @@ impl Ctx {
196196

197197
visit::walk_pat(self, pat, ());
198198
}
199+
200+
fn impl_pretty_name(&self, trait_ref: &Option<trait_ref>,
201+
ty: &Ty, default: Ident) -> path_elt {
202+
let itr = get_ident_interner();
203+
let ty_ident = match ty.node {
204+
ty_path(ref path, _, _) => path.segments.last().identifier,
205+
_ => default
206+
};
207+
let hash = (trait_ref, ty).hash();
208+
match *trait_ref {
209+
None => path_pretty_name(ty_ident, hash),
210+
Some(ref trait_ref) => {
211+
// XXX: this dollar sign is actually a relic of being one of the
212+
// very few valid symbol names on unix. These kinds of
213+
// details shouldn't be exposed way up here in the ast.
214+
let s = fmt!("%s$%s",
215+
itr.get(trait_ref.path.segments.last().identifier.name),
216+
itr.get(ty_ident.name));
217+
path_pretty_name(Ident::new(itr.gensym(s)), hash)
218+
}
219+
}
220+
}
199221
}
200222

201223
impl Visitor<()> for Ctx {
@@ -205,40 +227,27 @@ impl Visitor<()> for Ctx {
205227
self.map.insert(i.id, node_item(i, item_path));
206228
match i.node {
207229
item_impl(_, ref maybe_trait, ref ty, ref ms) => {
230+
// Right now the ident on impls is __extensions__ which isn't
231+
// very pretty when debugging, so attempt to select a better
232+
// name to use.
233+
let elt = self.impl_pretty_name(maybe_trait, ty, i.ident);
234+
208235
let impl_did = ast_util::local_def(i.id);
209236
for m in ms.iter() {
210-
let extended = { self.extend(i.ident) };
237+
let extended = { self.extend(elt) };
211238
self.map_method(impl_did, extended, *m, false)
212239
}
213240

214-
// Right now the ident on impls is __extensions__ which isn't
215-
// very pretty when debugging, so attempt to select a better
216-
// name to use.
217-
let name = match *maybe_trait {
218-
Some(ref trait_ref) => {
219-
trait_ref.path.segments.last().identifier
220-
}
221-
None => {
222-
match ty.node {
223-
ty_path(ref p, _, _) => {
224-
p.segments.last().identifier
225-
}
226-
// oh well, just give up for now
227-
_ => { i.ident }
228-
}
229-
}
230-
};
231-
232-
let hash = hash::hash_keyed_2(maybe_trait, ty, 0, 0);
233-
self.path.push(path_pretty_name(name, hash));
241+
self.path.push(elt);
234242
}
235243
item_enum(ref enum_definition, _) => {
236244
for v in (*enum_definition).variants.iter() {
245+
let elt = path_name(i.ident);
237246
// FIXME #2543: bad clone
238247
self.map.insert(v.node.id,
239248
node_variant((*v).clone(),
240249
i,
241-
self.extend(i.ident)));
250+
self.extend(elt)));
242251
}
243252
}
244253
item_foreign_mod(ref nm) => {
@@ -257,7 +266,9 @@ impl Visitor<()> for Ctx {
257266
// FIXME (#2543)
258267
if nm.sort ==
259268
ast::named {
260-
self.extend(i.ident)
269+
let e = path_name(
270+
i.ident);
271+
self.extend(e)
261272
} else {
262273
// Anonymous extern
263274
// mods go in the
@@ -276,7 +287,7 @@ impl Visitor<()> for Ctx {
276287
self.map.insert(p.ref_id, node_item(i, item_path));
277288
}
278289
for tm in methods.iter() {
279-
let ext = { self.extend(i.ident) };
290+
let ext = { self.extend(path_name(i.ident)) };
280291
let d_id = ast_util::local_def(i.id);
281292
match *tm {
282293
required(ref m) => {

src/test/compile-fail/ambig_impl_2_exe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ use ambig_impl_2_lib::me;
1515
trait me {
1616
fn me(&self) -> uint;
1717
}
18-
impl me for uint { fn me(&self) -> uint { *self } } //~ NOTE is `__extensions__::me`
18+
impl me for uint { fn me(&self) -> uint { *self } } //~ NOTE is `me$uint::me`
1919
fn main() { 1u.me(); } //~ ERROR multiple applicable methods in scope
2020
//~^ NOTE is `ambig_impl_2_lib::__extensions__::me`

src/test/compile-fail/ambig_impl_unify.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ trait foo {
1313
}
1414

1515
impl foo for ~[uint] {
16-
fn foo(&self) -> int {1} //~ NOTE candidate #1 is `__extensions__::foo`
16+
fn foo(&self) -> int {1} //~ NOTE candidate #1 is `foo$__extensions__::foo`
1717
}
1818

1919
impl foo for ~[int] {
20-
fn foo(&self) -> int {2} //~ NOTE candidate #2 is `__extensions__::foo`
20+
fn foo(&self) -> int {2} //~ NOTE candidate #2 is `foo$__extensions__::foo`
2121
}
2222

2323
fn main() {

0 commit comments

Comments
 (0)