@@ -35,7 +35,7 @@ use std::run;
35
35
use std:: str;
36
36
use std:: vec;
37
37
use syntax:: ast;
38
- use syntax:: ast_map:: { path, path_mod, path_name} ;
38
+ use syntax:: ast_map:: { path, path_mod, path_name, path_pretty_name } ;
39
39
use syntax:: attr;
40
40
use syntax:: attr:: { AttrMetaMethods } ;
41
41
use syntax:: print:: pprust;
@@ -667,8 +667,7 @@ pub fn truncated_hash_result(symbol_hasher: &mut hash::State) -> ~str {
667
667
pub fn symbol_hash ( tcx : ty:: ctxt ,
668
668
symbol_hasher : & mut hash:: State ,
669
669
t : ty:: t ,
670
- link_meta : LinkMeta )
671
- -> @str {
670
+ link_meta : LinkMeta ) -> @str {
672
671
// NB: do *not* use abbrevs here as we want the symbol names
673
672
// to be independent of one another in the crate.
674
673
@@ -723,7 +722,7 @@ pub fn sanitize(s: &str) -> ~str {
723
722
'a' .. 'z'
724
723
| 'A' .. 'Z'
725
724
| '0' .. '9'
726
- | '_' => result. push_char ( c) ,
725
+ | '_' | '.' => result. push_char ( c) ,
727
726
728
727
_ => {
729
728
let mut tstr = ~"";
@@ -744,19 +743,65 @@ pub fn sanitize(s: &str) -> ~str {
744
743
return result;
745
744
}
746
745
747
- pub fn mangle ( sess : Session , ss : path ) -> ~str {
748
- // Follow C++ namespace-mangling style
746
+ pub fn mangle ( sess : Session , ss : path ,
747
+ hash : Option < & str > , vers : Option < & str > ) -> ~str {
748
+ // Follow C++ namespace-mangling style, see
749
+ // http://en.wikipedia.org/wiki/Name_mangling for more info.
750
+ //
751
+ // It turns out that on OSX you can actually have arbitrary symbols in
752
+ // function names (at least when given to LLVM), but this is not possible
753
+ // when using unix's linker. Perhaps one day when we just a linker from LLVM
754
+ // we won't need to do this name mangling. The problem with name mangling is
755
+ // that it seriously limits the available characters. For example we can't
756
+ // have things like @T or ~[T] in symbol names when one would theoretically
757
+ // want them for things like impls of traits on that type.
758
+ //
759
+ // To be able to work on all platforms and get *some* reasonable output, we
760
+ // use C++ name-mangling.
761
+
762
+ let mut n = ~"_ZN"; // _Z == Begin name-sequence, N == nested
763
+
764
+ let push = |s : & str | {
765
+ let sani = sanitize ( s) ;
766
+ n. push_str ( fmt ! ( "%u%s" , sani. len( ) , sani) ) ;
767
+ } ;
749
768
750
- let mut n = ~"_ZN"; // Begin name-sequence.
769
+ // First, connect each component with <len, name> pairs.
770
+ for s in ss. iter ( ) {
771
+ match * s {
772
+ path_name( s) | path_mod( s) | path_pretty_name( s, _) => {
773
+ push ( sess. str_of ( s) )
774
+ }
775
+ }
776
+ }
751
777
778
+ // next, if any identifiers are "pretty" and need extra information tacked
779
+ // on, then use the hash to generate two unique characters. For now
780
+ // hopefully 2 characters is enough to avoid collisions.
781
+ static EXTRA_CHARS : & ' static str =
782
+ "abcdefghijklmnopqrstuvwxyz\
783
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ\
784
+ 0123456789";
785
+ let mut hash = match hash { Some ( s) => s. to_owned ( ) , None => ~"" } ;
752
786
for s in ss. iter ( ) {
753
787
match * s {
754
- path_name( s) | path_mod( s) => {
755
- let sani = sanitize ( sess. str_of ( s) ) ;
756
- n. push_str ( fmt ! ( "%u%s" , sani. len( ) , sani) ) ;
788
+ path_pretty_name( _, extra) => {
789
+ let hi = ( extra >> 32 ) as u32 as uint ;
790
+ let lo = extra as u32 as uint ;
791
+ hash. push_char ( EXTRA_CHARS [ hi % EXTRA_CHARS . len ( ) ] as char ) ;
792
+ hash. push_char ( EXTRA_CHARS [ lo % EXTRA_CHARS . len ( ) ] as char ) ;
757
793
}
794
+ _ => { }
758
795
}
759
796
}
797
+ if hash. len( ) > 0 {
798
+ push( hash) ;
799
+ }
800
+ match vers {
801
+ Some ( s) => push ( s) ,
802
+ None => { }
803
+ }
804
+
760
805
n. push_char ( 'E' ) ; // End name-sequence.
761
806
n
762
807
}
@@ -765,10 +810,15 @@ pub fn exported_name(sess: Session,
765
810
path : path ,
766
811
hash : & str ,
767
812
vers : & str ) -> ~str {
768
- mangle ( sess,
769
- vec:: append_one (
770
- vec:: append_one ( path, path_name ( sess. ident_of ( hash) ) ) ,
771
- path_name ( sess. ident_of ( vers) ) ) )
813
+ // The version will get mangled to have a leading '_', but it makes more
814
+ // sense to lead with a 'v' b/c this is a version...
815
+ let vers = if vers. len ( ) > 0 && !char:: is_XID_start ( vers. char_at ( 0 ) ) {
816
+ "v" + vers
817
+ } else {
818
+ vers. to_owned ( )
819
+ } ;
820
+
821
+ mangle ( sess, path, Some ( hash) , Some ( vers. as_slice ( ) ) )
772
822
}
773
823
774
824
pub fn mangle_exported_name ( ccx : & mut CrateContext ,
@@ -786,31 +836,33 @@ pub fn mangle_internal_name_by_type_only(ccx: &mut CrateContext,
786
836
let s = ppaux:: ty_to_short_str ( ccx. tcx , t) ;
787
837
let hash = get_symbol_hash ( ccx, t) ;
788
838
return mangle ( ccx. sess ,
789
- ~[ path_name ( ccx. sess . ident_of ( name) ) ,
790
- path_name ( ccx. sess . ident_of ( s) ) ,
791
- path_name ( ccx. sess . ident_of ( hash) ) ] ) ;
839
+ ~[ path_name ( ccx. sess . ident_of ( name) ) ,
840
+ path_name ( ccx. sess . ident_of ( s) ) ] ,
841
+ Some ( hash. as_slice ( ) ) ,
842
+ None ) ;
792
843
}
793
844
794
845
pub fn mangle_internal_name_by_type_and_seq ( ccx : & mut CrateContext ,
795
- t : ty:: t ,
796
- name : & str ) -> ~str {
846
+ t : ty:: t ,
847
+ name : & str ) -> ~str {
797
848
let s = ppaux:: ty_to_str ( ccx. tcx , t) ;
798
849
let hash = get_symbol_hash ( ccx, t) ;
799
850
return mangle ( ccx. sess ,
800
- ~[ path_name ( ccx. sess . ident_of ( s) ) ,
801
- path_name ( ccx. sess . ident_of ( hash) ) ,
802
- path_name ( gensym_name ( name) ) ] ) ;
851
+ ~[ path_name ( ccx. sess . ident_of ( s) ) ,
852
+ path_name ( gensym_name ( name) ) ] ,
853
+ Some ( hash. as_slice ( ) ) ,
854
+ None ) ;
803
855
}
804
856
805
857
pub fn mangle_internal_name_by_path_and_seq ( ccx : & mut CrateContext ,
806
858
mut path : path ,
807
859
flav : & str ) -> ~str {
808
860
path. push ( path_name ( gensym_name ( flav) ) ) ;
809
- mangle ( ccx. sess , path)
861
+ mangle ( ccx. sess , path, None , None )
810
862
}
811
863
812
864
pub fn mangle_internal_name_by_path ( ccx : & mut CrateContext , path : path ) -> ~str {
813
- mangle ( ccx. sess , path)
865
+ mangle ( ccx. sess , path, None , None )
814
866
}
815
867
816
868
pub fn mangle_internal_name_by_seq ( _ccx : & mut CrateContext , flav : & str ) -> ~str {
0 commit comments