Skip to content

Commit 4b367ba

Browse files
committed
Remove ScalarPair from ConstValue
1 parent b68fc18 commit 4b367ba

File tree

13 files changed

+178
-134
lines changed

13 files changed

+178
-134
lines changed

src/librustc/ich/impls_ty.rs

-1
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ impl_stable_hash_for!(
313313
impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValue ] {
314314
Unevaluated(def_id, substs),
315315
Scalar(val),
316-
ScalarPair(a, b),
317316
ByRef(id, alloc, offset),
318317
}
319318
);

src/librustc/mir/interpret/allocation.rs

+50-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use super::{
1515
truncate,
1616
};
1717

18-
use ty::layout::{Size, Align};
18+
use ty::layout::{Size, Align, self};
1919
use syntax::ast::Mutability;
2020
use std::iter;
2121
use mir;
@@ -325,6 +325,33 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
325325
Ok(())
326326
}
327327

328+
pub fn write_scalar_pair<MemoryExtra>(
329+
&mut self,
330+
cx: &impl HasDataLayout,
331+
ptr: Pointer<Tag>,
332+
a_val: ScalarMaybeUndef<Tag>,
333+
b_val: ScalarMaybeUndef<Tag>,
334+
layout: layout::TyLayout<'tcx>,
335+
) -> EvalResult<'tcx>
336+
// FIXME: Working around https://github.com/rust-lang/rust/issues/56209
337+
where Extra: AllocationExtra<Tag, MemoryExtra>
338+
{
339+
let (a, b) = match layout.abi {
340+
layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
341+
_ => bug!("write_scalar_pair: invalid ScalarPair layout: {:#?}", layout),
342+
};
343+
let (a_size, b_size) = (a.size(cx), b.size(cx));
344+
let b_offset = a_size.align_to(b.align(cx).abi);
345+
let b_ptr = ptr.offset(b_offset, cx)?;
346+
347+
// It is tempting to verify `b_offset` against `layout.fields.offset(1)`,
348+
// but that does not work: We could be a newtype around a pair, then the
349+
// fields do not match the `ScalarPair` components.
350+
351+
self.write_scalar(cx, ptr, a_val, a_size)?;
352+
self.write_scalar(cx, b_ptr, b_val, b_size)
353+
}
354+
328355
/// Sets `count` bytes starting at `ptr.offset` with `val`. Basically `memset`.
329356
pub fn write_repeat<MemoryExtra>(
330357
&mut self,
@@ -400,6 +427,28 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
400427
self.read_scalar(cx, ptr, cx.data_layout().pointer_size)
401428
}
402429

430+
pub fn read_usize<MemoryExtra>(
431+
&self,
432+
cx: &impl HasDataLayout,
433+
ptr: Pointer<Tag>,
434+
) -> EvalResult<'tcx, u64>
435+
// FIXME: Working around https://github.com/rust-lang/rust/issues/56209
436+
where Extra: AllocationExtra<Tag, MemoryExtra>
437+
{
438+
self.read_ptr_sized(cx, ptr)?.not_undef()?.to_usize(cx)
439+
}
440+
441+
pub fn read_ptr<MemoryExtra>(
442+
&self,
443+
cx: &impl HasDataLayout,
444+
ptr: Pointer<Tag>,
445+
) -> EvalResult<'tcx, Pointer<Tag>>
446+
// FIXME: Working around https://github.com/rust-lang/rust/issues/56209
447+
where Extra: AllocationExtra<Tag, MemoryExtra>
448+
{
449+
self.read_ptr_sized(cx, ptr)?.not_undef()?.to_ptr()
450+
}
451+
403452
/// Write a *non-ZST* scalar
404453
///
405454
/// zsts can't be read out of two reasons:

src/librustc/mir/interpret/value.rs

+39-19
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use std::fmt;
1212

13-
use crate::ty::{Ty, subst::Substs, layout::{HasDataLayout, Size}};
13+
use crate::ty::{Ty, subst::Substs, layout::{HasDataLayout, Size}, TyCtxt};
1414
use crate::hir::def_id::DefId;
1515

1616
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
@@ -39,11 +39,6 @@ pub enum ConstValue<'tcx> {
3939
/// Not using the enum `Value` to encode that this must not be `Undef`
4040
Scalar(Scalar),
4141

42-
/// Used only for *fat pointers* with layout::abi::ScalarPair
43-
///
44-
/// Needed for pattern matching code related to slices and strings.
45-
ScalarPair(Scalar, Scalar),
46-
4742
/// An allocation + offset into the allocation.
4843
/// Invariant: The AllocId matches the allocation.
4944
ByRef(AllocId, &'tcx Allocation, Size),
@@ -54,8 +49,7 @@ impl<'tcx> ConstValue<'tcx> {
5449
pub fn try_to_scalar(&self) -> Option<Scalar> {
5550
match *self {
5651
ConstValue::Unevaluated(..) |
57-
ConstValue::ByRef(..) |
58-
ConstValue::ScalarPair(..) => None,
52+
ConstValue::ByRef(..) => None,
5953
ConstValue::Scalar(val) => Some(val),
6054
}
6155
}
@@ -71,20 +65,46 @@ impl<'tcx> ConstValue<'tcx> {
7165
}
7266

7367
#[inline]
74-
pub fn new_slice(
75-
val: Scalar,
76-
len: u64,
77-
cx: &impl HasDataLayout
78-
) -> Self {
79-
ConstValue::ScalarPair(val, Scalar::Bits {
80-
bits: len as u128,
81-
size: cx.data_layout().pointer_size.bytes() as u8,
82-
})
68+
pub fn new_slice(val: Scalar, len: u64, tcx: TyCtxt<'_, '_, 'tcx>) -> Self {
69+
Self::new_ptr_sized_seq(
70+
&[
71+
val,
72+
Scalar::Bits {
73+
bits: len as u128,
74+
size: tcx.data_layout.pointer_size.bytes() as u8,
75+
}
76+
],
77+
tcx,
78+
)
79+
}
80+
81+
#[inline]
82+
/// Used for fat pointers and vtables
83+
fn new_ptr_sized_seq(scalars: &[Scalar], tcx: TyCtxt<'_, '_, 'tcx>) -> Self {
84+
let mut allocation = Allocation::undef(
85+
tcx.data_layout.pointer_size * scalars.len() as u64,
86+
tcx.data_layout.pointer_align.abi,
87+
Default::default(),
88+
);
89+
let alloc_id = tcx.alloc_map.lock().reserve();
90+
let mut ptr = Pointer::from(alloc_id);
91+
for &scalar in scalars {
92+
allocation.write_scalar(
93+
&tcx,
94+
ptr,
95+
scalar.into(),
96+
tcx.data_layout.pointer_size,
97+
).unwrap();
98+
ptr = ptr.offset(tcx.data_layout.pointer_size, &tcx).unwrap();
99+
}
100+
let allocation = tcx.intern_const_alloc(allocation);
101+
tcx.alloc_map.lock().set_id_memory(alloc_id, allocation);
102+
ConstValue::ByRef(alloc_id, allocation, Size::ZERO)
83103
}
84104

85105
#[inline]
86-
pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
87-
ConstValue::ScalarPair(val, Scalar::Ptr(vtable))
106+
pub fn new_dyn_trait(val: Scalar, vtable: Pointer, tcx: TyCtxt<'_, '_, 'tcx>) -> Self {
107+
Self::new_ptr_sized_seq(&[val, Scalar::Ptr(vtable)], tcx)
88108
}
89109
}
90110

src/librustc/mir/mod.rs

+24-19
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use hir::def::CtorKind;
1616
use hir::def_id::DefId;
1717
use hir::{self, HirId, InlineAsm};
18-
use mir::interpret::{ConstValue, EvalErrorKind, Scalar};
18+
use mir::interpret::{ConstValue, EvalErrorKind, Scalar, Pointer, EvalResult};
1919
use mir::visit::MirVisitable;
2020
use rustc_apfloat::ieee::{Double, Single};
2121
use rustc_apfloat::Float;
@@ -39,7 +39,7 @@ use syntax_pos::{Span, DUMMY_SP};
3939
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
4040
use ty::subst::{CanonicalUserSubsts, Subst, Substs};
4141
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
42-
use ty::layout::VariantIdx;
42+
use ty::layout::{VariantIdx, Size};
4343
use util::ppaux;
4444

4545
pub use mir::interpret::AssertMessage;
@@ -2623,24 +2623,29 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const<'_>) -> fmt::Resu
26232623
return write!(f, "{}", item_path_str(did));
26242624
}
26252625
// print string literals
2626-
if let ConstValue::ScalarPair(ptr, len) = value {
2627-
if let Scalar::Ptr(ptr) = ptr {
2628-
if let Scalar::Bits { bits: len, .. } = len {
2629-
if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
2630-
return ty::tls::with(|tcx| {
2631-
let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
2632-
if let Some(interpret::AllocType::Memory(alloc)) = alloc {
2633-
assert_eq!(len as usize as u128, len);
2634-
let slice =
2635-
&alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
2636-
let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
2637-
write!(f, "{:?}", s)
2638-
} else {
2639-
write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
2640-
}
2641-
});
2626+
if let ConstValue::ByRef(alloc_id, alloc, offset) = value {
2627+
if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
2628+
return ty::tls::with(|tcx| {
2629+
let mut dummy = || -> EvalResult<'_, _> {
2630+
let ptr = Pointer::new(alloc_id, offset);
2631+
let slice_ptr = alloc.read_ptr(&tcx, ptr)?;
2632+
let ptr = ptr.offset(tcx.data_layout.pointer_size, &tcx)?;
2633+
let len = alloc.read_usize(&tcx, ptr)?;
2634+
let alloc = tcx.alloc_map.lock().get(slice_ptr.alloc_id);
2635+
if let Some(interpret::AllocType::Memory(alloc)) = alloc {
2636+
let slice = alloc.get_bytes(&tcx, slice_ptr, Size::from_bytes(len))?;
2637+
let s = ::std::str::from_utf8(slice)
2638+
.map_err(|err| EvalErrorKind::ValidationFailure(err.to_string()))?;
2639+
Ok(write!(f, "{:?}", s))
2640+
} else {
2641+
Ok(write!(f, "broken str slice: {:?}", alloc))
2642+
}
2643+
};
2644+
match dummy() {
2645+
Ok(res) => res,
2646+
Err(err) => write!(f, "broken str constant: {:?}", err),
26422647
}
2643-
}
2648+
});
26442649
}
26452650
}
26462651
// just raw dump everything else

src/librustc/ty/structural_impls.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,6 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
10321032
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
10331033
match *self {
10341034
ConstValue::Scalar(v) => ConstValue::Scalar(v),
1035-
ConstValue::ScalarPair(a, b) => ConstValue::ScalarPair(a, b),
10361035
ConstValue::ByRef(id, alloc, offset) => ConstValue::ByRef(id, alloc, offset),
10371036
ConstValue::Unevaluated(def_id, substs) => {
10381037
ConstValue::Unevaluated(def_id, substs.fold_with(folder))
@@ -1043,7 +1042,6 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
10431042
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
10441043
match *self {
10451044
ConstValue::Scalar(_) |
1046-
ConstValue::ScalarPair(_, _) |
10471045
ConstValue::ByRef(_, _, _) => false,
10481046
ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
10491047
}

src/librustc_codegen_ssa/mir/operand.rs

-17
Original file line numberDiff line numberDiff line change
@@ -99,23 +99,6 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
9999
);
100100
OperandValue::Immediate(llval)
101101
},
102-
ConstValue::ScalarPair(a, b) => {
103-
let (a_scalar, b_scalar) = match layout.abi {
104-
layout::Abi::ScalarPair(ref a, ref b) => (a, b),
105-
_ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
106-
};
107-
let a_llval = bx.cx().scalar_to_backend(
108-
a,
109-
a_scalar,
110-
bx.cx().scalar_pair_element_backend_type(layout, 0, true),
111-
);
112-
let b_llval = bx.cx().scalar_to_backend(
113-
b,
114-
b_scalar,
115-
bx.cx().scalar_pair_element_backend_type(layout, 1, true),
116-
);
117-
OperandValue::Pair(a_llval, b_llval)
118-
},
119102
ConstValue::ByRef(_, alloc, offset) => {
120103
return Ok(bx.load_operand(bx.cx().from_const_alloc(layout, alloc, offset)));
121104
},

src/librustc_mir/const_eval.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc::hir::def::Def;
2121
use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
2222
use rustc::mir;
2323
use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
24-
use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx};
24+
use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx, Size};
2525
use rustc::ty::subst::Subst;
2626
use rustc::traits::Reveal;
2727
use rustc_data_structures::indexed_vec::IndexVec;
@@ -141,8 +141,18 @@ pub fn op_to_const<'tcx>(
141141
},
142142
Ok(Immediate::Scalar(x)) =>
143143
ConstValue::Scalar(x.not_undef()?),
144-
Ok(Immediate::ScalarPair(a, b)) =>
145-
ConstValue::ScalarPair(a.not_undef()?, b.not_undef()?),
144+
Ok(Immediate::ScalarPair(a, b)) => {
145+
// create an allocation just for the fat pointer
146+
let mut allocation = Allocation::undef(op.layout.size, op.layout.align.abi, Default::default());
147+
let alloc_id = ecx.tcx.alloc_map.lock().reserve();
148+
let ptr = Pointer::from(alloc_id);
149+
// write the fat pointer into the allocation
150+
allocation.write_scalar_pair(&ecx.tcx.tcx, ptr, a, b, op.layout)?;
151+
// intern everything
152+
let allocation = ecx.tcx.intern_const_alloc(allocation);
153+
ecx.tcx.alloc_map.lock().set_id_memory(alloc_id, allocation);
154+
ConstValue::ByRef(alloc_id, allocation, Size::ZERO)
155+
},
146156
};
147157
Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty))
148158
}

src/librustc_mir/hair/cx/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
166166
LitKind::Str(ref s, _) => {
167167
let s = s.as_str();
168168
let id = self.tcx.allocate_bytes(s.as_bytes());
169-
ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &self.tcx)
169+
ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, self.tcx)
170170
},
171171
LitKind::ByteStr(ref data) => {
172172
let id = self.tcx.allocate_bytes(data);

src/librustc_mir/hair/pattern/_match.rs

+22-16
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,10 @@ use super::{PatternFoldable, PatternFolder, compare_const_vals};
179179
use rustc::hir::def_id::DefId;
180180
use rustc::hir::RangeEnd;
181181
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
182-
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx};
182+
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
183183

184184
use rustc::mir::Field;
185-
use rustc::mir::interpret::ConstValue;
185+
use rustc::mir::interpret::{ConstValue, Scalar, Pointer};
186186
use rustc::util::common::ErrorReported;
187187

188188
use syntax::attr::{SignedInt, UnsignedInt};
@@ -1387,21 +1387,27 @@ fn slice_pat_covered_by_constructor<'tcx>(
13871387
) -> Result<bool, ErrorReported> {
13881388
let data: &[u8] = match *ctor {
13891389
ConstantValue(const_val) => {
1390-
let val = match const_val.val {
1391-
ConstValue::Unevaluated(..) |
1392-
ConstValue::ByRef(..) => bug!("unexpected ConstValue: {:?}", const_val),
1393-
ConstValue::Scalar(val) | ConstValue::ScalarPair(val, _) => val,
1390+
let (ptr, len) = match const_val.val {
1391+
ConstValue::ByRef(alloc_id, alloc, offset) => {
1392+
let ptr = Pointer::new(alloc_id, offset);
1393+
let slice_ptr = alloc.read_ptr(&tcx, ptr).unwrap();
1394+
let len_ptr = ptr.offset(tcx.data_layout.pointer_size, &tcx).unwrap();
1395+
let len = alloc.read_usize(&tcx, len_ptr).unwrap();
1396+
(slice_ptr, len)
1397+
}
1398+
ConstValue::Scalar(Scalar::Ptr(ptr)) => {
1399+
match const_val.ty.builtin_deref(true).unwrap().ty.sty {
1400+
ty::TyKind::Array(e, n) => {
1401+
assert!(e == tcx.types.u8);
1402+
(ptr, n.unwrap_usize(tcx))
1403+
},
1404+
_ => bug!("bad ConstValue type: {:#?}", const_val),
1405+
}
1406+
},
1407+
_ => bug!("unexpected ConstValue: {:#?}", const_val),
13941408
};
1395-
if let Ok(ptr) = val.to_ptr() {
1396-
let is_array_ptr = const_val.ty
1397-
.builtin_deref(true)
1398-
.and_then(|t| t.ty.builtin_index())
1399-
.map_or(false, |t| t == tcx.types.u8);
1400-
assert!(is_array_ptr);
1401-
tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id).bytes.as_ref()
1402-
} else {
1403-
bug!("unexpected non-ptr ConstantValue")
1404-
}
1409+
let len = Size::from_bytes(len);
1410+
tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id).get_bytes(&tcx, ptr, len).unwrap()
14051411
}
14061412
_ => bug!()
14071413
};

0 commit comments

Comments
 (0)