Add a query to convert from ConstValue to Allocation
This commit is contained in:
parent
fdd9787777
commit
0aa92acda7
10 changed files with 110 additions and 21 deletions
|
@ -621,13 +621,14 @@ define_dep_nodes!( <'tcx>
|
||||||
[input] UsedCrateSource(CrateNum),
|
[input] UsedCrateSource(CrateNum),
|
||||||
[input] PostorderCnums,
|
[input] PostorderCnums,
|
||||||
|
|
||||||
// This query is not expected to have inputs -- as a result, it's
|
// These queries are not expected to have inputs -- as a result, they
|
||||||
// not a good candidate for "replay" because it's essentially a
|
// are not good candidates for "replay" because they are essentially
|
||||||
// pure function of its input (and hence the expectation is that
|
// pure functions of their input (and hence the expectation is that
|
||||||
// no caller would be green **apart** from just this
|
// no caller would be green **apart** from just these
|
||||||
// query). Making it anonymous avoids hashing the result, which
|
// queries). Making them anonymous avoids hashing the result, which
|
||||||
// may save a bit of time.
|
// may save a bit of time.
|
||||||
[anon] EraseRegionsTy { ty: Ty<'tcx> },
|
[anon] EraseRegionsTy { ty: Ty<'tcx> },
|
||||||
|
[anon] ConstValueToAllocation { val: ConstValue<'tcx>, ty: Ty<'tcx> },
|
||||||
|
|
||||||
[input] Freevars(DefId),
|
[input] Freevars(DefId),
|
||||||
[input] MaybeUnusedTraitImport(DefId),
|
[input] MaybeUnusedTraitImport(DefId),
|
||||||
|
|
|
@ -137,6 +137,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> QueryDescription<'tcx> for queries::const_value_to_allocation<'tcx> {
|
||||||
|
fn describe(_tcx: TyCtxt, (val, ty): (ConstValue<'tcx>, Ty<'tcx>)) -> String {
|
||||||
|
format!("converting value `{:?}` ({}) to an allocation", val, ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
|
impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
|
||||||
fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String {
|
fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String {
|
||||||
format!("erasing regions from `{:?}`", ty)
|
format!("erasing regions from `{:?}`", ty)
|
||||||
|
|
|
@ -145,6 +145,15 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx>{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Key for (mir::interpret::ConstValue<'tcx>, Ty<'tcx>) {
|
||||||
|
fn map_crate(&self) -> CrateNum {
|
||||||
|
LOCAL_CRATE
|
||||||
|
}
|
||||||
|
fn default_span(&self, _: TyCtxt) -> Span {
|
||||||
|
DUMMY_SP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Key for Ty<'tcx> {
|
impl<'tcx> Key for Ty<'tcx> {
|
||||||
fn map_crate(&self) -> CrateNum {
|
fn map_crate(&self) -> CrateNum {
|
||||||
LOCAL_CRATE
|
LOCAL_CRATE
|
||||||
|
|
|
@ -228,6 +228,11 @@ define_maps! { <'tcx>
|
||||||
[] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
[] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||||
-> EvalResult<'tcx>,
|
-> EvalResult<'tcx>,
|
||||||
|
|
||||||
|
/// Converts a constant value to an constant allocation
|
||||||
|
[] fn const_value_to_allocation: const_value_to_allocation(
|
||||||
|
(ConstValue<'tcx>, Ty<'tcx>)
|
||||||
|
) -> &'tcx Allocation,
|
||||||
|
|
||||||
[] fn check_match: CheckMatch(DefId)
|
[] fn check_match: CheckMatch(DefId)
|
||||||
-> Result<(), ErrorReported>,
|
-> Result<(), ErrorReported>,
|
||||||
|
|
||||||
|
@ -478,6 +483,12 @@ fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
|
||||||
DepConstructor::EraseRegionsTy { ty }
|
DepConstructor::EraseRegionsTy { ty }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn const_value_to_allocation<'tcx>(
|
||||||
|
(val, ty): (ConstValue<'tcx>, Ty<'tcx>)
|
||||||
|
) -> DepConstructor<'tcx> {
|
||||||
|
DepConstructor::ConstValueToAllocation { val, ty }
|
||||||
|
}
|
||||||
|
|
||||||
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
|
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
|
||||||
DepConstructor::TypeParamPredicates {
|
DepConstructor::TypeParamPredicates {
|
||||||
item_id,
|
item_id,
|
||||||
|
|
|
@ -956,6 +956,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||||
DepKind::FulfillObligation |
|
DepKind::FulfillObligation |
|
||||||
DepKind::VtableMethods |
|
DepKind::VtableMethods |
|
||||||
DepKind::EraseRegionsTy |
|
DepKind::EraseRegionsTy |
|
||||||
|
DepKind::ConstValueToAllocation |
|
||||||
DepKind::NormalizeProjectionTy |
|
DepKind::NormalizeProjectionTy |
|
||||||
DepKind::NormalizeTyAfterErasingRegions |
|
DepKind::NormalizeTyAfterErasingRegions |
|
||||||
DepKind::DropckOutlives |
|
DepKind::DropckOutlives |
|
||||||
|
|
|
@ -8,12 +8,13 @@ use rustc::ty::subst::Subst;
|
||||||
|
|
||||||
use syntax::ast::Mutability;
|
use syntax::ast::Mutability;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
|
use syntax::codemap::DUMMY_SP;
|
||||||
|
|
||||||
use rustc::mir::interpret::{
|
use rustc::mir::interpret::{
|
||||||
EvalResult, EvalError, EvalErrorKind, GlobalId,
|
EvalResult, EvalError, EvalErrorKind, GlobalId,
|
||||||
Value, Pointer, PrimVal, AllocId, Allocation, ConstValue,
|
Value, Pointer, PrimVal, AllocId, Allocation, ConstValue,
|
||||||
};
|
};
|
||||||
use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory};
|
use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory, MemoryKind};
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
@ -470,7 +471,6 @@ pub fn const_variant_index<'a, 'tcx>(
|
||||||
let (ptr, align) = match value {
|
let (ptr, align) = match value {
|
||||||
Value::ByValPair(..) | Value::ByVal(_) => {
|
Value::ByValPair(..) | Value::ByVal(_) => {
|
||||||
let layout = ecx.layout_of(ty)?;
|
let layout = ecx.layout_of(ty)?;
|
||||||
use super::MemoryKind;
|
|
||||||
let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
|
let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
|
||||||
let ptr: Pointer = ptr.into();
|
let ptr: Pointer = ptr.into();
|
||||||
ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
|
ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
|
||||||
|
@ -482,6 +482,30 @@ pub fn const_variant_index<'a, 'tcx>(
|
||||||
ecx.read_discriminant_as_variant_index(place, ty)
|
ecx.read_discriminant_as_variant_index(place, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn const_value_to_allocation_provider<'a, 'tcx>(
|
||||||
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
(val, ty): (ConstValue<'tcx>, Ty<'tcx>),
|
||||||
|
) -> &'tcx Allocation {
|
||||||
|
match val {
|
||||||
|
ConstValue::ByRef(alloc) => return alloc,
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
let result = || -> EvalResult<'tcx, &'tcx Allocation> {
|
||||||
|
let mut ecx = EvalContext::new(
|
||||||
|
tcx.at(DUMMY_SP),
|
||||||
|
ty::ParamEnv::reveal_all(),
|
||||||
|
CompileTimeEvaluator,
|
||||||
|
());
|
||||||
|
let value = ecx.const_value_to_value(val, ty)?;
|
||||||
|
let layout = ecx.layout_of(ty)?;
|
||||||
|
let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
|
||||||
|
ecx.write_value_to_ptr(value, ptr.into(), layout.align, ty)?;
|
||||||
|
let alloc = ecx.memory.get(ptr.alloc_id)?;
|
||||||
|
Ok(tcx.intern_const_alloc(alloc.clone()))
|
||||||
|
};
|
||||||
|
result().expect("unable to convert ConstVal to Allocation")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn const_eval_provider<'a, 'tcx>(
|
pub fn const_eval_provider<'a, 'tcx>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
use std::collections::{btree_map, VecDeque};
|
use std::collections::{btree_map, VecDeque};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::ty::Instance;
|
use rustc::ty::Instance;
|
||||||
|
use rustc::ty::ParamEnv;
|
||||||
use rustc::ty::maps::TyCtxtAt;
|
use rustc::ty::maps::TyCtxtAt;
|
||||||
use rustc::ty::layout::{self, Align, TargetDataLayout};
|
use rustc::ty::layout::{self, Align, TargetDataLayout};
|
||||||
use syntax::ast::Mutability;
|
use syntax::ast::Mutability;
|
||||||
|
use rustc::middle::const_val::{ConstVal, ErrKind};
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
||||||
use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, Value, Pointer,
|
use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, Value, Pointer,
|
||||||
EvalResult, PrimVal, EvalErrorKind};
|
EvalResult, PrimVal, EvalErrorKind, GlobalId};
|
||||||
pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint};
|
pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint};
|
||||||
|
|
||||||
use super::{EvalContext, Machine};
|
use super::{EvalContext, Machine};
|
||||||
|
@ -274,6 +277,31 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||||
|
|
||||||
/// Allocation accessors
|
/// Allocation accessors
|
||||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||||
|
fn const_eval_static(&self, def_id: DefId) -> EvalResult<'tcx, &'tcx Allocation> {
|
||||||
|
let instance = Instance::mono(self.tcx.tcx, def_id);
|
||||||
|
let gid = GlobalId {
|
||||||
|
instance,
|
||||||
|
promoted: None,
|
||||||
|
};
|
||||||
|
self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
|
||||||
|
match *err.kind {
|
||||||
|
ErrKind::Miri(ref err, _) => match err.kind {
|
||||||
|
EvalErrorKind::TypeckError |
|
||||||
|
EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
|
||||||
|
_ => EvalErrorKind::ReferencedConstant.into(),
|
||||||
|
},
|
||||||
|
ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
|
||||||
|
ref other => bug!("const eval returned {:?}", other),
|
||||||
|
}
|
||||||
|
}).map(|val| {
|
||||||
|
let const_val = match val.val {
|
||||||
|
ConstVal::Value(val) => val,
|
||||||
|
ConstVal::Unevaluated(..) => bug!("should be evaluated"),
|
||||||
|
};
|
||||||
|
self.tcx.const_value_to_allocation((const_val, val.ty))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
|
pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
|
||||||
// normal alloc?
|
// normal alloc?
|
||||||
match self.alloc_map.get(&id) {
|
match self.alloc_map.get(&id) {
|
||||||
|
@ -283,13 +311,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||||
Some(alloc) => Ok(alloc),
|
Some(alloc) => Ok(alloc),
|
||||||
None => {
|
None => {
|
||||||
// static alloc?
|
// static alloc?
|
||||||
self.tcx.interpret_interner.get_alloc(id)
|
if let Some(a) = self.tcx.interpret_interner.get_alloc(id) {
|
||||||
// no alloc? produce an error
|
return Ok(a);
|
||||||
.ok_or_else(|| if self.tcx.interpret_interner.get_fn(id).is_some() {
|
}
|
||||||
EvalErrorKind::DerefFunctionPointer.into()
|
// static variable?
|
||||||
} else {
|
if let Some(did) = self.tcx.interpret_interner.get_static(id) {
|
||||||
EvalErrorKind::DanglingPointerDeref.into()
|
return self.const_eval_static(did);
|
||||||
})
|
}
|
||||||
|
// otherwise return an error
|
||||||
|
Err(if self.tcx.interpret_interner.get_fn(id).is_some() {
|
||||||
|
EvalErrorKind::DerefFunctionPointer.into()
|
||||||
|
} else {
|
||||||
|
EvalErrorKind::DanglingPointerDeref.into()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ pub use self::const_eval::{
|
||||||
mk_borrowck_eval_cx,
|
mk_borrowck_eval_cx,
|
||||||
eval_body,
|
eval_body,
|
||||||
CompileTimeEvaluator,
|
CompileTimeEvaluator,
|
||||||
|
const_value_to_allocation_provider,
|
||||||
const_eval_provider,
|
const_eval_provider,
|
||||||
const_val_field,
|
const_val_field,
|
||||||
const_variant_index,
|
const_variant_index,
|
||||||
|
|
|
@ -85,6 +85,7 @@ pub fn provide(providers: &mut Providers) {
|
||||||
shim::provide(providers);
|
shim::provide(providers);
|
||||||
transform::provide(providers);
|
transform::provide(providers);
|
||||||
providers.const_eval = interpret::const_eval_provider;
|
providers.const_eval = interpret::const_eval_provider;
|
||||||
|
providers.const_value_to_allocation = interpret::const_value_to_allocation_provider;
|
||||||
providers.check_match = hair::pattern::check_match;
|
providers.check_match = hair::pattern::check_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1373,6 +1373,7 @@ mod temp_stable_hash_impls {
|
||||||
|
|
||||||
fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
|
fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
|
||||||
use rustc::mir::interpret::GlobalId;
|
use rustc::mir::interpret::GlobalId;
|
||||||
|
use rustc::middle::const_val::ConstVal;
|
||||||
|
|
||||||
info!("loading wasm section {:?}", id);
|
info!("loading wasm section {:?}", id);
|
||||||
|
|
||||||
|
@ -1391,11 +1392,11 @@ fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let val = tcx.const_eval(param_env.and(cid)).unwrap();
|
let val = tcx.const_eval(param_env.and(cid)).unwrap();
|
||||||
|
|
||||||
let mem = val.to_ptr().expect("should be pointer");
|
let const_val = match val.val {
|
||||||
assert_eq!(mem.offset, 0);
|
ConstVal::Value(val) => val,
|
||||||
let alloc = tcx
|
ConstVal::Unevaluated(..) => bug!("should be evaluated"),
|
||||||
.interpret_interner
|
};
|
||||||
.get_alloc(mem.alloc_id)
|
|
||||||
.expect("miri allocation never successfully created");
|
let alloc = tcx.const_value_to_allocation((const_val, val.ty));
|
||||||
(section.to_string(), alloc.bytes.clone())
|
(section.to_string(), alloc.bytes.clone())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue