Skip to content

Commit c705877

Browse files
committed
Auto merge of #50249 - Zoxc:allocation-const, r=oli-obk
Introduce ConstValue and use it instead of miri's Value for constant values r? @oli-obk
2 parents 388df82 + 0aa92ac commit c705877

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1090
-753
lines changed

src/librustc/dep_graph/dep_node.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
//! user of the `DepNode` API of having to know how to compute the expected
6161
//! fingerprint for a given set of node parameters.
6262
63-
use mir::interpret::{GlobalId};
63+
use mir::interpret::{GlobalId, ConstValue};
6464
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
6565
use hir::map::DefPathHash;
6666
use hir::{HirId, ItemLocalId};
@@ -621,13 +621,14 @@ define_dep_nodes!( <'tcx>
621621
[input] UsedCrateSource(CrateNum),
622622
[input] PostorderCnums,
623623

624-
// This query is not expected to have inputs -- as a result, it's
625-
// not a good candidate for "replay" because it's essentially a
626-
// pure function of its input (and hence the expectation is that
627-
// no caller would be green **apart** from just this
628-
// query). Making it anonymous avoids hashing the result, which
624+
// These queries are not expected to have inputs -- as a result, they
625+
// are not good candidates for "replay" because they are essentially
626+
// pure functions of their input (and hence the expectation is that
627+
// no caller would be green **apart** from just these
628+
// queries). Making them anonymous avoids hashing the result, which
629629
// may save a bit of time.
630630
[anon] EraseRegionsTy { ty: Ty<'tcx> },
631+
[anon] ConstValueToAllocation { val: ConstValue<'tcx>, ty: Ty<'tcx> },
631632

632633
[input] Freevars(DefId),
633634
[input] MaybeUnusedTraitImport(DefId),

src/librustc/ich/impls_ty.rs

+24
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,30 @@ for ::middle::const_val::ConstVal<'gcx> {
384384
}
385385
}
386386

387+
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
388+
for ::mir::interpret::ConstValue<'gcx> {
389+
fn hash_stable<W: StableHasherResult>(&self,
390+
hcx: &mut StableHashingContext<'a>,
391+
hasher: &mut StableHasher<W>) {
392+
use mir::interpret::ConstValue::*;
393+
394+
mem::discriminant(self).hash_stable(hcx, hasher);
395+
396+
match *self {
397+
ByVal(val) => {
398+
val.hash_stable(hcx, hasher);
399+
}
400+
ByValPair(a, b) => {
401+
a.hash_stable(hcx, hasher);
402+
b.hash_stable(hcx, hasher);
403+
}
404+
ByRef(alloc) => {
405+
alloc.hash_stable(hcx, hasher);
406+
}
407+
}
408+
}
409+
}
410+
387411
impl_stable_hash_for!(enum mir::interpret::Value {
388412
ByVal(v),
389413
ByValPair(a, b),

src/librustc/middle/const_val.rs

+2-22
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use hir::def_id::DefId;
1212
use ty::{self, TyCtxt, layout};
1313
use ty::subst::Substs;
14-
use mir::interpret::{Value, PrimVal};
14+
use mir::interpret::ConstValue;
1515
use errors::DiagnosticBuilder;
1616

1717
use graphviz::IntoCow;
@@ -25,27 +25,7 @@ pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
2525
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
2626
pub enum ConstVal<'tcx> {
2727
Unevaluated(DefId, &'tcx Substs<'tcx>),
28-
Value(Value),
29-
}
30-
31-
impl<'tcx> ConstVal<'tcx> {
32-
pub fn to_raw_bits(&self) -> Option<u128> {
33-
match *self {
34-
ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => {
35-
Some(b)
36-
},
37-
_ => None,
38-
}
39-
}
40-
pub fn unwrap_u64(&self) -> u64 {
41-
match self.to_raw_bits() {
42-
Some(val) => {
43-
assert_eq!(val as u64 as u128, val);
44-
val as u64
45-
},
46-
None => bug!("expected constant u64, got {:#?}", self),
47-
}
48-
}
28+
Value(ConstValue<'tcx>),
4929
}
5030

5131
#[derive(Clone, Debug)]

src/librustc/middle/mem_categorization.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
945945

946946
// Always promote `[T; 0]` (even when e.g. borrowed mutably).
947947
let promotable = match expr_ty.sty {
948-
ty::TyArray(_, len) if len.val.to_raw_bits() == Some(0) => true,
948+
ty::TyArray(_, len) if len.assert_usize(self.tcx) == Some(0) => true,
949949
_ => promotable,
950950
};
951951

src/librustc/mir/interpret/mod.rs

+58-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod value;
1010

1111
pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage};
1212

13-
pub use self::value::{PrimVal, PrimValKind, Value, Pointer};
13+
pub use self::value::{PrimVal, PrimValKind, Value, Pointer, ConstValue};
1414

1515
use std::collections::BTreeMap;
1616
use std::fmt;
@@ -20,8 +20,10 @@ use ty::{self, TyCtxt};
2020
use ty::layout::{self, Align, HasDataLayout};
2121
use middle::region;
2222
use std::iter;
23+
use std::io;
2324
use syntax::ast::Mutability;
2425
use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
26+
use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian};
2527

2628
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
2729
pub enum Lock {
@@ -235,7 +237,7 @@ impl fmt::Display for AllocId {
235237
}
236238
}
237239

238-
#[derive(Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
240+
#[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
239241
pub struct Allocation {
240242
/// The actual bytes of the allocation.
241243
/// Note that the bytes of a pointer represent the offset of the pointer
@@ -254,17 +256,69 @@ pub struct Allocation {
254256
}
255257

256258
impl Allocation {
257-
pub fn from_bytes(slice: &[u8]) -> Self {
259+
pub fn from_bytes(slice: &[u8], align: Align) -> Self {
258260
let mut undef_mask = UndefMask::new(0);
259261
undef_mask.grow(slice.len() as u64, true);
260262
Self {
261263
bytes: slice.to_owned(),
262264
relocations: BTreeMap::new(),
263265
undef_mask,
264-
align: Align::from_bytes(1, 1).unwrap(),
266+
align,
265267
runtime_mutability: Mutability::Immutable,
266268
}
267269
}
270+
271+
pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self {
272+
Allocation::from_bytes(slice, Align::from_bytes(1, 1).unwrap())
273+
}
274+
275+
pub fn undef(size: u64, align: Align) -> Self {
276+
assert_eq!(size as usize as u64, size);
277+
Allocation {
278+
bytes: vec![0; size as usize],
279+
relocations: BTreeMap::new(),
280+
undef_mask: UndefMask::new(size),
281+
align,
282+
runtime_mutability: Mutability::Immutable,
283+
}
284+
}
285+
}
286+
287+
impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
288+
289+
////////////////////////////////////////////////////////////////////////////////
290+
// Methods to access integers in the target endianness
291+
////////////////////////////////////////////////////////////////////////////////
292+
293+
pub fn write_target_uint(
294+
endianness: layout::Endian,
295+
mut target: &mut [u8],
296+
data: u128,
297+
) -> Result<(), io::Error> {
298+
let len = target.len();
299+
match endianness {
300+
layout::Endian::Little => target.write_uint128::<LittleEndian>(data, len),
301+
layout::Endian::Big => target.write_uint128::<BigEndian>(data, len),
302+
}
303+
}
304+
305+
pub fn write_target_int(
306+
endianness: layout::Endian,
307+
mut target: &mut [u8],
308+
data: i128,
309+
) -> Result<(), io::Error> {
310+
let len = target.len();
311+
match endianness {
312+
layout::Endian::Little => target.write_int128::<LittleEndian>(data, len),
313+
layout::Endian::Big => target.write_int128::<BigEndian>(data, len),
314+
}
315+
}
316+
317+
pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result<u128, io::Error> {
318+
match endianness {
319+
layout::Endian::Little => source.read_uint128::<LittleEndian>(source.len()),
320+
layout::Endian::Big => source.read_uint128::<BigEndian>(source.len()),
321+
}
268322
}
269323

270324
////////////////////////////////////////////////////////////////////////////////

src/librustc/mir/interpret/value.rs

+63-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,69 @@
33
use ty::layout::{Align, HasDataLayout};
44
use ty;
55

6-
use super::{EvalResult, MemoryPointer, PointerArithmetic};
6+
use super::{EvalResult, MemoryPointer, PointerArithmetic, Allocation};
7+
8+
/// Represents a constant value in Rust. ByVal and ByValPair are optimizations which
9+
/// matches Value's optimizations for easy conversions between these two types
10+
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
11+
pub enum ConstValue<'tcx> {
12+
// Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
13+
ByVal(PrimVal),
14+
// Used only for types with layout::abi::ScalarPair
15+
ByValPair(PrimVal, PrimVal),
16+
// Used only for the remaining cases
17+
ByRef(&'tcx Allocation),
18+
}
19+
20+
impl<'tcx> ConstValue<'tcx> {
21+
#[inline]
22+
pub fn from_byval_value(val: Value) -> Self {
23+
match val {
24+
Value::ByRef(..) => bug!(),
25+
Value::ByValPair(a, b) => ConstValue::ByValPair(a, b),
26+
Value::ByVal(val) => ConstValue::ByVal(val),
27+
}
28+
}
29+
30+
#[inline]
31+
pub fn to_byval_value(&self) -> Option<Value> {
32+
match *self {
33+
ConstValue::ByRef(..) => None,
34+
ConstValue::ByValPair(a, b) => Some(Value::ByValPair(a, b)),
35+
ConstValue::ByVal(val) => Some(Value::ByVal(val)),
36+
}
37+
}
38+
39+
#[inline]
40+
pub fn from_primval(val: PrimVal) -> Self {
41+
ConstValue::ByVal(val)
42+
}
43+
44+
#[inline]
45+
pub fn to_primval(&self) -> Option<PrimVal> {
46+
match *self {
47+
ConstValue::ByRef(..) => None,
48+
ConstValue::ByValPair(..) => None,
49+
ConstValue::ByVal(val) => Some(val),
50+
}
51+
}
52+
53+
#[inline]
54+
pub fn to_bits(&self) -> Option<u128> {
55+
match self.to_primval() {
56+
Some(PrimVal::Bytes(val)) => Some(val),
57+
_ => None,
58+
}
59+
}
60+
61+
#[inline]
62+
pub fn to_ptr(&self) -> Option<MemoryPointer> {
63+
match self.to_primval() {
64+
Some(PrimVal::Ptr(ptr)) => Some(ptr),
65+
_ => None,
66+
}
67+
}
68+
}
769

870
/// A `Value` represents a single self-contained Rust value.
971
///

src/librustc/mir/mod.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html
1414
1515
use graphviz::IntoCow;
16-
use middle::const_val::ConstVal;
1716
use middle::region;
1817
use rustc_data_structures::sync::{Lrc};
1918
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -1549,11 +1548,7 @@ impl<'tcx> Operand<'tcx> {
15491548
span,
15501549
ty,
15511550
literal: Literal::Value {
1552-
value: tcx.mk_const(ty::Const {
1553-
// ZST function type
1554-
val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
1555-
ty
1556-
})
1551+
value: ty::Const::zero_sized(tcx, ty),
15571552
},
15581553
})
15591554
}
@@ -1881,11 +1876,17 @@ impl<'tcx> Debug for Literal<'tcx> {
18811876
}
18821877

18831878
/// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
1884-
fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
1885-
use middle::const_val::ConstVal::*;
1879+
pub fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
1880+
use middle::const_val::ConstVal;
18861881
match const_val.val {
1887-
Unevaluated(..) => write!(fmt, "{:?}", const_val),
1888-
Value(val) => print_miri_value(val, const_val.ty, fmt),
1882+
ConstVal::Unevaluated(..) => write!(fmt, "{:?}", const_val),
1883+
ConstVal::Value(val) => {
1884+
if let Some(value) = val.to_byval_value() {
1885+
print_miri_value(value, const_val.ty, fmt)
1886+
} else {
1887+
write!(fmt, "{:?}:{}", val, const_val.ty)
1888+
}
1889+
},
18891890
}
18901891
}
18911892

src/librustc/mir/tcx.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
6969
PlaceTy::Ty {
7070
ty: match ty.sty {
7171
ty::TyArray(inner, size) => {
72-
let size = size.val.unwrap_u64();
72+
let size = size.unwrap_usize(tcx);
7373
let len = size - (from as u64) - (to as u64);
7474
tcx.mk_array(inner, len)
7575
}

src/librustc/ty/codec.rs

+19
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use std::hash::Hash;
2424
use std::intrinsics;
2525
use ty::{self, Ty, TyCtxt};
2626
use ty::subst::Substs;
27+
use mir::interpret::Allocation;
2728

2829
/// The shorthand encoding uses an enum's variant index `usize`
2930
/// and is offset by this value so it never matches a real variant.
@@ -262,6 +263,15 @@ pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
262263
Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
263264
}
264265

266+
#[inline]
267+
pub fn decode_allocation<'a, 'tcx, D>(decoder: &mut D)
268+
-> Result<&'tcx Allocation, D::Error>
269+
where D: TyDecoder<'a, 'tcx>,
270+
'tcx: 'a,
271+
{
272+
Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
273+
}
274+
265275
#[macro_export]
266276
macro_rules! __impl_decoder_methods {
267277
($($name:ident -> $ty:ty;)*) => {
@@ -393,6 +403,15 @@ macro_rules! implement_ty_decoder {
393403
decode_const(self)
394404
}
395405
}
406+
407+
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
408+
for $DecoderName<$($typaram),*> {
409+
fn specialized_decode(
410+
&mut self
411+
) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
412+
decode_allocation(self)
413+
}
414+
}
396415
}
397416
}
398417
}

0 commit comments

Comments
 (0)