@@ -20,9 +20,11 @@ use crate::llvm::debuginfo::{
20
20
use crate :: value:: Value ;
21
21
22
22
use cstr:: cstr;
23
+ use inlinable_string:: InlinableString ;
23
24
use rustc_codegen_ssa:: debuginfo:: type_names:: cpp_like_debuginfo;
24
25
use rustc_codegen_ssa:: debuginfo:: type_names:: VTableNameKind ;
25
26
use rustc_codegen_ssa:: traits:: * ;
27
+ use rustc_data_structures:: base_n;
26
28
use rustc_data_structures:: fx:: FxHashMap ;
27
29
use rustc_fs_util:: path_to_c_string;
28
30
use rustc_hir:: def:: CtorKind ;
@@ -93,8 +95,23 @@ pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
93
95
94
96
pub const NO_SCOPE_METADATA : Option < & DIScope > = None ;
95
97
98
+ /// Same as format!() but produces an InlinableString to avoid
99
+ /// unnecessary memory allocations.
100
+ macro_rules! format_inline {
101
+ ( $( $tokens: expr) ,* ) => {
102
+ {
103
+ use inlinable_string:: StringExt ;
104
+ let mut string = inlinable_string:: InlinableString :: new( ) ;
105
+ write!( & mut string, $( $tokens) ,* ) . unwrap( ) ;
106
+ string
107
+ }
108
+ } ;
109
+ }
110
+
96
111
mod unique_type_id {
112
+ use inlinable_string:: InlinableString ;
97
113
use rustc_data_structures:: {
114
+ base_n,
98
115
fingerprint:: Fingerprint ,
99
116
stable_hasher:: { HashStable , NodeIdHashingMode , StableHasher } ,
100
117
} ;
@@ -163,15 +180,16 @@ mod unique_type_id {
163
180
UniqueTypeId :: VTableTy ( self_type, implemented_trait, HiddenZst { _inaccessible : ( ) } )
164
181
}
165
182
166
- pub fn to_string ( & self , tcx : TyCtxt < ' tcx > ) -> String {
183
+ pub fn to_string ( & self , tcx : TyCtxt < ' tcx > ) -> InlinableString {
167
184
let mut hasher = StableHasher :: new ( ) ;
168
185
let mut hcx = tcx. create_stable_hashing_context ( ) ;
169
186
hcx. while_hashing_spans ( false , |hcx| {
170
187
hcx. with_node_id_hashing_mode ( NodeIdHashingMode :: HashDefPath , |hcx| {
171
188
self . hash_stable ( hcx, & mut hasher) ;
172
189
} ) ;
173
190
} ) ;
174
- hasher. finish :: < Fingerprint > ( ) . to_hex ( )
191
+ let ( low, high) = hasher. finish :: < Fingerprint > ( ) . as_value ( ) ;
192
+ base_n:: encode ( ( low as u128 ) | ( ( high as u128 ) << 64 ) , base_n:: MAX_BASE )
175
193
}
176
194
}
177
195
}
@@ -884,7 +902,7 @@ fn foreign_type_metadata<'ll, 'tcx>(
884
902
885
903
fn param_type_metadata < ' ll , ' tcx > ( cx : & CodegenCx < ' ll , ' tcx > , t : Ty < ' tcx > ) -> & ' ll DIType {
886
904
debug ! ( "param_type_metadata: {:?}" , t) ;
887
- let name = format ! ( "{:?}" , t) ;
905
+ let name = format_inline ! ( "{:?}" , t) ;
888
906
unsafe {
889
907
llvm:: LLVMRustDIBuilderCreateBasicType (
890
908
DIB ( cx) ,
@@ -1077,7 +1095,7 @@ struct SourceInfo<'ll> {
1077
1095
/// structs or tuples) or an enum variant.
1078
1096
#[ derive( Debug ) ]
1079
1097
struct MemberDescription < ' ll > {
1080
- name : String ,
1098
+ name : InlinableString ,
1081
1099
type_metadata : & ' ll DIType ,
1082
1100
offset : Size ,
1083
1101
size : Size ,
@@ -1162,9 +1180,9 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
1162
1180
. enumerate ( )
1163
1181
. map ( |( i, f) | {
1164
1182
let name = if self . variant . ctor_kind == CtorKind :: Fn {
1165
- format ! ( "__{}" , i)
1183
+ format_inline ! ( "__{}" , i)
1166
1184
} else {
1167
- f. name . to_string ( )
1185
+ f. name . as_str ( ) . into ( )
1168
1186
} ;
1169
1187
let field = layout. field ( cx, i) ;
1170
1188
MemberDescription {
@@ -1227,7 +1245,10 @@ fn prepare_struct_metadata<'ll, 'tcx>(
1227
1245
/// Here are some examples:
1228
1246
/// - `name__field1__field2` when the upvar is captured by value.
1229
1247
/// - `_ref__name__field` when the upvar is captured by reference.
1230
- fn closure_saved_names_of_captured_variables ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> Vec < String > {
1248
+ fn closure_saved_names_of_captured_variables (
1249
+ tcx : TyCtxt < ' _ > ,
1250
+ def_id : DefId ,
1251
+ ) -> Vec < InlinableString > {
1231
1252
let body = tcx. optimized_mir ( def_id) ;
1232
1253
1233
1254
body. var_debug_info
@@ -1242,7 +1263,7 @@ fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) ->
1242
1263
_ => return None ,
1243
1264
} ;
1244
1265
let prefix = if is_ref { "_ref__" } else { "" } ;
1245
- Some ( prefix . to_owned ( ) + var. name . as_str ( ) )
1266
+ Some ( format_inline ! ( "{}{}" , prefix , var. name) )
1246
1267
} )
1247
1268
. collect :: < Vec < _ > > ( )
1248
1269
}
@@ -1273,7 +1294,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
1273
1294
let name = if let Some ( names) = capture_names. as_mut ( ) {
1274
1295
names. next ( ) . unwrap ( )
1275
1296
} else {
1276
- format ! ( "__{}" , i)
1297
+ format_inline ! ( "__{}" , i)
1277
1298
} ;
1278
1299
MemberDescription {
1279
1300
name,
@@ -1345,7 +1366,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
1345
1366
. map ( |( i, f) | {
1346
1367
let field = self . layout . field ( cx, i) ;
1347
1368
MemberDescription {
1348
- name : f. name . to_string ( ) ,
1369
+ name : f. name . as_str ( ) . into ( ) ,
1349
1370
type_metadata : type_metadata ( cx, field. ty ) ,
1350
1371
offset : Size :: ZERO ,
1351
1372
size : field. size ,
@@ -1563,7 +1584,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
1563
1584
1564
1585
MemberDescription {
1565
1586
name : if fallback {
1566
- format ! ( "variant{}" , i. as_u32( ) )
1587
+ format_inline ! ( "variant{}" , i. as_u32( ) )
1567
1588
} else {
1568
1589
variant_info. variant_name ( )
1569
1590
} ,
@@ -1697,7 +1718,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
1697
1718
vec ! [
1698
1719
MemberDescription {
1699
1720
// Name the dataful variant so that we can identify it for natvis
1700
- name: "dataful_variant" . to_string ( ) ,
1721
+ name: "dataful_variant" . into ( ) ,
1701
1722
type_metadata: variant_type_metadata,
1702
1723
offset: Size :: ZERO ,
1703
1724
size: self . layout. size,
@@ -1762,7 +1783,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
1762
1783
struct VariantMemberDescriptionFactory < ' tcx > {
1763
1784
/// Cloned from the `layout::Struct` describing the variant.
1764
1785
offsets : Vec < Size > ,
1765
- args : Vec < ( String , Ty < ' tcx > ) > ,
1786
+ args : Vec < ( InlinableString , Ty < ' tcx > ) > ,
1766
1787
}
1767
1788
1768
1789
impl < ' tcx > VariantMemberDescriptionFactory < ' tcx > {
@@ -1776,7 +1797,7 @@ impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
1776
1797
. map ( |( i, & ( ref name, ty) ) | {
1777
1798
let ( size, align) = cx. size_and_align_of ( ty) ;
1778
1799
MemberDescription {
1779
- name : name. to_string ( ) ,
1800
+ name : name. clone ( ) ,
1780
1801
type_metadata : type_metadata ( cx, ty) ,
1781
1802
offset : self . offsets [ i] ,
1782
1803
size,
@@ -1819,20 +1840,20 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
1819
1840
}
1820
1841
}
1821
1842
1822
- fn variant_name ( & self ) -> String {
1843
+ fn variant_name ( & self ) -> InlinableString {
1823
1844
match self {
1824
- VariantInfo :: Adt ( variant, _) => variant. name . to_string ( ) ,
1845
+ VariantInfo :: Adt ( variant, _) => variant. name . as_str ( ) . into ( ) ,
1825
1846
VariantInfo :: Generator { variant_index, .. } => {
1826
1847
// Since GDB currently prints out the raw discriminant along
1827
1848
// with every variant, make each variant name be just the value
1828
1849
// of the discriminant. The struct name for the variant includes
1829
1850
// the actual variant description.
1830
- format ! ( "{}" , variant_index. as_usize( ) )
1851
+ base_n :: encode ( variant_index. as_usize ( ) as u128 , 10 )
1831
1852
}
1832
1853
}
1833
1854
}
1834
1855
1835
- fn field_name ( & self , i : usize ) -> String {
1856
+ fn field_name ( & self , i : usize ) -> InlinableString {
1836
1857
let field_name = match * self {
1837
1858
VariantInfo :: Adt ( variant, _) if variant. ctor_kind != CtorKind :: Fn => {
1838
1859
Some ( variant. fields [ i] . name )
@@ -1848,7 +1869,7 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
1848
1869
}
1849
1870
_ => None ,
1850
1871
} ;
1851
- field_name. map ( |name| name. to_string ( ) ) . unwrap_or_else ( || format ! ( "__{}" , i) )
1872
+ field_name. map ( |name| name. as_str ( ) . into ( ) ) . unwrap_or_else ( || format_inline ! ( "__{}" , i) )
1852
1873
}
1853
1874
1854
1875
fn source_info < ' ll > ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> Option < SourceInfo < ' ll > > {
@@ -2532,19 +2553,19 @@ fn vtable_type_metadata<'ll, 'tcx>(
2532
2553
. filter_map ( |( index, vtable_entry) | {
2533
2554
let ( field_name, field_type) = match vtable_entry {
2534
2555
ty:: VtblEntry :: MetadataDropInPlace => {
2535
- ( "drop_in_place" . to_string ( ) , void_pointer_type_debuginfo)
2556
+ ( "drop_in_place" . into ( ) , void_pointer_type_debuginfo)
2536
2557
}
2537
2558
ty:: VtblEntry :: Method ( _) => {
2538
2559
// Note: This code does not try to give a proper name to each method
2539
2560
// because their might be multiple methods with the same name
2540
2561
// (coming from different traits).
2541
- ( format ! ( "__method{}" , index) , void_pointer_type_debuginfo)
2562
+ ( format_inline ! ( "__method{}" , index) , void_pointer_type_debuginfo)
2542
2563
}
2543
2564
ty:: VtblEntry :: TraitVPtr ( _) => {
2544
- ( format ! ( "__super_trait_ptr{}" , index) , void_pointer_type_debuginfo)
2565
+ ( format_inline ! ( "__super_trait_ptr{}" , index) , void_pointer_type_debuginfo)
2545
2566
}
2546
- ty:: VtblEntry :: MetadataAlign => ( "align" . to_string ( ) , usize_debuginfo) ,
2547
- ty:: VtblEntry :: MetadataSize => ( "size" . to_string ( ) , usize_debuginfo) ,
2567
+ ty:: VtblEntry :: MetadataAlign => ( "align" . into ( ) , usize_debuginfo) ,
2568
+ ty:: VtblEntry :: MetadataSize => ( "size" . into ( ) , usize_debuginfo) ,
2548
2569
ty:: VtblEntry :: Vacant => return None ,
2549
2570
} ;
2550
2571
0 commit comments