about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <oli-obk@users.noreply.github.com>2017-07-12 11:02:03 +0200
committerGitHub <noreply@github.com>2017-07-12 11:02:03 +0200
commitfda18f64cdef25daeeecbd7453cd45c47cfacff3 (patch)
tree3bd8f3bcb6b13800a5ebb43e73f81d4677fd1382
parente362c30ef85d74a00fe699688f88107181f39322 (diff)
parent4ce8be9538e332cb650983f14a341b6093ba0c34 (diff)
downloadrust-fda18f64cdef25daeeecbd7453cd45c47cfacff3.tar.gz
rust-fda18f64cdef25daeeecbd7453cd45c47cfacff3.zip
Merge pull request #241 from solson/rustc_integration
Produce `ConstInt` from a `def_id` for rustc
-rw-r--r--src/const_eval.rs63
-rw-r--r--src/lib.rs5
2 files changed, 68 insertions, 0 deletions
diff --git a/src/const_eval.rs b/src/const_eval.rs
new file mode 100644
index 00000000000..ff80f68e2c3
--- /dev/null
+++ b/src/const_eval.rs
@@ -0,0 +1,63 @@
+use rustc::hir::def_id::DefId;
+use rustc::traits::Reveal;
+use rustc::ty::subst::Substs;
+use rustc::ty::{self, TyCtxt};
+
+use error::{EvalError, EvalResult};
+use lvalue::{Global, GlobalId, Lvalue};
+use rustc_const_math::ConstInt;
+use eval_context::{EvalContext, StackPopCleanup};
+
+pub fn eval_body_as_integer<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    (def_id, substs): (DefId, &'tcx Substs<'tcx>),
+) -> EvalResult<'tcx, ConstInt> {
+    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") {
+        return Err(EvalError::NotConst("extern global".to_string()));
+    }
+    
+    let mir = ecx.load_mir(instance.def)?;
+    if !ecx.globals.contains_key(&cid) {
+        ecx.globals.insert(cid, Global::uninitialized(mir.return_ty));
+        let mutable = !mir.return_ty.is_freeze(
+                ecx.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));
+        trace!("pushing stack frame for global: {}", name);
+        ecx.push_stack_frame(
+            instance,
+            mir.span,
+            mir,
+            Lvalue::Global(cid),
+            cleanup,
+        )?;
+
+        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()?;
+    use syntax::ast::{IntTy, UintTy};
+    use rustc::ty::TypeVariants::*;
+    use rustc_const_math::{ConstIsize, ConstUsize};
+    Ok(match mir.return_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),
+        TyInt(IntTy::I64) => ConstInt::I64(prim as i128 as i64),
+        TyInt(IntTy::I128) => ConstInt::I128(prim as i128),
+        TyInt(IntTy::Is) => ConstInt::Isize(ConstIsize::new(prim as i128 as i64, tcx.sess.target.int_type).expect("miri should already have errored")),
+        TyUint(UintTy::U8) => ConstInt::U8(prim as u8),
+        TyUint(UintTy::U16) => ConstInt::U16(prim as u16),
+        TyUint(UintTy::U32) => ConstInt::U32(prim as u32),
+        TyUint(UintTy::U64) => ConstInt::U64(prim as u64),
+        TyUint(UintTy::U128) => ConstInt::U128(prim),
+        TyUint(UintTy::Us) => ConstInt::Usize(ConstUsize::new(prim as u64, tcx.sess.target.uint_type).expect("miri should already have errored")),
+        _ => return Err(EvalError::NeedsRfc("evaluating anything other than isize/usize during typeck".to_string())),
+    })
+}
diff --git a/src/lib.rs b/src/lib.rs
index bbb271a6b6a..d87a9ab6535 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -17,6 +17,7 @@ extern crate syntax;
 extern crate byteorder;
 
 mod cast;
+mod const_eval;
 mod error;
 mod eval_context;
 mod lvalue;
@@ -56,3 +57,7 @@ pub use value::{
     PrimValKind,
     Value,
 };
+
+pub use const_eval::{
+    eval_body_as_integer,
+};