Skip to content

Commit e590b84

Browse files
committed
CTFE: simplify Value type by not checking for alignment
1 parent cf048cc commit e590b84

File tree

14 files changed

+50
-59
lines changed

14 files changed

+50
-59
lines changed

Diff for: 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

Diff for: 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),

Diff for: src/librustc_codegen_llvm/common.rs

+2-2
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,10 +329,10 @@ 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+
let align = alloc.align; // follow what CTFE did, not what the layout says
336336
let init = const_alloc_to_llvm(self, alloc);
337337
let base_addr = self.static_addr_of(init, align, None);
338338

Diff for: 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_),

Diff for: 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

Diff for: 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
},

Diff for: 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>;

Diff for: 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
@@ -552,9 +556,8 @@ fn validate_and_turn_into_const<'tcx>(
552556
let ptr = mplace.ptr.to_ptr()?;
553557
Ok(tcx.mk_const(ty::Const {
554558
val: ConstValue::ByRef {
555-
offset: ptr.offset,
556-
align: mplace.align,
557559
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
560+
offset: ptr.offset,
558561
},
559562
ty: mplace.layout.ty,
560563
}))

Diff for: 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

Diff for: 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

Diff for: src/librustc_mir/interpret/memory.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -338,11 +338,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
338338
Ok(bits) => {
339339
let bits = bits as u64; // it's ptr-sized
340340
assert!(size.bytes() == 0);
341-
// Must be non-NULL and aligned.
341+
// Must be non-NULL.
342342
if bits == 0 {
343343
throw_unsup!(InvalidNullPointerUsage)
344344
}
345-
check_offset_align(bits, align)?;
345+
// Must be aligned.
346+
if M::CHECK_ALIGN {
347+
check_offset_align(bits, align)?;
348+
}
346349
None
347350
}
348351
Err(ptr) => {
@@ -355,18 +358,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
355358
end_ptr.check_in_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?;
356359
// Test align. Check this last; if both bounds and alignment are violated
357360
// 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-
})
361+
if M::CHECK_ALIGN {
362+
if alloc_align.bytes() < align.bytes() {
363+
// The allocation itself is not aligned enough.
364+
// FIXME: Alignment check is too strict, depending on the base address that
365+
// got picked we might be aligned even if this check fails.
366+
// We instead have to fall back to converting to an integer and checking
367+
// the "real" alignment.
368+
throw_unsup!(AlignmentCheckFailed {
369+
has: alloc_align,
370+
required: align,
371+
});
372+
}
373+
check_offset_align(ptr.offset.bytes(), align)?;
368374
}
369-
check_offset_align(ptr.offset.bytes(), align)?;
370375

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

Diff for: src/librustc_mir/interpret/operand.rs

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

Diff for: src/test/ui/consts/const-eval/ub-ref.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55
use std::mem;
66

7-
const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
8-
//~^ ERROR it is undefined behavior to use this value
9-
//~^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1)
7+
const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; // Ok (CTFE does not check alignment)
108

119
const NULL: &u16 = unsafe { mem::transmute(0usize) };
1210
//~^ ERROR it is undefined behavior to use this value

Diff for: src/test/ui/consts/const-eval/ub-ref.stderr

+5-13
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,35 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/ub-ref.rs:7:1
3-
|
4-
LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1)
6-
|
7-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
8-
9-
error[E0080]: it is undefined behavior to use this value
10-
--> $DIR/ub-ref.rs:11:1
2+
--> $DIR/ub-ref.rs:9:1
113
|
124
LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
135
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
146
|
157
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
168

179
error[E0080]: it is undefined behavior to use this value
18-
--> $DIR/ub-ref.rs:14:1
10+
--> $DIR/ub-ref.rs:12:1
1911
|
2012
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
2113
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
2214
|
2315
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
2416

2517
error[E0080]: it is undefined behavior to use this value
26-
--> $DIR/ub-ref.rs:17:1
18+
--> $DIR/ub-ref.rs:15:1
2719
|
2820
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
2921
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
3022
|
3123
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
3224

3325
error[E0080]: it is undefined behavior to use this value
34-
--> $DIR/ub-ref.rs:20:1
26+
--> $DIR/ub-ref.rs:18:1
3527
|
3628
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
3729
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (created from integer)
3830
|
3931
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
4032

41-
error: aborting due to 5 previous errors
33+
error: aborting due to 4 previous errors
4234

4335
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)