Skip to content

Commit 555fc41

Browse files
authored
Merge pull request rust-lang#243 from solson/magic_numbers
Get rid of magic numbers
2 parents 14c8fe7 + f8757aa commit 555fc41

File tree

3 files changed

+88
-18
lines changed

3 files changed

+88
-18
lines changed

src/const_eval.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
1-
use rustc::hir::def_id::DefId;
21
use rustc::traits::Reveal;
3-
use rustc::ty::subst::Substs;
4-
use rustc::ty::{self, TyCtxt};
2+
use rustc::ty::{self, TyCtxt, Ty, Instance};
53

64
use error::{EvalError, EvalResult};
75
use lvalue::{Global, GlobalId, Lvalue};
6+
use value::PrimVal;
87
use rustc_const_math::ConstInt;
98
use eval_context::{EvalContext, StackPopCleanup};
109

11-
pub fn eval_body_as_integer<'a, 'tcx>(
10+
pub fn eval_body_as_primval<'a, 'tcx>(
1211
tcx: TyCtxt<'a, 'tcx, 'tcx>,
13-
(def_id, substs): (DefId, &'tcx Substs<'tcx>),
14-
) -> EvalResult<'tcx, ConstInt> {
12+
instance: Instance<'tcx>,
13+
) -> EvalResult<'tcx, (PrimVal, Ty<'tcx>)> {
1514
let limits = ::ResourceLimits::default();
1615
let mut ecx = EvalContext::new(tcx, limits);
17-
let instance = ecx.resolve_associated_const(def_id, substs);
1816
let cid = GlobalId { instance, promoted: None };
19-
if ecx.tcx.has_attr(def_id, "linkage") {
17+
if ecx.tcx.has_attr(instance.def_id(), "linkage") {
2018
return Err(EvalError::NotConst("extern global".to_string()));
2119
}
2220

@@ -28,7 +26,7 @@ pub fn eval_body_as_integer<'a, 'tcx>(
2826
ty::ParamEnv::empty(Reveal::All),
2927
mir.span);
3028
let cleanup = StackPopCleanup::MarkStatic(mutable);
31-
let name = ty::tls::with(|tcx| tcx.item_path_str(def_id));
29+
let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
3230
trace!("pushing stack frame for global: {}", name);
3331
ecx.push_stack_frame(
3432
instance,
@@ -41,11 +39,19 @@ pub fn eval_body_as_integer<'a, 'tcx>(
4139
while ecx.step()? {}
4240
}
4341
let value = ecx.globals.get(&cid).expect("global not cached").value;
44-
let prim = ecx.value_to_primval(value, mir.return_ty)?.to_bytes()?;
42+
Ok((ecx.value_to_primval(value, mir.return_ty)?, mir.return_ty))
43+
}
44+
45+
pub fn eval_body_as_integer<'a, 'tcx>(
46+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
47+
instance: Instance<'tcx>,
48+
) -> EvalResult<'tcx, ConstInt> {
49+
let (prim, ty) = eval_body_as_primval(tcx, instance)?;
50+
let prim = prim.to_bytes()?;
4551
use syntax::ast::{IntTy, UintTy};
4652
use rustc::ty::TypeVariants::*;
4753
use rustc_const_math::{ConstIsize, ConstUsize};
48-
Ok(match mir.return_ty.sty {
54+
Ok(match ty.sty {
4955
TyInt(IntTy::I8) => ConstInt::I8(prim as i128 as i8),
5056
TyInt(IntTy::I16) => ConstInt::I16(prim as i128 as i16),
5157
TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),

src/error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub enum EvalError<'tcx> {
6969
NeedsRfc(String),
7070
NotConst(String),
7171
ReadFromReturnPointer,
72+
PathNotFound(Vec<String>),
7273
}
7374

7475
pub type EvalResult<'tcx, T = ()> = Result<T, EvalError<'tcx>>;
@@ -175,6 +176,8 @@ impl<'tcx> Error for EvalError<'tcx> {
175176
"this feature is not compatible with constant evaluation",
176177
ReadFromReturnPointer =>
177178
"tried to read from the return pointer",
179+
EvalError::PathNotFound(_) =>
180+
"a path could not be resolved, maybe the crate is not loaded",
178181
}
179182
}
180183

@@ -215,6 +218,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
215218
write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg),
216219
NotConst(ref msg) =>
217220
write!(f, "Cannot evaluate within constants: \"{}\"", msg),
221+
EvalError::PathNotFound(ref path) =>
222+
write!(f, "Cannot find path {:?}", path),
218223
_ => write!(f, "{}", self.description()),
219224
}
220225
}

src/terminator/mod.rs

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc::hir::def_id::DefId;
1+
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
22
use rustc::mir;
33
use rustc::ty::{self, TypeVariants, Ty};
44
use rustc::ty::layout::Layout;
@@ -13,6 +13,8 @@ use memory::{MemoryPointer, TlsKey};
1313
use value::{PrimVal, Value};
1414
use rustc_data_structures::indexed_vec::Idx;
1515

16+
use std::mem;
17+
1618
mod drop;
1719
mod intrinsic;
1820

@@ -853,12 +855,32 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
853855
"sysconf" => {
854856
let name = self.value_to_primval(args[0], usize)?.to_u64()?;
855857
trace!("sysconf() called with name {}", name);
856-
let result = match name {
857-
30 => PrimVal::Bytes(4096), // _SC_PAGESIZE
858-
70 => PrimVal::from_i128(-1), // _SC_GETPW_R_SIZE_MAX
859-
_ => return Err(EvalError::Unimplemented(format!("Unimplemented sysconf name: {}", name)))
860-
};
861-
self.write_primval(dest, result, dest_ty)?;
858+
// cache the sysconf integers via miri's global cache
859+
let paths = &[
860+
(&["libc", "_SC_PAGESIZE"], PrimVal::Bytes(4096)),
861+
(&["libc", "_SC_GETPW_R_SIZE_MAX"], PrimVal::from_i128(-1)),
862+
];
863+
let mut result = None;
864+
for &(path, path_value) in paths {
865+
if let Ok(instance) = self.resolve_path(path) {
866+
use lvalue::GlobalId;
867+
let cid = GlobalId { instance, promoted: None };
868+
// compute global if not cached
869+
let val = match self.globals.get(&cid).map(|glob| glob.value) {
870+
Some(value) => self.value_to_primval(value, usize)?.to_u64()?,
871+
None => ::const_eval::eval_body_as_primval(self.tcx, instance)?.0.to_u64()?,
872+
};
873+
if val == name {
874+
result = Some(path_value);
875+
break;
876+
}
877+
}
878+
}
879+
if let Some(result) = result {
880+
self.write_primval(dest, result, dest_ty)?;
881+
} else {
882+
return Err(EvalError::Unimplemented(format!("Unimplemented sysconf name: {}", name)));
883+
}
862884
}
863885

864886
// Hook pthread calls that go to the thread-local storage memory subsystem
@@ -933,4 +955,41 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
933955
self.goto_block(dest_block);
934956
Ok(())
935957
}
958+
959+
/// Get an instance for a path.
960+
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> {
961+
let cstore = &self.tcx.sess.cstore;
962+
963+
let crates = cstore.crates();
964+
crates.iter()
965+
.find(|&&krate| cstore.crate_name(krate) == path[0])
966+
.and_then(|krate| {
967+
let krate = DefId {
968+
krate: *krate,
969+
index: CRATE_DEF_INDEX,
970+
};
971+
let mut items = cstore.item_children(krate, self.tcx.sess);
972+
let mut path_it = path.iter().skip(1).peekable();
973+
974+
while let Some(segment) = path_it.next() {
975+
for item in &mem::replace(&mut items, vec![]) {
976+
if item.ident.name == *segment {
977+
if path_it.peek().is_none() {
978+
return Some(ty::Instance::mono(self.tcx, item.def.def_id()));
979+
}
980+
981+
items = cstore.item_children(item.def.def_id(), self.tcx.sess);
982+
break;
983+
}
984+
}
985+
}
986+
None
987+
})
988+
.ok_or_else(|| {
989+
let path = path.iter()
990+
.map(|&s| s.to_owned())
991+
.collect();
992+
EvalError::PathNotFound(path)
993+
})
994+
}
936995
}

0 commit comments

Comments
 (0)