Skip to content

Commit 6630678

Browse files
committed
Go through an allocation when accessing fields of constants
1 parent 76ddede commit 6630678

File tree

9 files changed

+87
-38
lines changed

9 files changed

+87
-38
lines changed

src/librustc/ich/impls_ty.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,9 @@ for ::mir::interpret::ConstValue<'gcx> {
401401
a.hash_stable(hcx, hasher);
402402
b.hash_stable(hcx, hasher);
403403
}
404-
ByRef(alloc) => {
404+
ByRef(alloc, offset) => {
405405
alloc.hash_stable(hcx, hasher);
406+
offset.hash_stable(hcx, hasher);
406407
}
407408
}
408409
}

src/librustc/mir/interpret/value.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ use super::{EvalResult, MemoryPointer, PointerArithmetic, Allocation};
99
/// matches Value's optimizations for easy conversions between these two types
1010
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
1111
pub enum ConstValue<'tcx> {
12-
// Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
12+
/// Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
1313
ByVal(PrimVal),
14-
// Used only for types with layout::abi::ScalarPair
14+
/// Used only for types with layout::abi::ScalarPair
1515
ByValPair(PrimVal, PrimVal),
16-
// Used only for the remaining cases
17-
ByRef(&'tcx Allocation),
16+
/// Used only for the remaining cases. An allocation + offset into the allocation
17+
ByRef(&'tcx Allocation, u64),
1818
}
1919

2020
impl<'tcx> ConstValue<'tcx> {

src/librustc/ty/sty.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use ty::subst::{Substs, Subst, Kind, UnpackedKind};
1919
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
2020
use ty::{Slice, TyS};
2121
use util::captures::Captures;
22-
use mir::interpret::{Allocation, PrimVal, MemoryPointer, Value, ConstValue};
22+
use mir::interpret::{PrimVal, MemoryPointer, Value, ConstValue};
2323

2424
use std::iter;
2525
use std::cmp::Ordering;
@@ -1767,15 +1767,6 @@ impl<'tcx> Const<'tcx> {
17671767
Self::from_const_val(tcx, ConstVal::Value(val), ty)
17681768
}
17691769

1770-
#[inline]
1771-
pub fn from_alloc(
1772-
tcx: TyCtxt<'_, '_, 'tcx>,
1773-
alloc: &'tcx Allocation,
1774-
ty: Ty<'tcx>,
1775-
) -> &'tcx Self {
1776-
Self::from_const_value(tcx, ConstValue::ByRef(alloc), ty)
1777-
}
1778-
17791770
#[inline]
17801771
pub fn from_byval_value(
17811772
tcx: TyCtxt<'_, '_, 'tcx>,

src/librustc_codegen_llvm/mir/constant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ pub fn codegen_static_initializer<'a, 'tcx>(
129129
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
130130

131131
let alloc = match static_.val {
132-
ConstVal::Value(ConstValue::ByRef(alloc)) => alloc,
132+
ConstVal::Value(ConstValue::ByRef(alloc, 0)) => alloc,
133133
_ => bug!("static const eval returned {:#?}", static_),
134134
};
135135
Ok(const_alloc_to_llvm(cx, alloc))

src/librustc_codegen_llvm/mir/operand.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use llvm::ValueRef;
11+
use llvm::{ValueRef, LLVMConstInBoundsGEP};
1212
use rustc::middle::const_val::ConstEvalErr;
1313
use rustc::mir;
1414
use rustc::mir::interpret::ConstValue;
@@ -137,9 +137,15 @@ impl<'a, 'tcx> OperandRef<'tcx> {
137137
);
138138
OperandValue::Pair(a_llval, b_llval)
139139
},
140-
ConstValue::ByRef(alloc) => {
140+
ConstValue::ByRef(alloc, offset) => {
141141
let init = const_alloc_to_llvm(bx.cx, alloc);
142-
let llval = consts::addr_of(bx.cx, init, layout.align, "byte_str");
142+
let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str");
143+
144+
let llval = unsafe { LLVMConstInBoundsGEP(
145+
consts::bitcast(base_addr, Type::i8p(bx.cx)),
146+
&C_usize(bx.cx, offset),
147+
1,
148+
)};
143149
let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to());
144150
return Ok(PlaceRef::new_sized(llval, layout, alloc.align).load(bx));
145151
},

src/librustc_mir/interpret/const_eval.rs

+20-16
Original file line numberDiff line numberDiff line change
@@ -422,22 +422,23 @@ pub fn const_val_field<'a, 'tcx>(
422422
let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
423423
let result = (|| {
424424
let value = ecx.const_value_to_value(value, ty)?;
425-
let (field, ty) = match value {
426-
Value::ByValPair(..) | Value::ByVal(_) =>
427-
ecx.read_field(value, variant, field, ty)?.expect("const_val_field on non-field"),
428-
Value::ByRef(ptr, align) => {
429-
let place = Place::Ptr {
430-
ptr,
431-
align,
432-
extra: variant.map_or(PlaceExtra::None, PlaceExtra::DowncastVariant),
433-
};
434-
let layout = ecx.layout_of(ty)?;
435-
let (place, layout) = ecx.place_field(place, field, layout)?;
436-
let (ptr, align) = place.to_ptr_align();
437-
(Value::ByRef(ptr, align), layout.ty)
438-
}
425+
let layout = ecx.layout_of(ty)?;
426+
let (ptr, align) = match value {
427+
Value::ByRef(ptr, align) => (ptr, align),
428+
Value::ByValPair(..) | Value::ByVal(_) => {
429+
let ptr = ecx.alloc_ptr(ty)?.into();
430+
ecx.write_value_to_ptr(value, ptr, ty)?;
431+
(ptr, layout.align)
432+
},
439433
};
440-
Ok(value_to_const_value(&ecx, field, ty))
434+
let place = Place::Ptr {
435+
ptr,
436+
align,
437+
extra: variant.map_or(PlaceExtra::None, PlaceExtra::DowncastVariant),
438+
};
439+
let (place, layout) = ecx.place_field(place, field, layout)?;
440+
let (ptr, align) = place.to_ptr_align();
441+
Ok((Value::ByRef(ptr, align), layout.ty))
441442
})();
442443
result.map_err(|err| {
443444
let (trace, span) = ecx.generate_stacktrace(None);
@@ -478,7 +479,10 @@ pub fn const_value_to_allocation_provider<'a, 'tcx>(
478479
(val, ty): (ConstValue<'tcx>, Ty<'tcx>),
479480
) -> &'tcx Allocation {
480481
match val {
481-
ConstValue::ByRef(alloc) => return alloc,
482+
ConstValue::ByRef(alloc, offset) => {
483+
assert_eq!(offset, 0);
484+
return alloc;
485+
},
482486
_ => ()
483487
}
484488
let result = || -> EvalResult<'tcx, &'tcx Allocation> {

src/librustc_mir/interpret/eval_context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
243243
_ty: Ty<'tcx>,
244244
) -> EvalResult<'tcx, Value> {
245245
match val {
246-
ConstValue::ByRef(alloc) => {
246+
ConstValue::ByRef(alloc, offset) => {
247247
// FIXME: Allocate new AllocId for all constants inside
248248
let id = self.memory.allocate_value(alloc.clone(), Some(MemoryKind::Stack))?;
249-
Ok(Value::ByRef(MemoryPointer::new(id, 0).into(), alloc.align))
249+
Ok(Value::ByRef(MemoryPointer::new(id, offset).into(), alloc.align))
250250
},
251251
ConstValue::ByValPair(a, b) => Ok(Value::ByValPair(a, b)),
252252
ConstValue::ByVal(val) => Ok(Value::ByVal(val)),

src/librustc_mir/monomorphize/collector.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,7 @@ fn collect_const<'a, 'tcx>(
12491249
ConstVal::Value(ConstValue::ByValPair(PrimVal::Ptr(ptr), _)) |
12501250
ConstVal::Value(ConstValue::ByVal(PrimVal::Ptr(ptr))) =>
12511251
collect_miri(tcx, ptr.alloc_id, output),
1252-
ConstVal::Value(ConstValue::ByRef(alloc)) => {
1252+
ConstVal::Value(ConstValue::ByRef(alloc, _offset)) => {
12531253
for &id in alloc.relocations.values() {
12541254
collect_miri(tcx, id, output);
12551255
}

src/test/ui/const-eval/issue-50706.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-pass
12+
13+
pub struct Stats;
14+
15+
#[derive(PartialEq, Eq)]
16+
pub struct StatVariant {
17+
pub id: u8,
18+
_priv: (),
19+
}
20+
21+
#[derive(PartialEq, Eq)]
22+
pub struct Stat {
23+
pub variant: StatVariant,
24+
pub index: usize,
25+
_priv: (),
26+
}
27+
28+
impl Stats {
29+
pub const TEST: StatVariant = StatVariant{id: 0, _priv: (),};
30+
#[allow(non_upper_case_globals)]
31+
pub const A: Stat = Stat{
32+
variant: Self::TEST,
33+
index: 0,
34+
_priv: (),};
35+
}
36+
37+
impl Stat {
38+
pub fn from_index(variant: StatVariant, index: usize) -> Option<Stat> {
39+
let stat = Stat{variant, index, _priv: (),};
40+
match stat {
41+
Stats::A => Some(Stats::A),
42+
_ => None,
43+
}
44+
}
45+
}
46+
47+
fn main() {}

0 commit comments

Comments
 (0)