@@ -9,7 +9,6 @@ use rustc_middle::mir::Mutability;
9
9
use rustc_middle:: mir:: interpret:: { ConstAllocation , GlobalAlloc , Scalar } ;
10
10
use rustc_middle:: ty:: layout:: LayoutOf ;
11
11
12
- use crate :: consts:: const_alloc_to_gcc;
13
12
use crate :: context:: CodegenCx ;
14
13
use crate :: type_of:: LayoutGccExt ;
15
14
@@ -46,12 +45,58 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
46
45
}
47
46
48
47
pub fn bytes_in_context < ' gcc , ' tcx > ( cx : & CodegenCx < ' gcc , ' tcx > , bytes : & [ u8 ] ) -> RValue < ' gcc > {
49
- let context = & cx. context ;
50
- let byte_type = context. new_type :: < u8 > ( ) ;
51
- let typ = context. new_array_type ( None , byte_type, bytes. len ( ) as u64 ) ;
52
- let elements: Vec < _ > =
53
- bytes. iter ( ) . map ( |& byte| context. new_rvalue_from_int ( byte_type, byte as i32 ) ) . collect ( ) ;
54
- context. new_array_constructor ( None , typ, & elements)
48
+ // Instead of alaways using an array of bytes, use an array of larger intgers of target endianess
49
+ // if possible.
50
+ match bytes. len ( ) % 8 {
51
+ 0 => {
52
+ let context = & cx. context ;
53
+ let byte_type = context. new_type :: < u64 > ( ) ;
54
+ let typ = context. new_array_type ( None , byte_type, bytes. len ( ) as u64 / 8 ) ;
55
+ let elements: Vec < _ > = bytes
56
+ . chunks_exact ( 8 )
57
+ . map ( |arr| {
58
+ let arr: [ u8 ; 8 ] = arr. try_into ( ) . unwrap ( ) ;
59
+ context. new_rvalue_from_long (
60
+ byte_type,
61
+ match cx. sess ( ) . target . options . endian {
62
+ rustc_abi:: Endian :: Little => u64:: from_le_bytes ( arr) as i64 ,
63
+ rustc_abi:: Endian :: Big => u64:: from_be_bytes ( arr) as i64 ,
64
+ } ,
65
+ )
66
+ } )
67
+ . collect ( ) ;
68
+ context. new_array_constructor ( None , typ, & elements)
69
+ }
70
+ 4 => {
71
+ let context = & cx. context ;
72
+ let byte_type = context. new_type :: < u32 > ( ) ;
73
+ let typ = context. new_array_type ( None , byte_type, bytes. len ( ) as u64 / 4 ) ;
74
+ let elements: Vec < _ > = bytes
75
+ . chunks_exact ( 4 )
76
+ . map ( |arr| {
77
+ let arr: [ u8 ; 4 ] = arr. try_into ( ) . unwrap ( ) ;
78
+ context. new_rvalue_from_int (
79
+ byte_type,
80
+ match cx. sess ( ) . target . options . endian {
81
+ rustc_abi:: Endian :: Little => u32:: from_le_bytes ( arr) as i32 ,
82
+ rustc_abi:: Endian :: Big => u32:: from_be_bytes ( arr) as i32 ,
83
+ } ,
84
+ )
85
+ } )
86
+ . collect ( ) ;
87
+ context. new_array_constructor ( None , typ, & elements)
88
+ }
89
+ _ => {
90
+ let context = cx. context ;
91
+ let byte_type = context. new_type :: < u8 > ( ) ;
92
+ let typ = context. new_array_type ( None , byte_type, bytes. len ( ) as u64 ) ;
93
+ let elements: Vec < _ > = bytes
94
+ . iter ( )
95
+ . map ( |& byte| context. new_rvalue_from_int ( byte_type, byte as i32 ) )
96
+ . collect ( ) ;
97
+ context. new_array_constructor ( None , typ, & elements)
98
+ }
99
+ }
55
100
}
56
101
57
102
pub fn type_is_pointer ( typ : Type < ' _ > ) -> bool {
@@ -212,7 +257,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
212
257
let alloc_id = prov. alloc_id ( ) ;
213
258
let base_addr = match self . tcx . global_alloc ( alloc_id) {
214
259
GlobalAlloc :: Memory ( alloc) => {
215
- let init = const_alloc_to_gcc ( self , alloc) ;
260
+ let init = self . const_data_from_alloc ( alloc) ;
216
261
let alloc = alloc. inner ( ) ;
217
262
let value = match alloc. mutability {
218
263
Mutability :: Mut => self . static_addr_of_mut ( init, alloc. align , None ) ,
@@ -234,7 +279,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
234
279
} ) ,
235
280
) ) )
236
281
. unwrap_memory ( ) ;
237
- let init = const_alloc_to_gcc ( self , alloc) ;
282
+ let init = self . const_data_from_alloc ( alloc) ;
238
283
self . static_addr_of ( init, alloc. inner ( ) . align , None )
239
284
}
240
285
GlobalAlloc :: Static ( def_id) => {
@@ -257,7 +302,19 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
257
302
}
258
303
259
304
fn const_data_from_alloc ( & self , alloc : ConstAllocation < ' _ > ) -> Self :: Value {
260
- const_alloc_to_gcc ( self , alloc)
305
+ // We ignore the alignment for the purpose of deduping RValues
306
+ // The alignment is not handled / used in any way by `const_alloc_to_gcc`,
307
+ // so it is OK to overwrite it here.
308
+ let mut mock_alloc = alloc. inner ( ) . clone ( ) ;
309
+ mock_alloc. align = rustc_abi:: Align :: MAX ;
310
+ // Check if the rvalue is already in the cache - if so, just return it directly.
311
+ if let Some ( res) = self . const_cache . borrow ( ) . get ( & mock_alloc) {
312
+ return * res;
313
+ }
314
+ // Rvalue not in the cache - convert and add it.
315
+ let res = crate :: consts:: const_alloc_to_gcc_unchached ( self , alloc) ;
316
+ self . const_cache . borrow_mut ( ) . insert ( mock_alloc, res) ;
317
+ res
261
318
}
262
319
263
320
fn const_ptr_byte_offset ( & self , base_addr : Self :: Value , offset : abi:: Size ) -> Self :: Value {
0 commit comments