@@ -111,7 +111,8 @@ use rustc::hir::map::definitions::DefPathData;
111111use rustc:: util:: common:: record_time;
112112
113113use syntax:: attr;
114- use syntax:: symbol:: { Symbol , InternedString } ;
114+
115+ use std:: fmt:: Write ;
115116
116117fn get_symbol_hash < ' a , ' tcx > ( scx : & SharedCrateContext < ' a , ' tcx > ,
117118
@@ -255,19 +256,47 @@ pub fn symbol_name<'a, 'tcx>(instance: Instance<'tcx>,
255256
256257 let hash = get_symbol_hash ( scx, Some ( def_id) , instance_ty, Some ( substs) ) ;
257258
258- let mut buffer = SymbolPathBuffer {
259- names : Vec :: new ( )
260- } ;
261-
259+ let mut buffer = SymbolPathBuffer :: new ( ) ;
262260 item_path:: with_forced_absolute_paths ( || {
263261 scx. tcx ( ) . push_item_path ( & mut buffer, def_id) ;
264262 } ) ;
265-
266- mangle ( buffer. names . into_iter ( ) , & hash)
263+ buffer. finish ( & hash)
267264}
268265
266+ // Follow C++ namespace-mangling style, see
267+ // http://en.wikipedia.org/wiki/Name_mangling for more info.
268+ //
269+ // It turns out that on macOS you can actually have arbitrary symbols in
270+ // function names (at least when given to LLVM), but this is not possible
271+ // when using unix's linker. Perhaps one day when we just use a linker from LLVM
272+ // we won't need to do this name mangling. The problem with name mangling is
273+ // that it seriously limits the available characters. For example we can't
274+ // have things like &T in symbol names when one would theoretically
275+ // want them for things like impls of traits on that type.
276+ //
277+ // To be able to work on all platforms and get *some* reasonable output, we
278+ // use C++ name-mangling.
269279struct SymbolPathBuffer {
270- names : Vec < InternedString > ,
280+ result : String ,
281+ temp_buf : String
282+ }
283+
284+ impl SymbolPathBuffer {
285+ fn new ( ) -> Self {
286+ let mut result = SymbolPathBuffer {
287+ result : String :: with_capacity ( 64 ) ,
288+ temp_buf : String :: with_capacity ( 16 )
289+ } ;
290+ result. result . push_str ( "_ZN" ) ; // _Z == Begin name-sequence, N == nested
291+ result
292+ }
293+
294+ fn finish ( mut self , hash : & str ) -> String {
295+ // end name-sequence
296+ self . push ( hash) ;
297+ self . result . push ( 'E' ) ;
298+ self . result
299+ }
271300}
272301
273302impl ItemPathBuffer for SymbolPathBuffer {
@@ -277,7 +306,13 @@ impl ItemPathBuffer for SymbolPathBuffer {
277306 }
278307
279308 fn push ( & mut self , text : & str ) {
280- self . names . push ( Symbol :: intern ( text) . as_str ( ) ) ;
309+ self . temp_buf . clear ( ) ;
310+ let need_underscore = sanitize ( & mut self . temp_buf , text) ;
311+ let _ = write ! ( self . result, "{}" , self . temp_buf. len( ) + ( need_underscore as usize ) ) ;
312+ if need_underscore {
313+ self . result . push ( '_' ) ;
314+ }
315+ self . result . push_str ( & self . temp_buf ) ;
281316 }
282317}
283318
@@ -286,15 +321,17 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a,
286321 prefix : & str )
287322 -> String {
288323 let hash = get_symbol_hash ( scx, None , t, None ) ;
289- let path = [ Symbol :: intern ( prefix) . as_str ( ) ] ;
290- mangle ( path. iter ( ) . cloned ( ) , & hash)
324+ let mut buffer = SymbolPathBuffer :: new ( ) ;
325+ buffer. push ( prefix) ;
326+ buffer. finish ( & hash)
291327}
292328
293329// Name sanitation. LLVM will happily accept identifiers with weird names, but
294330// gas doesn't!
295331// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
296- pub fn sanitize ( s : & str ) -> String {
297- let mut result = String :: new ( ) ;
332+ //
333+ // returns true if an underscore must be added at the start
334+ pub fn sanitize ( result : & mut String , s : & str ) -> bool {
298335 for c in s. chars ( ) {
299336 match c {
300337 // Escape these with $ sequences
@@ -331,44 +368,7 @@ pub fn sanitize(s: &str) -> String {
331368 }
332369
333370 // Underscore-qualify anything that didn't start as an ident.
334- if !result. is_empty ( ) &&
371+ !result. is_empty ( ) &&
335372 result. as_bytes ( ) [ 0 ] != '_' as u8 &&
336- ! ( result. as_bytes ( ) [ 0 ] as char ) . is_xid_start ( ) {
337- return format ! ( "_{}" , result) ;
338- }
339-
340- return result;
341- }
342-
343- fn mangle < PI : Iterator < Item =InternedString > > ( path : PI , hash : & str ) -> String {
344- // Follow C++ namespace-mangling style, see
345- // http://en.wikipedia.org/wiki/Name_mangling for more info.
346- //
347- // It turns out that on macOS you can actually have arbitrary symbols in
348- // function names (at least when given to LLVM), but this is not possible
349- // when using unix's linker. Perhaps one day when we just use a linker from LLVM
350- // we won't need to do this name mangling. The problem with name mangling is
351- // that it seriously limits the available characters. For example we can't
352- // have things like &T in symbol names when one would theoretically
353- // want them for things like impls of traits on that type.
354- //
355- // To be able to work on all platforms and get *some* reasonable output, we
356- // use C++ name-mangling.
357-
358- let mut n = String :: from ( "_ZN" ) ; // _Z == Begin name-sequence, N == nested
359-
360- fn push ( n : & mut String , s : & str ) {
361- let sani = sanitize ( s) ;
362- n. push_str ( & format ! ( "{}{}" , sani. len( ) , sani) ) ;
363- }
364-
365- // First, connect each component with <len, name> pairs.
366- for data in path {
367- push ( & mut n, & data) ;
368- }
369-
370- push ( & mut n, hash) ;
371-
372- n. push ( 'E' ) ; // End name-sequence.
373- n
373+ ! ( result. as_bytes ( ) [ 0 ] as char ) . is_xid_start ( )
374374}
0 commit comments