@@ -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,18 @@ 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`); this field is only relevant for `Operand::Indirect`.
186+ /// Also CTFE ignores alignment anyway, so this is for Miri only.
187+ pub align : Option < Align > ,
180188}
181189
182190#[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
183- rustc_data_structures:: static_assert_size!( OpTy <' _>, 80 ) ;
191+ rustc_data_structures:: static_assert_size!( OpTy <' _>, 88 ) ;
184192
185193impl < ' tcx , Tag : Provenance > std:: ops:: Deref for OpTy < ' tcx , Tag > {
186194 type Target = Operand < Tag > ;
@@ -193,28 +201,28 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> {
193201impl < ' tcx , Tag : Provenance > From < MPlaceTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
194202 #[ inline( always) ]
195203 fn from ( mplace : MPlaceTy < ' tcx , Tag > ) -> Self {
196- OpTy { op : Operand :: Indirect ( * mplace) , layout : mplace. layout }
204+ OpTy { op : Operand :: Indirect ( * mplace) , layout : mplace. layout , align : Some ( mplace . align ) }
197205 }
198206}
199207
200208impl < ' tcx , Tag : Provenance > From < & ' _ MPlaceTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
201209 #[ inline( always) ]
202210 fn from ( mplace : & MPlaceTy < ' tcx , Tag > ) -> Self {
203- OpTy { op : Operand :: Indirect ( * * mplace) , layout : mplace. layout }
211+ OpTy { op : Operand :: Indirect ( * * mplace) , layout : mplace. layout , align : Some ( mplace . align ) }
204212 }
205213}
206214
207215impl < ' tcx , Tag : Provenance > From < & ' _ mut MPlaceTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
208216 #[ inline( always) ]
209217 fn from ( mplace : & mut MPlaceTy < ' tcx , Tag > ) -> Self {
210- OpTy { op : Operand :: Indirect ( * * mplace) , layout : mplace. layout }
218+ OpTy { op : Operand :: Indirect ( * * mplace) , layout : mplace. layout , align : Some ( mplace . align ) }
211219 }
212220}
213221
214222impl < ' tcx , Tag : Provenance > From < ImmTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
215223 #[ inline( always) ]
216224 fn from ( val : ImmTy < ' tcx , Tag > ) -> Self {
217- OpTy { op : Operand :: Immediate ( val. imm ) , layout : val. layout }
225+ OpTy { op : Operand :: Immediate ( val. imm ) , layout : val. layout , align : None }
218226 }
219227}
220228
@@ -450,7 +458,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
450458 ) ,
451459 } ;
452460
453- Ok ( OpTy { op : Operand :: Immediate ( field_val) , layout : field_layout } )
461+ Ok ( OpTy { op : Operand :: Immediate ( field_val) , layout : field_layout, align : None } )
454462 }
455463
456464 pub fn operand_index (
@@ -522,7 +530,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
522530 ///
523531 /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an
524532 /// OpTy from a local
525- pub fn access_local (
533+ pub fn local_to_op (
526534 & self ,
527535 frame : & super :: Frame < ' mir , ' tcx , M :: PointerTag , M :: FrameExtra > ,
528536 local : mir:: Local ,
@@ -535,7 +543,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
535543 } else {
536544 M :: access_local ( & self , frame, local) ?
537545 } ;
538- Ok ( OpTy { op, layout } )
546+ Ok ( OpTy { op, layout, align : Some ( layout . align . abi ) } )
539547 }
540548
541549 /// Every place can be read from, so we can turn them into an operand.
@@ -549,10 +557,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
549557 let op = match * * place {
550558 Place :: Ptr ( mplace) => Operand :: Indirect ( mplace) ,
551559 Place :: Local { frame, local } => {
552- * self . access_local ( & self . stack ( ) [ frame] , local, None ) ?
560+ * self . local_to_op ( & self . stack ( ) [ frame] , local, None ) ?
553561 }
554562 } ;
555- Ok ( OpTy { op, layout : place. layout } )
563+ Ok ( OpTy { op, layout : place. layout , align : Some ( place . align ) } )
556564 }
557565
558566 /// Evaluate a place with the goal of reading from it. This lets us sometimes
@@ -566,7 +574,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
566574 // here is not the entire place.
567575 let layout = if place. projection . is_empty ( ) { layout } else { None } ;
568576
569- let base_op = self . access_local ( self . frame ( ) , place. local , layout) ?;
577+ let base_op = self . local_to_op ( self . frame ( ) , place. local , layout) ?;
570578
571579 let op = place
572580 . projection
@@ -603,11 +611,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
603611 Constant ( ref constant) => {
604612 let val =
605613 self . subst_from_current_frame_and_normalize_erasing_regions ( constant. literal ) ?;
614+
606615 // This can still fail:
607616 // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all
608617 // checked yet.
609618 // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail.
610-
611619 self . mir_const_to_op ( & val, layout) ?
612620 }
613621 } ;
@@ -683,7 +691,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
683691 // We rely on mutability being set correctly in that allocation to prevent writes
684692 // where none should happen.
685693 let ptr = self . global_base_pointer ( Pointer :: new ( id, offset) ) ?;
686- Operand :: Indirect ( MemPlace :: from_ptr ( ptr. into ( ) , layout . align . abi ) )
694+ Operand :: Indirect ( MemPlace :: from_ptr ( ptr. into ( ) ) )
687695 }
688696 ConstValue :: Scalar ( x) => Operand :: Immediate ( tag_scalar ( x) ?. into ( ) ) ,
689697 ConstValue :: Slice { data, start, end } => {
@@ -700,7 +708,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
700708 ) )
701709 }
702710 } ;
703- Ok ( OpTy { op, layout } )
711+ Ok ( OpTy { op, layout, align : Some ( layout . align . abi ) } )
704712 }
705713
706714 /// Read discriminant, return the runtime value as well as the variant index.
0 commit comments