@@ -111,7 +111,8 @@ use rustc::hir::map::definitions::DefPathData;
111
111
use rustc:: util:: common:: record_time;
112
112
113
113
use syntax:: attr;
114
- use syntax:: symbol:: { Symbol , InternedString } ;
114
+
115
+ use std:: fmt:: Write ;
115
116
116
117
fn get_symbol_hash < ' a , ' tcx > ( scx : & SharedCrateContext < ' a , ' tcx > ,
117
118
@@ -255,19 +256,47 @@ pub fn symbol_name<'a, 'tcx>(instance: Instance<'tcx>,
255
256
256
257
let hash = get_symbol_hash ( scx, Some ( def_id) , instance_ty, Some ( substs) ) ;
257
258
258
- let mut buffer = SymbolPathBuffer {
259
- names : Vec :: new ( )
260
- } ;
261
-
259
+ let mut buffer = SymbolPathBuffer :: new ( ) ;
262
260
item_path:: with_forced_absolute_paths ( || {
263
261
scx. tcx ( ) . push_item_path ( & mut buffer, def_id) ;
264
262
} ) ;
265
-
266
- mangle ( buffer. names . into_iter ( ) , & hash)
263
+ buffer. finish ( & hash)
267
264
}
268
265
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.
269
279
struct 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
+ }
271
300
}
272
301
273
302
impl ItemPathBuffer for SymbolPathBuffer {
@@ -277,7 +306,13 @@ impl ItemPathBuffer for SymbolPathBuffer {
277
306
}
278
307
279
308
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 ) ;
281
316
}
282
317
}
283
318
@@ -286,15 +321,17 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a,
286
321
prefix : & str )
287
322
-> String {
288
323
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)
291
327
}
292
328
293
329
// Name sanitation. LLVM will happily accept identifiers with weird names, but
294
330
// gas doesn't!
295
331
// 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 {
298
335
for c in s. chars ( ) {
299
336
match c {
300
337
// Escape these with $ sequences
@@ -331,44 +368,7 @@ pub fn sanitize(s: &str) -> String {
331
368
}
332
369
333
370
// Underscore-qualify anything that didn't start as an ident.
334
- if !result. is_empty ( ) &&
371
+ !result. is_empty ( ) &&
335
372
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 ( )
374
374
}
0 commit comments