Skip to content

Commit 7c966de

Browse files
committed
Setup ty::Const to allow ConstValue::Scalar to be backed by an allocation
1 parent f47ec2a commit 7c966de

File tree

14 files changed

+110
-94
lines changed

14 files changed

+110
-94
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,12 +300,13 @@ impl_stable_hash_for!(struct ty::FieldDef {
300300
});
301301

302302
impl_stable_hash_for!(
303-
impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValue ] {
303+
impl<'tcx> for enum mir::interpret::ConstValue [ mir::interpret::ConstValue ] {
304304
Scalar(val),
305305
Slice(a, b),
306-
ByRef(id, alloc, offset),
306+
ByRef,
307307
}
308308
);
309+
309310
impl_stable_hash_for!(struct crate::mir::interpret::RawConst<'tcx> {
310311
alloc_id,
311312
ty,
@@ -374,6 +375,7 @@ impl_stable_hash_for!(enum ::syntax::ast::Mutability {
374375

375376
impl_stable_hash_for!(struct ty::Const<'tcx> {
376377
ty,
378+
alloc,
377379
val
378380
});
379381

src/librustc/mir/interpret/value.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::fmt;
22

33
use crate::ty::{Ty, layout::{HasDataLayout, Size}};
44

5-
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
5+
use super::{EvalResult, Pointer, PointerArithmetic, AllocId, sign_extend, truncate};
66

77
/// Represents the result of a raw const operation, pre-validation.
88
#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
@@ -16,7 +16,7 @@ pub struct RawConst<'tcx> {
1616
/// Represents a constant value in Rust. `Scalar` and `ScalarPair` are optimizations that
1717
/// match the `LocalState` optimizations for easy conversions between `Value` and `ConstValue`.
1818
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
19-
pub enum ConstValue<'tcx> {
19+
pub enum ConstValue {
2020
/// Used only for types with `layout::abi::Scalar` ABI and ZSTs.
2121
///
2222
/// Not using the enum `Value` to encode that this must not be `Undef`.
@@ -31,19 +31,17 @@ pub enum ConstValue<'tcx> {
3131
/// it.
3232
Slice(Scalar, u64),
3333

34-
/// An allocation together with an offset into the allocation.
35-
/// Invariant: the `AllocId` matches the allocation.
36-
ByRef(AllocId, &'tcx Allocation, Size),
34+
ByRef,
3735
}
3836

3937
#[cfg(target_arch = "x86_64")]
40-
static_assert!(CONST_SIZE: ::std::mem::size_of::<ConstValue<'static>>() == 40);
38+
static_assert!(CONST_SIZE: ::std::mem::size_of::<ConstValue>() == 40);
4139

42-
impl<'tcx> ConstValue<'tcx> {
40+
impl ConstValue {
4341
#[inline]
4442
pub fn try_to_scalar(&self) -> Option<Scalar> {
4543
match *self {
46-
ConstValue::ByRef(..) |
44+
ConstValue::ByRef |
4745
ConstValue::Slice(..) => None,
4846
ConstValue::Scalar(val) => Some(val),
4947
}

src/librustc/mir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,6 +1665,7 @@ impl<'tcx> TerminatorKind<'tcx> {
16651665
}.into(),
16661666
),
16671667
ty: switch_ty,
1668+
alloc: None,
16681669
};
16691670
fmt_const_val(&mut s, c).unwrap();
16701671
s.into()

src/librustc/ty/structural_impls.rs

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
//! `BraceStructLiftImpl!`) to help with the tedium.
55
66
use crate::mir::ProjectionKind;
7-
use crate::mir::interpret::ConstValue;
87
use crate::ty::{self, Lift, Ty, TyCtxt};
98
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
109
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -486,23 +485,20 @@ BraceStructLiftImpl! {
486485
}
487486
}
488487

489-
BraceStructLiftImpl! {
490-
impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> {
491-
type Lifted = ty::Const<'tcx>;
492-
val, ty
493-
}
494-
}
495-
496-
impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
497-
type Lifted = ConstValue<'tcx>;
488+
impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> {
489+
type Lifted = ty::Const<'tcx>;
498490
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
499-
match *self {
500-
ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
501-
ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
502-
ConstValue::ByRef(x, alloc, z) => Some(ConstValue::ByRef(
503-
x, alloc.lift_to_tcx(tcx)?, z,
504-
)),
505-
}
491+
let ty = self.ty.lift_to_tcx(tcx)?;
492+
let alloc = match self.alloc {
493+
// can't use `and_then` or `map`, because the inner `lift_to_tcx` needs to early return
494+
Some((a, p)) => Some((a.lift_to_tcx(tcx)?, p)),
495+
None => None,
496+
};
497+
Some(ty::Const {
498+
val: self.val,
499+
ty,
500+
alloc,
501+
})
506502
}
507503
}
508504

@@ -1064,24 +1060,14 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
10641060
impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> {
10651061
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
10661062
let ty = self.ty.fold_with(folder);
1067-
let val = self.val.fold_with(folder);
10681063
ty::Const {
10691064
ty,
1070-
val
1065+
val: self.val,
1066+
alloc: self.alloc,
10711067
}
10721068
}
10731069

10741070
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
1075-
self.ty.visit_with(visitor) || self.val.visit_with(visitor)
1076-
}
1077-
}
1078-
1079-
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
1080-
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
1081-
*self
1082-
}
1083-
1084-
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
1085-
false
1071+
self.ty.visit_with(visitor)
10861072
}
10871073
}

src/librustc/ty/sty.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::ty::subst::{Substs, Subst, Kind, UnpackedKind};
1111
use crate::ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
1212
use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
1313
use crate::util::captures::Captures;
14-
use crate::mir::interpret::{Scalar, Pointer};
14+
use crate::mir::interpret::{Scalar, Pointer, Allocation};
1515

1616
use smallvec::SmallVec;
1717
use std::iter;
@@ -2065,7 +2065,7 @@ pub enum LazyConst<'tcx> {
20652065
}
20662066

20672067
#[cfg(target_arch = "x86_64")]
2068-
static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 56);
2068+
static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 80);
20692069

20702070
impl<'tcx> LazyConst<'tcx> {
20712071
pub fn map_evaluated<R>(self, f: impl FnOnce(Const<'tcx>) -> Option<R>) -> Option<R> {
@@ -2090,11 +2090,22 @@ impl<'tcx> LazyConst<'tcx> {
20902090
pub struct Const<'tcx> {
20912091
pub ty: Ty<'tcx>,
20922092

2093-
pub val: ConstValue<'tcx>,
2093+
/// This field is an optimization for caching commonly needed values of constants like `usize`
2094+
/// (or other integers for enum discriminants) and slices (e.g. from `b"foo"` and `"foo"`
2095+
/// literals)
2096+
pub val: ConstValue,
2097+
2098+
/// The actual backing storage of the constant and a pointer which can be resolved back to the
2099+
/// `allocation` field
2100+
///
2101+
/// Can be `None` for trivial constants created from literals or directly. Is always `Some` for
2102+
/// aggregate constants or any named constant that you can actually end up taking a reference
2103+
/// to. This will get unwrapped in situations where we do know that it's a referencable
2104+
pub alloc: Option<(&'tcx Allocation, Pointer)>,
20942105
}
20952106

20962107
#[cfg(target_arch = "x86_64")]
2097-
static_assert!(CONST_SIZE: ::std::mem::size_of::<Const<'static>>() == 48);
2108+
static_assert!(CONST_SIZE: ::std::mem::size_of::<Const<'static>>() == 72);
20982109

20992110
impl<'tcx> Const<'tcx> {
21002111
#[inline]
@@ -2105,6 +2116,7 @@ impl<'tcx> Const<'tcx> {
21052116
Self {
21062117
val: ConstValue::Scalar(val),
21072118
ty,
2119+
alloc: None,
21082120
}
21092121
}
21102122

src/librustc_codegen_llvm/consts.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,12 @@ pub fn codegen_static_initializer(
6969
};
7070
let param_env = ty::ParamEnv::reveal_all();
7171
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
72-
73-
let alloc = match static_.val {
74-
ConstValue::ByRef(_, alloc, n) if n.bytes() == 0 => alloc,
72+
let (alloc, ptr) = static_.alloc.unwrap();
73+
assert_eq!(ptr.offset.bytes(), 0);
74+
match static_.val {
75+
ConstValue::ByRef => {},
7576
_ => bug!("static const eval returned {:#?}", static_),
76-
};
77+
}
7778
Ok((const_alloc_to_llvm(cx, alloc), alloc))
7879
}
7980

src/librustc_codegen_ssa/mir/operand.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
101101
let b_llval = bx.cx().const_usize(b);
102102
OperandValue::Pair(a_llval, b_llval)
103103
},
104-
ConstValue::ByRef(_, alloc, offset) => {
105-
return Ok(bx.load_operand(bx.cx().from_const_alloc(layout, alloc, offset)));
104+
ConstValue::ByRef => {
105+
let (alloc, ptr) = val.alloc.unwrap();
106+
return Ok(bx.load_operand(bx.cx().from_const_alloc(layout, alloc, ptr.offset)));
106107
},
107108
};
108109

src/librustc_codegen_ssa/mir/place.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
417417
let layout = cx.layout_of(self.monomorphize(&ty));
418418
match bx.tcx().const_eval(param_env.and(cid)) {
419419
Ok(val) => match val.val {
420-
mir::interpret::ConstValue::ByRef(_, alloc, offset) => {
421-
bx.cx().from_const_alloc(layout, alloc, offset)
420+
mir::interpret::ConstValue::ByRef => {
421+
let (alloc, ptr) = val.alloc.unwrap();
422+
bx.cx().from_const_alloc(layout, alloc, ptr.offset)
422423
}
423424
_ => bug!("promoteds should have an allocation: {:?}", val),
424425
},

src/librustc_mir/const_eval.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub fn op_to_const<'tcx>(
8383
Operand::Immediate(val) => Ok(val)
8484
}
8585
};
86-
let val = match normalized_op {
86+
let (val, alloc) = match normalized_op {
8787
Err(MemPlace { ptr, align, meta }) => {
8888
// extract alloc-offset pair
8989
assert!(meta.is_none());
@@ -96,14 +96,14 @@ pub fn op_to_const<'tcx>(
9696
// FIXME shouldn't it be the case that `mark_static_initialized` has already
9797
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
9898
let alloc = ecx.tcx.intern_const_alloc(alloc);
99-
ConstValue::ByRef(ptr.alloc_id, alloc, ptr.offset)
99+
(ConstValue::ByRef, Some((alloc, ptr)))
100100
},
101101
Ok(Immediate::Scalar(x)) =>
102-
ConstValue::Scalar(x.not_undef()?),
102+
(ConstValue::Scalar(x.not_undef()?), None),
103103
Ok(Immediate::ScalarPair(a, b)) =>
104-
ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?),
104+
(ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?), None),
105105
};
106-
Ok(ty::Const { val, ty: op.layout.ty })
106+
Ok(ty::Const { val, ty: op.layout.ty, alloc })
107107
}
108108

109109
fn eval_body_and_ecx<'a, 'mir, 'tcx>(

src/librustc_mir/hair/constant.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
4242
let id = tcx.allocate_bytes(s.as_bytes());
4343
return Ok(ty::Const {
4444
val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64),
45+
alloc: None,
4546
ty: tcx.types.err,
4647
});
4748
},
@@ -72,14 +73,14 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
7273
LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
7374
LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
7475
};
75-
Ok(ty::Const { val: lit, ty })
76+
Ok(ty::Const { val: lit, ty, alloc: None })
7677
}
7778

7879
fn parse_float<'tcx>(
7980
num: Symbol,
8081
fty: ast::FloatTy,
8182
neg: bool,
82-
) -> Result<ConstValue<'tcx>, ()> {
83+
) -> Result<ConstValue, ()> {
8384
let num = num.as_str();
8485
use rustc_apfloat::ieee::{Single, Double};
8586
use rustc_apfloat::Float;

0 commit comments

Comments
 (0)