@@ -4,7 +4,8 @@ use rustc_middle::mir::*;
44use rustc_middle:: ty:: util:: IntTypeExt ;
55use rustc_middle:: ty:: { self , Const , Ty , TyCtxt } ;
66use rustc_span:: def_id:: DefId ;
7- use rustc_target:: abi:: { Size , TagEncoding , Variants } ;
7+ use rustc_target:: abi:: { HasDataLayout , Size , TagEncoding , Variants } ;
8+ use std:: array:: IntoIter ;
89
910/// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large
1011/// enough discrepanc between them
@@ -21,11 +22,10 @@ impl<const D: u64> EnumSizeOpt<D> {
2122 tcx : TyCtxt < ' tcx > ,
2223 ty : Ty < ' tcx > ,
2324 body_did : DefId ,
24- ) -> Option < ( Size , u64 , Vec < Size > ) > {
25+ ) -> Option < ( u64 , Vec < Size > ) > {
2526 match ty. kind ( ) {
2627 ty:: Adt ( adt_def, _substs) if adt_def. is_enum ( ) => {
2728 let p_e = tcx. param_env ( body_did) ;
28- // FIXME(jknodt) handle error better below
2929 let layout =
3030 if let Ok ( layout) = tcx. layout_of ( p_e. and ( ty) ) { layout } else { return None } ;
3131 let variants = & layout. variants ;
@@ -50,7 +50,7 @@ impl<const D: u64> EnumSizeOpt<D> {
5050 assert_eq ! ( discr_sizes[ disc_idx] , Size :: ZERO ) ;
5151 discr_sizes[ disc_idx] = layout. size ;
5252 }
53- Some ( ( layout . size , variants. len ( ) as u64 , discr_sizes) )
53+ Some ( ( variants. len ( ) as u64 , discr_sizes) )
5454 }
5555 }
5656 }
@@ -73,28 +73,44 @@ impl<const D: u64> EnumSizeOpt<D> {
7373 let source_info = st. source_info ;
7474 let span = source_info. span ;
7575
76- let ( total_size , num_variants, sizes) =
76+ let ( num_variants, sizes) =
7777 if let Some ( cand) = Self :: candidate ( tcx, ty, body_did) {
7878 cand
7979 } else {
8080 return None ;
8181 } ;
8282 let adt_def = ty. ty_adt_def ( ) . unwrap ( ) ;
83-
8483 let alloc = if let Some ( alloc) = alloc_cache. get ( ty) {
8584 alloc
8685 } else {
87- let mut data =
88- vec ! [ 0 ; std:: mem:: size_of:: <usize >( ) * num_variants as usize ] ;
89-
86+ let data_layout = tcx. data_layout ( ) ;
87+ let ptr_sized_int = data_layout. ptr_sized_integer ( ) ;
88+ let target_bytes = ptr_sized_int. size ( ) . bytes ( ) as usize ;
89+ let mut data = vec ! [ 0 ; target_bytes * num_variants as usize ] ;
9090 let mut curr = 0 ;
91- for byte in sizes
92- . iter ( )
93- . flat_map ( |sz| sz. bytes ( ) . to_ne_bytes ( ) )
94- . take ( data. len ( ) )
95- {
96- data[ curr] = byte;
97- curr += 1 ;
91+ macro_rules! encode_store {
92+ ( $endian: expr, $bytes: expr) => {
93+ let bytes = match $endian {
94+ rustc_target:: abi:: Endian :: Little => $bytes. to_le_bytes( ) ,
95+ rustc_target:: abi:: Endian :: Big => $bytes. to_be_bytes( ) ,
96+ } ;
97+ for b in bytes {
98+ data[ curr] = b;
99+ curr += 1 ;
100+ }
101+ } ;
102+ }
103+
104+ for sz in sizes {
105+ match ptr_sized_int {
106+ rustc_target:: abi:: Integer :: I32 => {
107+ encode_store ! ( data_layout. endian, sz. bytes( ) as u32 ) ;
108+ }
109+ rustc_target:: abi:: Integer :: I64 => {
110+ encode_store ! ( data_layout. endian, sz. bytes( ) ) ;
111+ }
112+ _ => unreachable ! ( ) ,
113+ } ;
98114 }
99115 let alloc = interpret:: Allocation :: from_bytes (
100116 data,
@@ -162,7 +178,6 @@ impl<const D: u64> EnumSizeOpt<D> {
162178 ) ) ,
163179 } ;
164180
165- // FIXME(jknodt) do I need to add a storage live here for this place?
166181 let size_place =
167182 Place :: from ( local_decls. push ( LocalDecl :: new ( tcx. types . usize , span) ) ) ;
168183
@@ -230,24 +245,15 @@ impl<const D: u64> EnumSizeOpt<D> {
230245 kind : StatementKind :: CopyNonOverlapping ( box CopyNonOverlapping {
231246 src : Operand :: Copy ( src_cast_place) ,
232247 dst : Operand :: Copy ( dst_cast_place) ,
233- count : Operand :: Constant (
234- box ( Constant {
235- span,
236- user_ty : None ,
237- literal : ConstantKind :: Val (
238- interpret:: ConstValue :: from_u64 ( total_size. bytes ( ) ) ,
239- tcx. types . usize ,
240- ) ,
241- } ) ,
242- ) ,
248+ count : Operand :: Copy ( size_place) ,
243249 } ) ,
244250 } ;
245251
246252 let store_dead = Statement {
247253 source_info,
248254 kind : StatementKind :: StorageDead ( size_array_local) ,
249255 } ;
250- let iter = std :: array :: IntoIter :: new ( [
256+ let iter = IntoIter :: new ( [
251257 store_live,
252258 const_assign,
253259 store_discr,
0 commit comments