提交 555fc41d 编写于 作者: O Oliver Schneider 提交者: GitHub

Merge pull request #243 from solson/magic_numbers

Get rid of magic numbers
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 @@ fn description(&self) -> &str {
"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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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()),
}
}
......
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 value::{PrimVal, Value};
use rustc_data_structures::indexed_vec::Idx;
use std::mem;
mod drop;
mod intrinsic;
......@@ -853,12 +855,32 @@ fn call_c_abi(
"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 @@ fn call_c_abi(
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)
})
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册