Merge pull request #243 from solson/magic_numbers
Get rid of magic numbers
This commit is contained in:
commit
555fc41d5e
3 changed files with 88 additions and 18 deletions
|
|
@ -1,22 +1,20 @@
|
|||
use rustc::hir::def_id::DefId;
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::{self, TyCtxt, Ty, Instance};
|
||||
|
||||
use error::{EvalError, EvalResult};
|
||||
use lvalue::{Global, GlobalId, Lvalue};
|
||||
use value::PrimVal;
|
||||
use rustc_const_math::ConstInt;
|
||||
use eval_context::{EvalContext, StackPopCleanup};
|
||||
|
||||
pub fn eval_body_as_integer<'a, 'tcx>(
|
||||
pub fn eval_body_as_primval<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
(def_id, substs): (DefId, &'tcx Substs<'tcx>),
|
||||
) -> EvalResult<'tcx, ConstInt> {
|
||||
instance: Instance<'tcx>,
|
||||
) -> EvalResult<'tcx, (PrimVal, Ty<'tcx>)> {
|
||||
let limits = ::ResourceLimits::default();
|
||||
let mut ecx = EvalContext::new(tcx, limits);
|
||||
let instance = ecx.resolve_associated_const(def_id, substs);
|
||||
let cid = GlobalId { instance, promoted: None };
|
||||
if ecx.tcx.has_attr(def_id, "linkage") {
|
||||
if ecx.tcx.has_attr(instance.def_id(), "linkage") {
|
||||
return Err(EvalError::NotConst("extern global".to_string()));
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +26,7 @@ pub fn eval_body_as_integer<'a, 'tcx>(
|
|||
ty::ParamEnv::empty(Reveal::All),
|
||||
mir.span);
|
||||
let cleanup = StackPopCleanup::MarkStatic(mutable);
|
||||
let name = ty::tls::with(|tcx| tcx.item_path_str(def_id));
|
||||
let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
|
||||
trace!("pushing stack frame for global: {}", name);
|
||||
ecx.push_stack_frame(
|
||||
instance,
|
||||
|
|
@ -41,11 +39,19 @@ pub fn eval_body_as_integer<'a, 'tcx>(
|
|||
while ecx.step()? {}
|
||||
}
|
||||
let value = ecx.globals.get(&cid).expect("global not cached").value;
|
||||
let prim = ecx.value_to_primval(value, mir.return_ty)?.to_bytes()?;
|
||||
Ok((ecx.value_to_primval(value, mir.return_ty)?, mir.return_ty))
|
||||
}
|
||||
|
||||
pub fn eval_body_as_integer<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
) -> EvalResult<'tcx, ConstInt> {
|
||||
let (prim, ty) = eval_body_as_primval(tcx, instance)?;
|
||||
let prim = prim.to_bytes()?;
|
||||
use syntax::ast::{IntTy, UintTy};
|
||||
use rustc::ty::TypeVariants::*;
|
||||
use rustc_const_math::{ConstIsize, ConstUsize};
|
||||
Ok(match mir.return_ty.sty {
|
||||
Ok(match ty.sty {
|
||||
TyInt(IntTy::I8) => ConstInt::I8(prim as i128 as i8),
|
||||
TyInt(IntTy::I16) => ConstInt::I16(prim as i128 as i16),
|
||||
TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ pub enum EvalError<'tcx> {
|
|||
NeedsRfc(String),
|
||||
NotConst(String),
|
||||
ReadFromReturnPointer,
|
||||
PathNotFound(Vec<String>),
|
||||
}
|
||||
|
||||
pub type EvalResult<'tcx, T = ()> = Result<T, EvalError<'tcx>>;
|
||||
|
|
@ -175,6 +176,8 @@ impl<'tcx> Error for EvalError<'tcx> {
|
|||
"this feature is not compatible with constant evaluation",
|
||||
ReadFromReturnPointer =>
|
||||
"tried to read from the return pointer",
|
||||
EvalError::PathNotFound(_) =>
|
||||
"a path could not be resolved, maybe the crate is not loaded",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -215,6 +218,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
|
|||
write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg),
|
||||
NotConst(ref msg) =>
|
||||
write!(f, "Cannot evaluate within constants: \"{}\"", msg),
|
||||
EvalError::PathNotFound(ref path) =>
|
||||
write!(f, "Cannot find path {:?}", path),
|
||||
_ => write!(f, "{}", self.description()),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
use rustc::mir;
|
||||
use rustc::ty::{self, TypeVariants, Ty};
|
||||
use rustc::ty::layout::Layout;
|
||||
|
|
@ -13,6 +13,8 @@ use memory::{MemoryPointer, TlsKey};
|
|||
use value::{PrimVal, Value};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
||||
use std::mem;
|
||||
|
||||
mod drop;
|
||||
mod intrinsic;
|
||||
|
||||
|
|
@ -853,12 +855,32 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||
"sysconf" => {
|
||||
let name = self.value_to_primval(args[0], usize)?.to_u64()?;
|
||||
trace!("sysconf() called with name {}", name);
|
||||
let result = match name {
|
||||
30 => PrimVal::Bytes(4096), // _SC_PAGESIZE
|
||||
70 => PrimVal::from_i128(-1), // _SC_GETPW_R_SIZE_MAX
|
||||
_ => return Err(EvalError::Unimplemented(format!("Unimplemented sysconf name: {}", name)))
|
||||
};
|
||||
self.write_primval(dest, result, dest_ty)?;
|
||||
// cache the sysconf integers via miri's global cache
|
||||
let paths = &[
|
||||
(&["libc", "_SC_PAGESIZE"], PrimVal::Bytes(4096)),
|
||||
(&["libc", "_SC_GETPW_R_SIZE_MAX"], PrimVal::from_i128(-1)),
|
||||
];
|
||||
let mut result = None;
|
||||
for &(path, path_value) in paths {
|
||||
if let Ok(instance) = self.resolve_path(path) {
|
||||
use lvalue::GlobalId;
|
||||
let cid = GlobalId { instance, promoted: None };
|
||||
// compute global if not cached
|
||||
let val = match self.globals.get(&cid).map(|glob| glob.value) {
|
||||
Some(value) => self.value_to_primval(value, usize)?.to_u64()?,
|
||||
None => ::const_eval::eval_body_as_primval(self.tcx, instance)?.0.to_u64()?,
|
||||
};
|
||||
if val == name {
|
||||
result = Some(path_value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(result) = result {
|
||||
self.write_primval(dest, result, dest_ty)?;
|
||||
} else {
|
||||
return Err(EvalError::Unimplemented(format!("Unimplemented sysconf name: {}", name)));
|
||||
}
|
||||
}
|
||||
|
||||
// Hook pthread calls that go to the thread-local storage memory subsystem
|
||||
|
|
@ -933,4 +955,41 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||
self.goto_block(dest_block);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get an instance for a path.
|
||||
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> {
|
||||
let cstore = &self.tcx.sess.cstore;
|
||||
|
||||
let crates = cstore.crates();
|
||||
crates.iter()
|
||||
.find(|&&krate| cstore.crate_name(krate) == path[0])
|
||||
.and_then(|krate| {
|
||||
let krate = DefId {
|
||||
krate: *krate,
|
||||
index: CRATE_DEF_INDEX,
|
||||
};
|
||||
let mut items = cstore.item_children(krate, self.tcx.sess);
|
||||
let mut path_it = path.iter().skip(1).peekable();
|
||||
|
||||
while let Some(segment) = path_it.next() {
|
||||
for item in &mem::replace(&mut items, vec![]) {
|
||||
if item.ident.name == *segment {
|
||||
if path_it.peek().is_none() {
|
||||
return Some(ty::Instance::mono(self.tcx, item.def.def_id()));
|
||||
}
|
||||
|
||||
items = cstore.item_children(item.def.def_id(), self.tcx.sess);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
let path = path.iter()
|
||||
.map(|&s| s.to_owned())
|
||||
.collect();
|
||||
EvalError::PathNotFound(path)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue