@@ -10,7 +10,7 @@ use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
1010use rustc_middle:: ty:: print:: { FmtPrinter , PrettyPrinter , Printer } ;
1111use rustc_middle:: ty:: { ConstInt , DelaySpanBugEmitted , Ty } ;
1212use rustc_middle:: { mir, ty} ;
13- use rustc_target:: abi:: { self , Abi , HasDataLayout , Size , TagEncoding } ;
13+ use rustc_target:: abi:: { self , Abi , Align , HasDataLayout , Size , TagEncoding } ;
1414use rustc_target:: abi:: { VariantIdx , Variants } ;
1515
1616use super :: {
@@ -177,10 +177,17 @@ pub enum Operand<Tag: Provenance = AllocId> {
177177pub struct OpTy < ' tcx , Tag : Provenance = AllocId > {
178178 op : Operand < Tag > , // Keep this private; it helps enforce invariants.
179179 pub layout : TyAndLayout < ' tcx > ,
180+ /// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct:
181+ /// it needs to have a different alignment than the field type would usually have.
182+ /// So we represent this here with a separate field that "overwrites" `layout.align`.
183+ /// This means `layout.align` should never be used for an `OpTy`!
184+ /// `None` means "alignment does not matter since this is a by-value operand"
185+ /// (`Operand::Immediate`).
186+ pub align : Option < Align > ,
180187}
181188
182189#[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
183- rustc_data_structures:: static_assert_size!( OpTy <' _>, 80 ) ;
190+ rustc_data_structures:: static_assert_size!( OpTy <' _>, 88 ) ;
184191
185192impl < ' tcx , Tag : Provenance > std:: ops:: Deref for OpTy < ' tcx , Tag > {
186193 type Target = Operand < Tag > ;
@@ -193,28 +200,28 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> {
193200impl < ' tcx , Tag : Provenance > From < MPlaceTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
194201 #[ inline( always) ]
195202 fn from ( mplace : MPlaceTy < ' tcx , Tag > ) -> Self {
196- OpTy { op : Operand :: Indirect ( * mplace) , layout : mplace. layout }
203+ OpTy { op : Operand :: Indirect ( * mplace) , layout : mplace. layout , align : Some ( mplace . align ) }
197204 }
198205}
199206
200207impl < ' tcx , Tag : Provenance > From < & ' _ MPlaceTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
201208 #[ inline( always) ]
202209 fn from ( mplace : & MPlaceTy < ' tcx , Tag > ) -> Self {
203- OpTy { op : Operand :: Indirect ( * * mplace) , layout : mplace. layout }
210+ OpTy { op : Operand :: Indirect ( * * mplace) , layout : mplace. layout , align : Some ( mplace . align ) }
204211 }
205212}
206213
207214impl < ' tcx , Tag : Provenance > From < & ' _ mut MPlaceTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
208215 #[ inline( always) ]
209216 fn from ( mplace : & mut MPlaceTy < ' tcx , Tag > ) -> Self {
210- OpTy { op : Operand :: Indirect ( * * mplace) , layout : mplace. layout }
217+ OpTy { op : Operand :: Indirect ( * * mplace) , layout : mplace. layout , align : Some ( mplace . align ) }
211218 }
212219}
213220
214221impl < ' tcx , Tag : Provenance > From < ImmTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
215222 #[ inline( always) ]
216223 fn from ( val : ImmTy < ' tcx , Tag > ) -> Self {
217- OpTy { op : Operand :: Immediate ( val. imm ) , layout : val. layout }
224+ OpTy { op : Operand :: Immediate ( val. imm ) , layout : val. layout , align : None }
218225 }
219226}
220227
@@ -450,7 +457,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
450457 ) ,
451458 } ;
452459
453- Ok ( OpTy { op : Operand :: Immediate ( field_val) , layout : field_layout } )
460+ Ok ( OpTy { op : Operand :: Immediate ( field_val) , layout : field_layout, align : None } )
454461 }
455462
456463 pub fn operand_index (
@@ -522,7 +529,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
522529 ///
523530 /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an
524531 /// OpTy from a local
525- pub fn access_local (
532+ pub fn local_to_op (
526533 & self ,
527534 frame : & super :: Frame < ' mir , ' tcx , M :: PointerTag , M :: FrameExtra > ,
528535 local : mir:: Local ,
@@ -535,7 +542,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
535542 } else {
536543 M :: access_local ( & self , frame, local) ?
537544 } ;
538- Ok ( OpTy { op, layout } )
545+ Ok ( OpTy { op, layout, align : Some ( layout . align . abi ) } )
539546 }
540547
541548 /// Every place can be read from, so we can turn them into an operand.
@@ -549,10 +556,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
549556 let op = match * * place {
550557 Place :: Ptr ( mplace) => Operand :: Indirect ( mplace) ,
551558 Place :: Local { frame, local } => {
552- * self . access_local ( & self . stack ( ) [ frame] , local, None ) ?
559+ * self . local_to_op ( & self . stack ( ) [ frame] , local, None ) ?
553560 }
554561 } ;
555- Ok ( OpTy { op, layout : place. layout } )
562+ Ok ( OpTy { op, layout : place. layout , align : Some ( place . align ) } )
556563 }
557564
558565 /// Evaluate a place with the goal of reading from it. This lets us sometimes
@@ -566,7 +573,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
566573 // here is not the entire place.
567574 let layout = if place. projection . is_empty ( ) { layout } else { None } ;
568575
569- let base_op = self . access_local ( self . frame ( ) , place. local , layout) ?;
576+ let base_op = self . local_to_op ( self . frame ( ) , place. local , layout) ?;
570577
571578 let op = place
572579 . projection
@@ -603,11 +610,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
603610 Constant ( ref constant) => {
604611 let val =
605612 self . subst_from_current_frame_and_normalize_erasing_regions ( constant. literal ) ?;
613+
606614 // This can still fail:
607615 // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all
608616 // checked yet.
609617 // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail.
610-
611618 self . mir_const_to_op ( & val, layout) ?
612619 }
613620 } ;
@@ -683,7 +690,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
683690 // We rely on mutability being set correctly in that allocation to prevent writes
684691 // where none should happen.
685692 let ptr = self . global_base_pointer ( Pointer :: new ( id, offset) ) ?;
686- Operand :: Indirect ( MemPlace :: from_ptr ( ptr. into ( ) , layout . align . abi ) )
693+ Operand :: Indirect ( MemPlace :: from_ptr ( ptr. into ( ) ) )
687694 }
688695 ConstValue :: Scalar ( x) => Operand :: Immediate ( tag_scalar ( x) ?. into ( ) ) ,
689696 ConstValue :: Slice { data, start, end } => {
@@ -700,7 +707,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
700707 ) )
701708 }
702709 } ;
703- Ok ( OpTy { op, layout } )
710+ Ok ( OpTy { op, layout, align : Some ( layout . align . abi ) } )
704711 }
705712
706713 /// Read discriminant, return the runtime value as well as the variant index.
0 commit comments