Skip to content

Commit fda18f6

Browse files
authored
Merge pull request rust-lang#241 from solson/rustc_integration
Produce `ConstInt` from a `def_id` for rustc
2 parents e362c30 + 4ce8be9 commit fda18f6

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

src/const_eval.rs

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use rustc::hir::def_id::DefId;
2+
use rustc::traits::Reveal;
3+
use rustc::ty::subst::Substs;
4+
use rustc::ty::{self, TyCtxt};
5+
6+
use error::{EvalError, EvalResult};
7+
use lvalue::{Global, GlobalId, Lvalue};
8+
use rustc_const_math::ConstInt;
9+
use eval_context::{EvalContext, StackPopCleanup};
10+
11+
pub fn eval_body_as_integer<'a, 'tcx>(
12+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
13+
(def_id, substs): (DefId, &'tcx Substs<'tcx>),
14+
) -> EvalResult<'tcx, ConstInt> {
15+
let limits = ::ResourceLimits::default();
16+
let mut ecx = EvalContext::new(tcx, limits);
17+
let instance = ecx.resolve_associated_const(def_id, substs);
18+
let cid = GlobalId { instance, promoted: None };
19+
if ecx.tcx.has_attr(def_id, "linkage") {
20+
return Err(EvalError::NotConst("extern global".to_string()));
21+
}
22+
23+
let mir = ecx.load_mir(instance.def)?;
24+
if !ecx.globals.contains_key(&cid) {
25+
ecx.globals.insert(cid, Global::uninitialized(mir.return_ty));
26+
let mutable = !mir.return_ty.is_freeze(
27+
ecx.tcx,
28+
ty::ParamEnv::empty(Reveal::All),
29+
mir.span);
30+
let cleanup = StackPopCleanup::MarkStatic(mutable);
31+
let name = ty::tls::with(|tcx| tcx.item_path_str(def_id));
32+
trace!("pushing stack frame for global: {}", name);
33+
ecx.push_stack_frame(
34+
instance,
35+
mir.span,
36+
mir,
37+
Lvalue::Global(cid),
38+
cleanup,
39+
)?;
40+
41+
while ecx.step()? {}
42+
}
43+
let value = ecx.globals.get(&cid).expect("global not cached").value;
44+
let prim = ecx.value_to_primval(value, mir.return_ty)?.to_bytes()?;
45+
use syntax::ast::{IntTy, UintTy};
46+
use rustc::ty::TypeVariants::*;
47+
use rustc_const_math::{ConstIsize, ConstUsize};
48+
Ok(match mir.return_ty.sty {
49+
TyInt(IntTy::I8) => ConstInt::I8(prim as i128 as i8),
50+
TyInt(IntTy::I16) => ConstInt::I16(prim as i128 as i16),
51+
TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),
52+
TyInt(IntTy::I64) => ConstInt::I64(prim as i128 as i64),
53+
TyInt(IntTy::I128) => ConstInt::I128(prim as i128),
54+
TyInt(IntTy::Is) => ConstInt::Isize(ConstIsize::new(prim as i128 as i64, tcx.sess.target.int_type).expect("miri should already have errored")),
55+
TyUint(UintTy::U8) => ConstInt::U8(prim as u8),
56+
TyUint(UintTy::U16) => ConstInt::U16(prim as u16),
57+
TyUint(UintTy::U32) => ConstInt::U32(prim as u32),
58+
TyUint(UintTy::U64) => ConstInt::U64(prim as u64),
59+
TyUint(UintTy::U128) => ConstInt::U128(prim),
60+
TyUint(UintTy::Us) => ConstInt::Usize(ConstUsize::new(prim as u64, tcx.sess.target.uint_type).expect("miri should already have errored")),
61+
_ => return Err(EvalError::NeedsRfc("evaluating anything other than isize/usize during typeck".to_string())),
62+
})
63+
}

src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ extern crate syntax;
1717
extern crate byteorder;
1818

1919
mod cast;
20+
mod const_eval;
2021
mod error;
2122
mod eval_context;
2223
mod lvalue;
@@ -56,3 +57,7 @@ pub use value::{
5657
PrimValKind,
5758
Value,
5859
};
60+
61+
pub use const_eval::{
62+
eval_body_as_integer,
63+
};

0 commit comments

Comments
 (0)