@@ -10,7 +10,7 @@ use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
10
10
use rustc_middle:: ty:: print:: { FmtPrinter , PrettyPrinter , Printer } ;
11
11
use rustc_middle:: ty:: { ConstInt , DelaySpanBugEmitted , Ty } ;
12
12
use 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 } ;
14
14
use rustc_target:: abi:: { VariantIdx , Variants } ;
15
15
16
16
use super :: {
@@ -177,10 +177,17 @@ pub enum Operand<Tag: Provenance = AllocId> {
177
177
pub struct OpTy < ' tcx , Tag : Provenance = AllocId > {
178
178
op : Operand < Tag > , // Keep this private; it helps enforce invariants.
179
179
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 > ,
180
187
}
181
188
182
189
#[ 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 ) ;
184
191
185
192
impl < ' tcx , Tag : Provenance > std:: ops:: Deref for OpTy < ' tcx , Tag > {
186
193
type Target = Operand < Tag > ;
@@ -193,28 +200,28 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> {
193
200
impl < ' tcx , Tag : Provenance > From < MPlaceTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
194
201
#[ inline( always) ]
195
202
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 ) }
197
204
}
198
205
}
199
206
200
207
impl < ' tcx , Tag : Provenance > From < & ' _ MPlaceTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
201
208
#[ inline( always) ]
202
209
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 ) }
204
211
}
205
212
}
206
213
207
214
impl < ' tcx , Tag : Provenance > From < & ' _ mut MPlaceTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
208
215
#[ inline( always) ]
209
216
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 ) }
211
218
}
212
219
}
213
220
214
221
impl < ' tcx , Tag : Provenance > From < ImmTy < ' tcx , Tag > > for OpTy < ' tcx , Tag > {
215
222
#[ inline( always) ]
216
223
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 }
218
225
}
219
226
}
220
227
@@ -450,7 +457,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
450
457
) ,
451
458
} ;
452
459
453
- Ok ( OpTy { op : Operand :: Immediate ( field_val) , layout : field_layout } )
460
+ Ok ( OpTy { op : Operand :: Immediate ( field_val) , layout : field_layout, align : None } )
454
461
}
455
462
456
463
pub fn operand_index (
@@ -522,7 +529,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
522
529
///
523
530
/// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an
524
531
/// OpTy from a local
525
- pub fn access_local (
532
+ pub fn local_to_op (
526
533
& self ,
527
534
frame : & super :: Frame < ' mir , ' tcx , M :: PointerTag , M :: FrameExtra > ,
528
535
local : mir:: Local ,
@@ -535,7 +542,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
535
542
} else {
536
543
M :: access_local ( & self , frame, local) ?
537
544
} ;
538
- Ok ( OpTy { op, layout } )
545
+ Ok ( OpTy { op, layout, align : Some ( layout . align . abi ) } )
539
546
}
540
547
541
548
/// 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> {
549
556
let op = match * * place {
550
557
Place :: Ptr ( mplace) => Operand :: Indirect ( mplace) ,
551
558
Place :: Local { frame, local } => {
552
- * self . access_local ( & self . stack ( ) [ frame] , local, None ) ?
559
+ * self . local_to_op ( & self . stack ( ) [ frame] , local, None ) ?
553
560
}
554
561
} ;
555
- Ok ( OpTy { op, layout : place. layout } )
562
+ Ok ( OpTy { op, layout : place. layout , align : Some ( place . align ) } )
556
563
}
557
564
558
565
/// 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> {
566
573
// here is not the entire place.
567
574
let layout = if place. projection . is_empty ( ) { layout } else { None } ;
568
575
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) ?;
570
577
571
578
let op = place
572
579
. projection
@@ -603,11 +610,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
603
610
Constant ( ref constant) => {
604
611
let val =
605
612
self . subst_from_current_frame_and_normalize_erasing_regions ( constant. literal ) ?;
613
+
606
614
// This can still fail:
607
615
// * During ConstProp, with `TooGeneric` or since the `required_consts` were not all
608
616
// checked yet.
609
617
// * During CTFE, since promoteds in `const`/`static` initializer bodies can fail.
610
-
611
618
self . mir_const_to_op ( & val, layout) ?
612
619
}
613
620
} ;
@@ -683,7 +690,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
683
690
// We rely on mutability being set correctly in that allocation to prevent writes
684
691
// where none should happen.
685
692
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 ( ) ) )
687
694
}
688
695
ConstValue :: Scalar ( x) => Operand :: Immediate ( tag_scalar ( x) ?. into ( ) ) ,
689
696
ConstValue :: Slice { data, start, end } => {
@@ -700,7 +707,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
700
707
) )
701
708
}
702
709
} ;
703
- Ok ( OpTy { op, layout } )
710
+ Ok ( OpTy { op, layout, align : Some ( layout . align . abi ) } )
704
711
}
705
712
706
713
/// Read discriminant, return the runtime value as well as the variant index.
0 commit comments