@@ -110,7 +110,8 @@ use rustc::hir::map::definitions::DefPathData;
110
110
use rustc:: util:: common:: record_time;
111
111
112
112
use syntax:: attr;
113
- use syntax:: symbol:: { Symbol , InternedString } ;
113
+
114
+ use std:: fmt:: Write ;
114
115
115
116
fn get_symbol_hash < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
116
117
@@ -252,19 +253,47 @@ pub fn symbol_name<'a, 'tcx>(instance: Instance<'tcx>,
252
253
253
254
let hash = get_symbol_hash ( tcx, Some ( def_id) , instance_ty, Some ( substs) ) ;
254
255
255
- let mut buffer = SymbolPathBuffer {
256
- names : Vec :: new ( )
257
- } ;
258
-
256
+ let mut buffer = SymbolPathBuffer :: new ( ) ;
259
257
item_path:: with_forced_absolute_paths ( || {
260
258
tcx. push_item_path ( & mut buffer, def_id) ;
261
259
} ) ;
262
-
263
- mangle ( buffer. names . into_iter ( ) , & hash)
260
+ buffer. finish ( & hash)
264
261
}
265
262
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.
266
276
struct 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
+ }
268
297
}
269
298
270
299
impl ItemPathBuffer for SymbolPathBuffer {
@@ -274,7 +303,13 @@ impl ItemPathBuffer for SymbolPathBuffer {
274
303
}
275
304
276
305
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 ) ;
278
313
}
279
314
}
280
315
@@ -283,15 +318,17 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
283
318
prefix : & str )
284
319
-> String {
285
320
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)
288
324
}
289
325
290
326
// Name sanitation. LLVM will happily accept identifiers with weird names, but
291
327
// gas doesn't!
292
328
// 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 {
295
332
for c in s. chars ( ) {
296
333
match c {
297
334
// Escape these with $ sequences
@@ -328,44 +365,7 @@ pub fn sanitize(s: &str) -> String {
328
365
}
329
366
330
367
// Underscore-qualify anything that didn't start as an ident.
331
- if !result. is_empty ( ) &&
368
+ !result. is_empty ( ) &&
332
369
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 ( )
371
371
}
0 commit comments