Skip to content

Commit fb37bf0

Browse files
committed
Weave the alignment through ByRef
1 parent 921f0d9 commit fb37bf0

File tree

12 files changed

+41
-42
lines changed

12 files changed

+41
-42
lines changed

src/librustc/mir/interpret/value.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::fmt;
22
use rustc_macros::HashStable;
33
use rustc_apfloat::{Float, ieee::{Double, Single}};
44

5-
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef};
5+
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size, Align}, subst::SubstsRef};
66
use crate::ty::PlaceholderConst;
77
use crate::hir::def_id::DefId;
88

@@ -45,7 +45,9 @@ pub enum ConstValue<'tcx> {
4545

4646
/// An allocation together with a pointer into the allocation.
4747
/// Invariant: the pointer's `AllocId` resolves to the allocation.
48-
ByRef(Pointer, &'tcx Allocation),
48+
/// The alignment exists to allow `const_field` to have `ByRef` access to nonprimitive fields
49+
/// of packed structs.
50+
ByRef(Pointer, Align, &'tcx Allocation),
4951

5052
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
5153
/// variants when the code is monomorphic enough for that.

src/librustc/ty/structural_impls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
13351335
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
13361336
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
13371337
match *self {
1338-
ConstValue::ByRef(ptr, alloc) => ConstValue::ByRef(ptr, alloc),
1338+
ConstValue::ByRef(ptr, align, alloc) => ConstValue::ByRef(ptr, align, alloc),
13391339
ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)),
13401340
ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
13411341
ConstValue::Placeholder(p) => ConstValue::Placeholder(p),

src/librustc_codegen_llvm/common.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::value::Value;
1111
use rustc_codegen_ssa::traits::*;
1212

1313
use crate::consts::const_alloc_to_llvm;
14-
use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size};
14+
use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size, Align};
1515
use rustc::mir::interpret::{Scalar, GlobalAlloc, Allocation};
1616
use rustc_codegen_ssa::mir::place::PlaceRef;
1717

@@ -344,19 +344,20 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
344344
fn from_const_alloc(
345345
&self,
346346
layout: TyLayout<'tcx>,
347+
align: Align,
347348
alloc: &Allocation,
348349
offset: Size,
349350
) -> PlaceRef<'tcx, &'ll Value> {
350351
let init = const_alloc_to_llvm(self, alloc);
351-
let base_addr = self.static_addr_of(init, layout.align.abi, None);
352+
let base_addr = self.static_addr_of(init, align, None);
352353

353354
let llval = unsafe { llvm::LLVMConstInBoundsGEP(
354355
self.const_bitcast(base_addr, self.type_i8p()),
355356
&self.const_usize(offset.bytes()),
356357
1,
357358
)};
358359
let llval = self.const_bitcast(llval, self.type_ptr_to(layout.llvm_type(self)));
359-
PlaceRef::new_sized(llval, layout, alloc.align)
360+
PlaceRef::new_sized(llval, layout, align)
360361
}
361362

362363
fn const_ptrcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {

src/librustc_codegen_llvm/consts.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ pub fn codegen_static_initializer(
7171
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
7272

7373
let alloc = match static_.val {
74-
ConstValue::ByRef(ptr, alloc) if ptr.offset.bytes() == 0 => alloc,
74+
ConstValue::ByRef(ptr, align, alloc) if ptr.offset.bytes() == 0 && align == alloc.align => {
75+
alloc
76+
},
7577
_ => bug!("static const eval returned {:#?}", static_),
7678
};
7779
Ok((const_alloc_to_llvm(cx, alloc), alloc))

src/librustc_codegen_ssa/mir/operand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
109109
let b_llval = bx.const_usize((end - start) as u64);
110110
OperandValue::Pair(a_llval, b_llval)
111111
},
112-
ConstValue::ByRef(ptr, alloc) => {
113-
return bx.load_operand(bx.from_const_alloc(layout, alloc, ptr.offset));
112+
ConstValue::ByRef(ptr, align, alloc) => {
113+
return bx.load_operand(bx.from_const_alloc(layout, align, alloc, ptr.offset));
114114
},
115115
};
116116

src/librustc_codegen_ssa/mir/place.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
424424
let layout = cx.layout_of(self.monomorphize(&ty));
425425
match bx.tcx().const_eval(param_env.and(cid)) {
426426
Ok(val) => match val.val {
427-
mir::interpret::ConstValue::ByRef(ptr, alloc) => {
428-
bx.cx().from_const_alloc(layout, alloc, ptr.offset)
427+
mir::interpret::ConstValue::ByRef(ptr, align, alloc) => {
428+
bx.cx().from_const_alloc(layout, align, alloc, ptr.offset)
429429
}
430430
_ => bug!("promoteds should have an allocation: {:?}", val),
431431
},

src/librustc_codegen_ssa/traits/consts.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
3434
fn from_const_alloc(
3535
&self,
3636
layout: layout::TyLayout<'tcx>,
37+
align: layout::Align,
3738
alloc: &Allocation,
3839
offset: layout::Size,
3940
) -> PlaceRef<'tcx, Self::Value>;

src/librustc_mir/const_eval.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn op_to_const<'tcx>(
9999
Ok(mplace) => {
100100
let ptr = mplace.ptr.to_ptr().unwrap();
101101
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
102-
ConstValue::ByRef(ptr, alloc)
102+
ConstValue::ByRef(ptr, mplace.align, alloc)
103103
},
104104
// see comment on `let try_as_immediate` above
105105
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
@@ -113,7 +113,7 @@ fn op_to_const<'tcx>(
113113
let mplace = op.to_mem_place();
114114
let ptr = mplace.ptr.to_ptr().unwrap();
115115
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
116-
ConstValue::ByRef(ptr, alloc)
116+
ConstValue::ByRef(ptr, mplace.align, alloc)
117117
},
118118
},
119119
Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
@@ -482,10 +482,7 @@ pub fn const_field<'tcx>(
482482
trace!("const_field: {:?}, {:?}", field, value);
483483
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
484484
// get the operand again
485-
let mut op = ecx.eval_const_to_op(value, None).unwrap();
486-
// Ignore the alignment when accessing the field, since it may be a field of a
487-
// packed struct and thus end up causing an alignment error if we read from it.
488-
op.force_unaligned_access();
485+
let op = ecx.eval_const_to_op(value, None).unwrap();
489486
// downcast
490487
let down = match variant {
491488
None => op,
@@ -544,7 +541,11 @@ fn validate_and_turn_into_const<'tcx>(
544541
if tcx.is_static(def_id) || cid.promoted.is_some() {
545542
let ptr = mplace.ptr.to_ptr()?;
546543
Ok(tcx.mk_const(ty::Const {
547-
val: ConstValue::ByRef(ptr, ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id)),
544+
val: ConstValue::ByRef(
545+
ptr,
546+
mplace.align,
547+
ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
548+
),
548549
ty: mplace.layout.ty,
549550
}))
550551
} else {

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,15 @@ impl LiteralExpander<'tcx> {
215215
debug!("fold_const_value_deref {:?} {:?} {:?}", val, rty, crty);
216216
match (val, &crty.sty, &rty.sty) {
217217
// the easy case, deref a reference
218-
(ConstValue::Scalar(Scalar::Ptr(p)), x, y) if x == y => ConstValue::ByRef(
219-
p,
220-
self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id),
221-
),
218+
(ConstValue::Scalar(Scalar::Ptr(p)), x, y) if x == y => {
219+
let alloc = self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id);
220+
ConstValue::ByRef(
221+
p,
222+
// FIXME(oli-obk): this should be the type's layout
223+
alloc.align,
224+
alloc,
225+
)
226+
},
222227
// unsize array to slice if pattern is array but match value or other patterns are slice
223228
(ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => {
224229
assert_eq!(t, u);
@@ -1431,7 +1436,7 @@ fn slice_pat_covered_by_const<'tcx>(
14311436
suffix: &[Pattern<'tcx>],
14321437
) -> Result<bool, ErrorReported> {
14331438
let data: &[u8] = match (const_val.val, &const_val.ty.sty) {
1434-
(ConstValue::ByRef(ptr, alloc), ty::Array(t, n)) => {
1439+
(ConstValue::ByRef(ptr, _, alloc), ty::Array(t, n)) => {
14351440
assert_eq!(*t, tcx.types.u8);
14361441
let n = n.assert_usize(tcx).unwrap();
14371442
alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
@@ -1753,7 +1758,7 @@ fn specialize<'p, 'a: 'p, 'tcx>(
17531758
let (alloc, offset, n, ty) = match value.ty.sty {
17541759
ty::Array(t, n) => {
17551760
match value.val {
1756-
ConstValue::ByRef(ptr, alloc) => (
1761+
ConstValue::ByRef(ptr, _, alloc) => (
17571762
alloc,
17581763
ptr.offset,
17591764
n.unwrap_usize(cx.tcx),

src/librustc_mir/interpret/operand.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::convert::TryInto;
55

66
use rustc::{mir, ty};
77
use rustc::ty::layout::{
8-
self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx, Align,
8+
self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx,
99
};
1010

1111
use rustc::mir::interpret::{
@@ -179,19 +179,6 @@ impl<'tcx, Tag> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
179179
}
180180
}
181181

182-
impl<'tcx, Tag> OpTy<'tcx, Tag> {
183-
/// This function exists solely for pattern matching. If we pattern match a packed struct with
184-
/// an ADT field, the constant representing that field will have lost the information about the
185-
/// packedness. We could clone the allocation and adjust the alignment, but that seems wasteful,
186-
/// since the alignment is already encoded in the allocation. We know it is alright, because
187-
/// validation checked everything before the initial constant entered match checking.
188-
pub(crate) fn force_unaligned_access(&mut self) {
189-
if let Operand::Indirect(mplace) = &mut self.op {
190-
mplace.align = Align::from_bytes(1).unwrap();
191-
}
192-
}
193-
}
194-
195182
impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag>
196183
{
197184
#[inline]
@@ -551,11 +538,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
551538
self.layout_of(self.monomorphize(val.ty)?)
552539
})?;
553540
let op = match val.val {
554-
ConstValue::ByRef(ptr, _alloc) => {
541+
ConstValue::ByRef(ptr, align, _alloc) => {
555542
// We rely on mutability being set correctly in that allocation to prevent writes
556543
// where none should happen.
557544
let ptr = self.tag_static_base_pointer(ptr);
558-
Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi))
545+
Operand::Indirect(MemPlace::from_ptr(ptr, align))
559546
},
560547
ConstValue::Scalar(x) =>
561548
Operand::Immediate(Immediate::Scalar(tag_scalar(x).into())),

src/librustc_mir/monomorphize/collector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1262,7 +1262,7 @@ fn collect_const<'tcx>(
12621262
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
12631263
collect_miri(tcx, ptr.alloc_id, output),
12641264
ConstValue::Slice { data: alloc, start: _, end: _ } |
1265-
ConstValue::ByRef(_, alloc) => {
1265+
ConstValue::ByRef(_, _, alloc) => {
12661266
for &((), id) in alloc.relocations.values() {
12671267
collect_miri(tcx, id, output);
12681268
}

src/librustc_typeck/check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
14481448
};
14491449
let param_env = ty::ParamEnv::reveal_all();
14501450
if let Ok(static_) = tcx.const_eval(param_env.and(cid)) {
1451-
let alloc = if let ConstValue::ByRef(_, allocation) = static_.val {
1451+
let alloc = if let ConstValue::ByRef(_, _, allocation) = static_.val {
14521452
allocation
14531453
} else {
14541454
bug!("Matching on non-ByRef static")

0 commit comments

Comments
 (0)