@@ -663,8 +663,7 @@ pub fn truncated_hash_result(symbol_hasher: &mut hash::State) -> ~str {
663
663
pub fn symbol_hash ( tcx : ty:: ctxt ,
664
664
symbol_hasher : & mut hash:: State ,
665
665
t : ty:: t ,
666
- link_meta : LinkMeta )
667
- -> @str {
666
+ link_meta : LinkMeta ) -> @str {
668
667
// NB: do *not* use abbrevs here as we want the symbol names
669
668
// to be independent of one another in the crate.
670
669
@@ -719,7 +718,7 @@ pub fn sanitize(s: &str) -> ~str {
719
718
'a' .. 'z'
720
719
| 'A' .. 'Z'
721
720
| '0' .. '9'
722
- | '_' => result. push_char ( c) ,
721
+ | '_' | '.' => result. push_char ( c) ,
723
722
724
723
_ => {
725
724
let mut tstr = ~"";
@@ -740,22 +739,37 @@ pub fn sanitize(s: &str) -> ~str {
740
739
return result;
741
740
}
742
741
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 {
744
744
// Follow C++ namespace-mangling style, see
745
745
// 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.
746
757
747
758
let mut n = ~"_ZN"; // _Z == Begin name-sequence, N == nested
748
759
760
+ let push = |s : & str | {
761
+ let sani = sanitize ( s) ;
762
+ n. push_str ( fmt ! ( "%u%s" , sani. len( ) , sani) ) ;
763
+ } ;
764
+
749
765
// First, connect each component with <len, name> pairs.
750
766
for s in ss. iter ( ) {
751
767
match * s {
752
768
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) )
755
770
}
756
771
}
757
772
}
758
- n. push_char ( 'E' ) ; // End name-sequence.
759
773
760
774
// next, if any identifiers are "pretty" and need extra information tacked
761
775
// on, then use the hash to generate two unique characters. For now
@@ -764,28 +778,43 @@ pub fn mangle(sess: Session, ss: path) -> ~str {
764
778
"abcdefghijklmnopqrstuvwxyz\
765
779
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
766
780
0123456789";
781
+ let mut hash = match hash { Some ( s) => s. to_owned ( ) , None => ~"" } ;
767
782
for s in ss. iter ( ) {
768
783
match * s {
769
784
path_pretty_name( _, extra) => {
770
785
let hi = ( extra >> 32 ) as u32 as uint ;
771
786
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 ) ;
774
789
}
775
790
_ => { }
776
791
}
777
792
}
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.
778
802
n
779
803
}
780
804
781
805
pub fn exported_name ( sess : Session ,
782
806
path : path ,
783
807
hash : & str ,
784
808
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 ( ) ) )
789
818
}
790
819
791
820
pub fn mangle_exported_name ( ccx : & mut CrateContext ,
@@ -803,31 +832,33 @@ pub fn mangle_internal_name_by_type_only(ccx: &mut CrateContext,
803
832
let s = ppaux:: ty_to_short_str ( ccx. tcx , t) ;
804
833
let hash = get_symbol_hash ( ccx, t) ;
805
834
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 ) ;
809
839
}
810
840
811
841
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 {
814
844
let s = ppaux:: ty_to_str ( ccx. tcx , t) ;
815
845
let hash = get_symbol_hash ( ccx, t) ;
816
846
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 ) ;
820
851
}
821
852
822
853
pub fn mangle_internal_name_by_path_and_seq ( ccx : & mut CrateContext ,
823
854
mut path : path ,
824
855
flav : & str ) -> ~str {
825
856
path. push ( path_name ( gensym_name ( flav) ) ) ;
826
- mangle ( ccx. sess , path)
857
+ mangle ( ccx. sess , path, None , None )
827
858
}
828
859
829
860
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 )
831
862
}
832
863
833
864
pub fn mangle_internal_name_by_seq ( _ccx : & mut CrateContext , flav : & str ) -> ~str {
0 commit comments