Skip to content

Commit 4be0675

Browse files
committed
Auto merge of #63079 - RalfJung:ctfe-no-align, r=oli-obk
CTFE: simplify ConstValue by not checking for alignment I hope the test suite actually covers the problematic cases here? r? @oli-obk Fixes #61952
2 parents e1d7e4a + 0cf4329 commit 4be0675

File tree

13 files changed

+62
-46
lines changed

13 files changed

+62
-46
lines changed

src/librustc/mir/interpret/value.rs

+3-10
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, Align}, subst::SubstsRef};
5+
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef};
66
use crate::ty::PlaceholderConst;
77
use crate::hir::def_id::DefId;
88

@@ -45,18 +45,11 @@ pub enum ConstValue<'tcx> {
4545

4646
/// A value not represented/representable by `Scalar` or `Slice`
4747
ByRef {
48-
/// The alignment exists to allow `const_field` to have `ByRef` access to nonprimitive
49-
/// fields of `repr(packed)` structs. The alignment may be lower than the type of this
50-
/// constant. This permits reads with lower alignment than what the type would normally
51-
/// require.
52-
/// FIXME(RalfJ,oli-obk): The alignment checks are part of miri, but const eval doesn't
53-
/// really need them. Disabling them may be too hard though.
54-
align: Align,
55-
/// Offset into `alloc`
56-
offset: Size,
5748
/// The backing memory of the value, may contain more memory than needed for just the value
5849
/// in order to share `Allocation`s between values
5950
alloc: &'tcx Allocation,
51+
/// Offset into `alloc`
52+
offset: Size,
6053
},
6154

6255
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other

src/librustc/ty/structural_impls.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1367,8 +1367,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
13671367
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
13681368
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
13691369
match *self {
1370-
ConstValue::ByRef { offset, align, alloc } =>
1371-
ConstValue::ByRef { offset, align, alloc },
1370+
ConstValue::ByRef { alloc, offset } =>
1371+
ConstValue::ByRef { alloc, offset },
13721372
ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)),
13731373
ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
13741374
ConstValue::Placeholder(p) => ConstValue::Placeholder(p),

src/librustc_codegen_llvm/common.rs

+4-4
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, Align};
14+
use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size};
1515
use rustc::mir::interpret::{Scalar, GlobalAlloc, Allocation};
1616
use rustc_codegen_ssa::mir::place::PlaceRef;
1717

@@ -329,20 +329,20 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
329329
fn from_const_alloc(
330330
&self,
331331
layout: TyLayout<'tcx>,
332-
align: Align,
333332
alloc: &Allocation,
334333
offset: Size,
335334
) -> PlaceRef<'tcx, &'ll Value> {
335+
assert_eq!(alloc.align, layout.align.abi);
336336
let init = const_alloc_to_llvm(self, alloc);
337-
let base_addr = self.static_addr_of(init, align, None);
337+
let base_addr = self.static_addr_of(init, alloc.align, None);
338338

339339
let llval = unsafe { llvm::LLVMConstInBoundsGEP(
340340
self.const_bitcast(base_addr, self.type_i8p()),
341341
&self.const_usize(offset.bytes()),
342342
1,
343343
)};
344344
let llval = self.const_bitcast(llval, self.type_ptr_to(layout.llvm_type(self)));
345-
PlaceRef::new_sized(llval, layout, align)
345+
PlaceRef::new_sized(llval, layout, alloc.align)
346346
}
347347

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

src/librustc_codegen_llvm/consts.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ pub fn codegen_static_initializer(
7272

7373
let alloc = match static_.val {
7474
ConstValue::ByRef {
75-
offset, align, alloc,
76-
} if offset.bytes() == 0 && align == alloc.align => {
75+
alloc, offset,
76+
} if offset.bytes() == 0 => {
7777
alloc
7878
},
7979
_ => bug!("static const eval returned {:#?}", static_),

src/librustc_codegen_ssa/mir/operand.rs

+2-2
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 { offset, align, alloc } => {
113-
return bx.load_operand(bx.from_const_alloc(layout, align, alloc, offset));
112+
ConstValue::ByRef { alloc, offset } => {
113+
return bx.load_operand(bx.from_const_alloc(layout, alloc, offset));
114114
},
115115
};
116116

src/librustc_codegen_ssa/mir/place.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
466466
let layout = cx.layout_of(self.monomorphize(&ty));
467467
match bx.tcx().const_eval(param_env.and(cid)) {
468468
Ok(val) => match val.val {
469-
mir::interpret::ConstValue::ByRef { offset, align, alloc } => {
470-
bx.cx().from_const_alloc(layout, align, alloc, offset)
469+
mir::interpret::ConstValue::ByRef { alloc, offset } => {
470+
bx.cx().from_const_alloc(layout, alloc, offset)
471471
}
472472
_ => bug!("promoteds should have an allocation: {:?}", val),
473473
},

src/librustc_codegen_ssa/traits/consts.rs

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ pub trait ConstMethods<'tcx>: BackendTypes {
3535
fn from_const_alloc(
3636
&self,
3737
layout: layout::TyLayout<'tcx>,
38-
align: layout::Align,
3938
alloc: &Allocation,
4039
offset: layout::Size,
4140
) -> PlaceRef<'tcx, Self::Value>;

src/librustc_mir/const_eval.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ fn op_to_const<'tcx>(
9898
Ok(mplace) => {
9999
let ptr = mplace.ptr.to_ptr().unwrap();
100100
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
101-
ConstValue::ByRef { offset: ptr.offset, align: mplace.align, alloc }
101+
ConstValue::ByRef { alloc, offset: ptr.offset }
102102
},
103103
// see comment on `let try_as_immediate` above
104104
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
@@ -112,7 +112,7 @@ fn op_to_const<'tcx>(
112112
let mplace = op.assert_mem_place();
113113
let ptr = mplace.ptr.to_ptr().unwrap();
114114
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
115-
ConstValue::ByRef { offset: ptr.offset, align: mplace.align, alloc }
115+
ConstValue::ByRef { alloc, offset: ptr.offset }
116116
},
117117
},
118118
Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
@@ -326,6 +326,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
326326

327327
const STATIC_KIND: Option<!> = None; // no copying of statics allowed
328328

329+
// We do not check for alignment to avoid having to carry an `Align`
330+
// in `ConstValue::ByRef`.
331+
const CHECK_ALIGN: bool = false;
332+
329333
#[inline(always)]
330334
fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
331335
false // for now, we don't enforce validity
@@ -561,9 +565,8 @@ fn validate_and_turn_into_const<'tcx>(
561565
let ptr = mplace.ptr.to_ptr()?;
562566
Ok(tcx.mk_const(ty::Const {
563567
val: ConstValue::ByRef {
564-
offset: ptr.offset,
565-
align: mplace.align,
566568
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
569+
offset: ptr.offset,
567570
},
568571
ty: mplace.layout.ty,
569572
}))

src/librustc_mir/hair/pattern/_match.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,8 @@ impl LiteralExpander<'tcx> {
218218
(ConstValue::Scalar(Scalar::Ptr(p)), x, y) if x == y => {
219219
let alloc = self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id);
220220
ConstValue::ByRef {
221-
offset: p.offset,
222-
// FIXME(oli-obk): this should be the type's layout
223-
align: alloc.align,
224221
alloc,
222+
offset: p.offset,
225223
}
226224
},
227225
// unsize array to slice if pattern is array but match value or other patterns are slice

src/librustc_mir/interpret/machine.rs

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ pub trait Machine<'mir, 'tcx>: Sized {
109109
/// that is added to the memory so that the work is not done twice.
110110
const STATIC_KIND: Option<Self::MemoryKinds>;
111111

112+
/// Whether memory accesses should be alignment-checked.
113+
const CHECK_ALIGN: bool;
114+
112115
/// Whether to enforce the validity invariant
113116
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
114117

src/librustc_mir/interpret/memory.rs

+31-13
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,24 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
306306
///
307307
/// Most of the time you should use `check_mplace_access`, but when you just have a pointer,
308308
/// this method is still appropriate.
309+
#[inline(always)]
309310
pub fn check_ptr_access(
310311
&self,
311312
sptr: Scalar<M::PointerTag>,
312313
size: Size,
313314
align: Align,
315+
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
316+
let align = if M::CHECK_ALIGN { Some(align) } else { None };
317+
self.check_ptr_access_align(sptr, size, align)
318+
}
319+
320+
/// Like `check_ptr_access`, but *definitely* checks alignment when `align`
321+
/// is `Some` (overriding `M::CHECK_ALIGN`).
322+
pub(super) fn check_ptr_access_align(
323+
&self,
324+
sptr: Scalar<M::PointerTag>,
325+
size: Size,
326+
align: Option<Align>,
314327
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
315328
fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
316329
if offset % align.bytes() == 0 {
@@ -338,11 +351,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
338351
Ok(bits) => {
339352
let bits = bits as u64; // it's ptr-sized
340353
assert!(size.bytes() == 0);
341-
// Must be non-NULL and aligned.
354+
// Must be non-NULL.
342355
if bits == 0 {
343356
throw_unsup!(InvalidNullPointerUsage)
344357
}
345-
check_offset_align(bits, align)?;
358+
// Must be aligned.
359+
if let Some(align) = align {
360+
check_offset_align(bits, align)?;
361+
}
346362
None
347363
}
348364
Err(ptr) => {
@@ -355,18 +371,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
355371
end_ptr.check_in_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?;
356372
// Test align. Check this last; if both bounds and alignment are violated
357373
// we want the error to be about the bounds.
358-
if alloc_align.bytes() < align.bytes() {
359-
// The allocation itself is not aligned enough.
360-
// FIXME: Alignment check is too strict, depending on the base address that
361-
// got picked we might be aligned even if this check fails.
362-
// We instead have to fall back to converting to an integer and checking
363-
// the "real" alignment.
364-
throw_unsup!(AlignmentCheckFailed {
365-
has: alloc_align,
366-
required: align,
367-
})
374+
if let Some(align) = align {
375+
if alloc_align.bytes() < align.bytes() {
376+
// The allocation itself is not aligned enough.
377+
// FIXME: Alignment check is too strict, depending on the base address that
378+
// got picked we might be aligned even if this check fails.
379+
// We instead have to fall back to converting to an integer and checking
380+
// the "real" alignment.
381+
throw_unsup!(AlignmentCheckFailed {
382+
has: alloc_align,
383+
required: align,
384+
});
385+
}
386+
check_offset_align(ptr.offset.bytes(), align)?;
368387
}
369-
check_offset_align(ptr.offset.bytes(), align)?;
370388

371389
// We can still be zero-sized in this branch, in which case we have to
372390
// return `None`.

src/librustc_mir/interpret/operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -557,12 +557,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
557557
self.layout_of(self.monomorphize(val.ty)?)
558558
})?;
559559
let op = match val.val {
560-
ConstValue::ByRef { offset, align, alloc } => {
560+
ConstValue::ByRef { alloc, offset } => {
561561
let id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
562562
// We rely on mutability being set correctly in that allocation to prevent writes
563563
// where none should happen.
564564
let ptr = self.tag_static_base_pointer(Pointer::new(id, offset));
565-
Operand::Indirect(MemPlace::from_ptr(ptr, align))
565+
Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi))
566566
},
567567
ConstValue::Scalar(x) =>
568568
Operand::Immediate(tag_scalar(x).into()),

src/librustc_mir/interpret/validity.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,9 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
398398
// alignment and size determined by the layout (size will be 0,
399399
// alignment should take attributes into account).
400400
.unwrap_or_else(|| (layout.size, layout.align.abi));
401-
let ptr: Option<_> = match self.ecx.memory.check_ptr_access(ptr, size, align) {
401+
let ptr: Option<_> = match
402+
self.ecx.memory.check_ptr_access_align(ptr, size, Some(align))
403+
{
402404
Ok(ptr) => ptr,
403405
Err(err) => {
404406
info!(

0 commit comments

Comments
 (0)