@@ -9,7 +9,6 @@ use rustc_middle::mir::Mutability;
99use rustc_middle:: mir:: interpret:: { ConstAllocation , GlobalAlloc , Scalar } ;
1010use rustc_middle:: ty:: layout:: LayoutOf ;
1111
12- use crate :: consts:: const_alloc_to_gcc;
1312use crate :: context:: CodegenCx ;
1413use crate :: type_of:: LayoutGccExt ;
1514
@@ -46,12 +45,58 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
4645}
4746
4847pub 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+ }
55100}
56101
57102pub fn type_is_pointer ( typ : Type < ' _ > ) -> bool {
@@ -212,7 +257,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
212257 let alloc_id = prov. alloc_id ( ) ;
213258 let base_addr = match self . tcx . global_alloc ( alloc_id) {
214259 GlobalAlloc :: Memory ( alloc) => {
215- let init = const_alloc_to_gcc ( self , alloc) ;
260+ let init = self . const_data_from_alloc ( alloc) ;
216261 let alloc = alloc. inner ( ) ;
217262 let value = match alloc. mutability {
218263 Mutability :: Mut => self . static_addr_of_mut ( init, alloc. align , None ) ,
@@ -234,7 +279,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
234279 } ) ,
235280 ) ) )
236281 . unwrap_memory ( ) ;
237- let init = const_alloc_to_gcc ( self , alloc) ;
282+ let init = self . const_data_from_alloc ( alloc) ;
238283 self . static_addr_of ( init, alloc. inner ( ) . align , None )
239284 }
240285 GlobalAlloc :: Static ( def_id) => {
@@ -257,7 +302,19 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
257302 }
258303
259304 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
261318 }
262319
263320 fn const_ptr_byte_offset ( & self , base_addr : Self :: Value , offset : abi:: Size ) -> Self :: Value {
0 commit comments