@@ -110,7 +110,8 @@ use rustc::hir::map::definitions::DefPathData;
110110use rustc:: util:: common:: record_time;
111111
112112use syntax:: attr;
113- use syntax:: symbol:: { Symbol , InternedString } ;
113+
114+ use std:: fmt:: Write ;
114115
115116fn get_symbol_hash < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
116117
@@ -252,19 +253,47 @@ pub fn symbol_name<'a, 'tcx>(instance: Instance<'tcx>,
252253
253254 let hash = get_symbol_hash ( tcx, Some ( def_id) , instance_ty, Some ( substs) ) ;
254255
255- let mut buffer = SymbolPathBuffer {
256- names : Vec :: new ( )
257- } ;
258-
256+ let mut buffer = SymbolPathBuffer :: new ( ) ;
259257 item_path:: with_forced_absolute_paths ( || {
260258 tcx. push_item_path ( & mut buffer, def_id) ;
261259 } ) ;
262-
263- mangle ( buffer. names . into_iter ( ) , & hash)
260+ buffer. finish ( & hash)
264261}
265262
263+ // Follow C++ namespace-mangling style, see
264+ // http://en.wikipedia.org/wiki/Name_mangling for more info.
265+ //
266+ // It turns out that on macOS you can actually have arbitrary symbols in
267+ // function names (at least when given to LLVM), but this is not possible
268+ // when using unix's linker. Perhaps one day when we just use a linker from LLVM
269+ // we won't need to do this name mangling. The problem with name mangling is
270+ // that it seriously limits the available characters. For example we can't
271+ // have things like &T in symbol names when one would theoretically
272+ // want them for things like impls of traits on that type.
273+ //
274+ // To be able to work on all platforms and get *some* reasonable output, we
275+ // use C++ name-mangling.
266276struct SymbolPathBuffer {
267- names : Vec < InternedString > ,
277+ result : String ,
278+ temp_buf : String
279+ }
280+
281+ impl SymbolPathBuffer {
282+ fn new ( ) -> Self {
283+ let mut result = SymbolPathBuffer {
284+ result : String :: with_capacity ( 64 ) ,
285+ temp_buf : String :: with_capacity ( 16 )
286+ } ;
287+ result. result . push_str ( "_ZN" ) ; // _Z == Begin name-sequence, N == nested
288+ result
289+ }
290+
291+ fn finish ( mut self , hash : & str ) -> String {
292+ // end name-sequence
293+ self . push ( hash) ;
294+ self . result . push ( 'E' ) ;
295+ self . result
296+ }
268297}
269298
270299impl ItemPathBuffer for SymbolPathBuffer {
@@ -274,7 +303,13 @@ impl ItemPathBuffer for SymbolPathBuffer {
274303 }
275304
276305 fn push ( & mut self , text : & str ) {
277- self . names . push ( Symbol :: intern ( text) . as_str ( ) ) ;
306+ self . temp_buf . clear ( ) ;
307+ let need_underscore = sanitize ( & mut self . temp_buf , text) ;
308+ let _ = write ! ( self . result, "{}" , self . temp_buf. len( ) + ( need_underscore as usize ) ) ;
309+ if need_underscore {
310+ self . result . push ( '_' ) ;
311+ }
312+ self . result . push_str ( & self . temp_buf ) ;
278313 }
279314}
280315
@@ -283,15 +318,17 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
283318 prefix : & str )
284319 -> String {
285320 let hash = get_symbol_hash ( tcx, None , t, None ) ;
286- let path = [ Symbol :: intern ( prefix) . as_str ( ) ] ;
287- mangle ( path. iter ( ) . cloned ( ) , & hash)
321+ let mut buffer = SymbolPathBuffer :: new ( ) ;
322+ buffer. push ( prefix) ;
323+ buffer. finish ( & hash)
288324}
289325
290326// Name sanitation. LLVM will happily accept identifiers with weird names, but
291327// gas doesn't!
292328// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
293- pub fn sanitize ( s : & str ) -> String {
294- let mut result = String :: new ( ) ;
329+ //
330+ // returns true if an underscore must be added at the start
331+ pub fn sanitize ( result : & mut String , s : & str ) -> bool {
295332 for c in s. chars ( ) {
296333 match c {
297334 // Escape these with $ sequences
@@ -328,44 +365,7 @@ pub fn sanitize(s: &str) -> String {
328365 }
329366
330367 // Underscore-qualify anything that didn't start as an ident.
331- if !result. is_empty ( ) &&
368+ !result. is_empty ( ) &&
332369 result. as_bytes ( ) [ 0 ] != '_' as u8 &&
333- ! ( result. as_bytes ( ) [ 0 ] as char ) . is_xid_start ( ) {
334- return format ! ( "_{}" , result) ;
335- }
336-
337- return result;
338- }
339-
340- fn mangle < PI : Iterator < Item =InternedString > > ( path : PI , hash : & str ) -> String {
341- // Follow C++ namespace-mangling style, see
342- // http://en.wikipedia.org/wiki/Name_mangling for more info.
343- //
344- // It turns out that on macOS you can actually have arbitrary symbols in
345- // function names (at least when given to LLVM), but this is not possible
346- // when using unix's linker. Perhaps one day when we just use a linker from LLVM
347- // we won't need to do this name mangling. The problem with name mangling is
348- // that it seriously limits the available characters. For example we can't
349- // have things like &T in symbol names when one would theoretically
350- // want them for things like impls of traits on that type.
351- //
352- // To be able to work on all platforms and get *some* reasonable output, we
353- // use C++ name-mangling.
354-
355- let mut n = String :: from ( "_ZN" ) ; // _Z == Begin name-sequence, N == nested
356-
357- fn push ( n : & mut String , s : & str ) {
358- let sani = sanitize ( s) ;
359- n. push_str ( & format ! ( "{}{}" , sani. len( ) , sani) ) ;
360- }
361-
362- // First, connect each component with <len, name> pairs.
363- for data in path {
364- push ( & mut n, & data) ;
365- }
366-
367- push ( & mut n, hash) ;
368-
369- n. push ( 'E' ) ; // End name-sequence.
370- n
370+ ! ( result. as_bytes ( ) [ 0 ] as char ) . is_xid_start ( )
371371}
0 commit comments