Skip to content

Commit 0aa92ac

Browse files
committed
Add a query to convert from ConstValue to Allocation
1 parent fdd9787 commit 0aa92ac

File tree

10 files changed

+110
-21
lines changed

10 files changed

+110
-21
lines changed

src/librustc/dep_graph/dep_node.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -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/ty/maps/config.rs

+6
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> {
137137
}
138138
}
139139

140+
impl<'tcx> QueryDescription<'tcx> for queries::const_value_to_allocation<'tcx> {
141+
fn describe(_tcx: TyCtxt, (val, ty): (ConstValue<'tcx>, Ty<'tcx>)) -> String {
142+
format!("converting value `{:?}` ({}) to an allocation", val, ty)
143+
}
144+
}
145+
140146
impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
141147
fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String {
142148
format!("erasing regions from `{:?}`", ty)

src/librustc/ty/maps/keys.rs

+9
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,15 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx>{
145145
}
146146
}
147147

148+
impl<'tcx> Key for (mir::interpret::ConstValue<'tcx>, Ty<'tcx>) {
149+
fn map_crate(&self) -> CrateNum {
150+
LOCAL_CRATE
151+
}
152+
fn default_span(&self, _: TyCtxt) -> Span {
153+
DUMMY_SP
154+
}
155+
}
156+
148157
impl<'tcx> Key for Ty<'tcx> {
149158
fn map_crate(&self) -> CrateNum {
150159
LOCAL_CRATE

src/librustc/ty/maps/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,11 @@ define_maps! { <'tcx>
228228
[] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
229229
-> EvalResult<'tcx>,
230230

231+
/// Converts a constant value to an constant allocation
232+
[] fn const_value_to_allocation: const_value_to_allocation(
233+
(ConstValue<'tcx>, Ty<'tcx>)
234+
) -> &'tcx Allocation,
235+
231236
[] fn check_match: CheckMatch(DefId)
232237
-> Result<(), ErrorReported>,
233238

@@ -478,6 +483,12 @@ fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
478483
DepConstructor::EraseRegionsTy { ty }
479484
}
480485

486+
fn const_value_to_allocation<'tcx>(
487+
(val, ty): (ConstValue<'tcx>, Ty<'tcx>)
488+
) -> DepConstructor<'tcx> {
489+
DepConstructor::ConstValueToAllocation { val, ty }
490+
}
491+
481492
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
482493
DepConstructor::TypeParamPredicates {
483494
item_id,

src/librustc/ty/maps/plumbing.rs

+1
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
956956
DepKind::FulfillObligation |
957957
DepKind::VtableMethods |
958958
DepKind::EraseRegionsTy |
959+
DepKind::ConstValueToAllocation |
959960
DepKind::NormalizeProjectionTy |
960961
DepKind::NormalizeTyAfterErasingRegions |
961962
DepKind::DropckOutlives |

src/librustc_mir/interpret/const_eval.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ use rustc::ty::subst::Subst;
88

99
use syntax::ast::Mutability;
1010
use syntax::codemap::Span;
11+
use syntax::codemap::DUMMY_SP;
1112

1213
use rustc::mir::interpret::{
1314
EvalResult, EvalError, EvalErrorKind, GlobalId,
1415
Value, Pointer, PrimVal, AllocId, Allocation, ConstValue,
1516
};
16-
use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory};
17+
use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory, MemoryKind};
1718

1819
use std::fmt;
1920
use std::error::Error;
@@ -470,7 +471,6 @@ pub fn const_variant_index<'a, 'tcx>(
470471
let (ptr, align) = match value {
471472
Value::ByValPair(..) | Value::ByVal(_) => {
472473
let layout = ecx.layout_of(ty)?;
473-
use super::MemoryKind;
474474
let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
475475
let ptr: Pointer = ptr.into();
476476
ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
@@ -482,6 +482,30 @@ pub fn const_variant_index<'a, 'tcx>(
482482
ecx.read_discriminant_as_variant_index(place, ty)
483483
}
484484

485+
pub fn const_value_to_allocation_provider<'a, 'tcx>(
486+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
487+
(val, ty): (ConstValue<'tcx>, Ty<'tcx>),
488+
) -> &'tcx Allocation {
489+
match val {
490+
ConstValue::ByRef(alloc) => return alloc,
491+
_ => ()
492+
}
493+
let result = || -> EvalResult<'tcx, &'tcx Allocation> {
494+
let mut ecx = EvalContext::new(
495+
tcx.at(DUMMY_SP),
496+
ty::ParamEnv::reveal_all(),
497+
CompileTimeEvaluator,
498+
());
499+
let value = ecx.const_value_to_value(val, ty)?;
500+
let layout = ecx.layout_of(ty)?;
501+
let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
502+
ecx.write_value_to_ptr(value, ptr.into(), layout.align, ty)?;
503+
let alloc = ecx.memory.get(ptr.alloc_id)?;
504+
Ok(tcx.intern_const_alloc(alloc.clone()))
505+
};
506+
result().expect("unable to convert ConstVal to Allocation")
507+
}
508+
485509
pub fn const_eval_provider<'a, 'tcx>(
486510
tcx: TyCtxt<'a, 'tcx, 'tcx>,
487511
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,

src/librustc_mir/interpret/memory.rs

+42-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
use std::collections::{btree_map, VecDeque};
22
use std::ptr;
33

4+
use rustc::hir::def_id::DefId;
45
use rustc::ty::Instance;
6+
use rustc::ty::ParamEnv;
57
use rustc::ty::maps::TyCtxtAt;
68
use rustc::ty::layout::{self, Align, TargetDataLayout};
79
use syntax::ast::Mutability;
10+
use rustc::middle::const_val::{ConstVal, ErrKind};
811

912
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
1013
use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, Value, Pointer,
11-
EvalResult, PrimVal, EvalErrorKind};
14+
EvalResult, PrimVal, EvalErrorKind, GlobalId};
1215
pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint};
1316

1417
use super::{EvalContext, Machine};
@@ -274,6 +277,31 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
274277

275278
/// Allocation accessors
276279
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
280+
fn const_eval_static(&self, def_id: DefId) -> EvalResult<'tcx, &'tcx Allocation> {
281+
let instance = Instance::mono(self.tcx.tcx, def_id);
282+
let gid = GlobalId {
283+
instance,
284+
promoted: None,
285+
};
286+
self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
287+
match *err.kind {
288+
ErrKind::Miri(ref err, _) => match err.kind {
289+
EvalErrorKind::TypeckError |
290+
EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
291+
_ => EvalErrorKind::ReferencedConstant.into(),
292+
},
293+
ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
294+
ref other => bug!("const eval returned {:?}", other),
295+
}
296+
}).map(|val| {
297+
let const_val = match val.val {
298+
ConstVal::Value(val) => val,
299+
ConstVal::Unevaluated(..) => bug!("should be evaluated"),
300+
};
301+
self.tcx.const_value_to_allocation((const_val, val.ty))
302+
})
303+
}
304+
277305
pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
278306
// normal alloc?
279307
match self.alloc_map.get(&id) {
@@ -283,13 +311,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
283311
Some(alloc) => Ok(alloc),
284312
None => {
285313
// static alloc?
286-
self.tcx.interpret_interner.get_alloc(id)
287-
// no alloc? produce an error
288-
.ok_or_else(|| if self.tcx.interpret_interner.get_fn(id).is_some() {
289-
EvalErrorKind::DerefFunctionPointer.into()
290-
} else {
291-
EvalErrorKind::DanglingPointerDeref.into()
292-
})
314+
if let Some(a) = self.tcx.interpret_interner.get_alloc(id) {
315+
return Ok(a);
316+
}
317+
// static variable?
318+
if let Some(did) = self.tcx.interpret_interner.get_static(id) {
319+
return self.const_eval_static(did);
320+
}
321+
// otherwise return an error
322+
Err(if self.tcx.interpret_interner.get_fn(id).is_some() {
323+
EvalErrorKind::DerefFunctionPointer.into()
324+
} else {
325+
EvalErrorKind::DanglingPointerDeref.into()
326+
})
293327
},
294328
},
295329
}

src/librustc_mir/interpret/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub use self::const_eval::{
2323
mk_borrowck_eval_cx,
2424
eval_body,
2525
CompileTimeEvaluator,
26+
const_value_to_allocation_provider,
2627
const_eval_provider,
2728
const_val_field,
2829
const_variant_index,

src/librustc_mir/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pub fn provide(providers: &mut Providers) {
8585
shim::provide(providers);
8686
transform::provide(providers);
8787
providers.const_eval = interpret::const_eval_provider;
88+
providers.const_value_to_allocation = interpret::const_value_to_allocation_provider;
8889
providers.check_match = hair::pattern::check_match;
8990
}
9091

src/librustc_trans/base.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,7 @@ mod temp_stable_hash_impls {
13731373

13741374
fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
13751375
use rustc::mir::interpret::GlobalId;
1376+
use rustc::middle::const_val::ConstVal;
13761377

13771378
info!("loading wasm section {:?}", id);
13781379

@@ -1391,11 +1392,11 @@ fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
13911392
let param_env = ty::ParamEnv::reveal_all();
13921393
let val = tcx.const_eval(param_env.and(cid)).unwrap();
13931394

1394-
let mem = val.to_ptr().expect("should be pointer");
1395-
assert_eq!(mem.offset, 0);
1396-
let alloc = tcx
1397-
.interpret_interner
1398-
.get_alloc(mem.alloc_id)
1399-
.expect("miri allocation never successfully created");
1395+
let const_val = match val.val {
1396+
ConstVal::Value(val) => val,
1397+
ConstVal::Unevaluated(..) => bug!("should be evaluated"),
1398+
};
1399+
1400+
let alloc = tcx.const_value_to_allocation((const_val, val.ty));
14001401
(section.to_string(), alloc.bytes.clone())
14011402
}

0 commit comments

Comments
 (0)