]> git.lizzy.rs Git - rust.git/commitdiff
rustc_mir: expose MIR building through ty::maps::Provider.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Wed, 8 Feb 2017 09:16:14 +0000 (11:16 +0200)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Sat, 25 Feb 2017 15:07:59 +0000 (17:07 +0200)
src/librustc_driver/driver.rs
src/librustc_mir/mir_map.rs

index 6dbdf55f1ca377fd6cf2f5197bd9e5a823d79d61..c1cfc0234e141c7f8ce2b58515a3b902b164ad4c 100644 (file)
@@ -872,9 +872,10 @@ macro_rules! try_with_f {
 
     let index = stability::Index::new(&hir_map);
 
-    let local_providers = ty::maps::Providers::default();
-    let mut extern_providers = ty::maps::Providers::default();
+    let mut local_providers = ty::maps::Providers::default();
+    mir::mir_map::provide(&mut local_providers);
 
+    let mut extern_providers = ty::maps::Providers::default();
     cstore::provide(&mut extern_providers);
 
     TyCtxt::create_and_enter(sess,
index 913b0d5fb8ae883bc1d4d53aeb0a9f4eac5042c0..dedc55404496a651ce4e6f951068fc6fa8271de9 100644 (file)
@@ -17,6 +17,7 @@
 //! - `#[rustc_mir(pretty="file.mir")]`
 
 use build;
+use rustc::hir::def_id::DefId;
 use rustc::dep_graph::DepNode;
 use rustc::mir::Mir;
 use rustc::mir::transform::MirSource;
@@ -24,9 +25,9 @@
 use pretty;
 use hair::cx::Cx;
 
-use rustc::infer::InferCtxt;
 use rustc::traits::Reveal;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::maps::Providers;
 use rustc::ty::subst::Substs;
 use rustc::hir;
 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
@@ -34,6 +35,7 @@
 use syntax::ast;
 use syntax_pos::Span;
 
+use std::cell::RefCell;
 use std::mem;
 
 pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -42,6 +44,103 @@ pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     }.as_deep_visitor());
 }
 
+pub fn provide(providers: &mut Providers) {
+    providers.mir = build_mir;
+}
+
+fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+                       -> &'tcx RefCell<Mir<'tcx>> {
+    let id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let unsupported = || {
+        span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id);
+    };
+
+    // Figure out what primary body this item has.
+    let body_id = match tcx.hir.get(id) {
+        hir::map::NodeItem(item) => {
+            match item.node {
+                hir::ItemConst(_, body) |
+                hir::ItemStatic(_, _, body) |
+                hir::ItemFn(.., body) => body,
+                _ => unsupported()
+            }
+        }
+        hir::map::NodeTraitItem(item) => {
+            match item.node {
+                hir::TraitItemKind::Const(_, Some(body)) |
+                hir::TraitItemKind::Method(_,
+                    hir::TraitMethod::Provided(body)) => body,
+                _ => unsupported()
+            }
+        }
+        hir::map::NodeImplItem(item) => {
+            match item.node {
+                hir::ImplItemKind::Const(_, body) |
+                hir::ImplItemKind::Method(_, body) => body,
+                _ => unsupported()
+            }
+        }
+        hir::map::NodeExpr(expr) => {
+            // FIXME(eddyb) Closures should have separate
+            // function definition IDs and expression IDs.
+            // Type-checking should not let closures get
+            // this far in a constant position.
+            // Assume that everything other than closures
+            // is a constant "initializer" expression.
+            match expr.node {
+                hir::ExprClosure(_, _, body, _) => body,
+                _ => hir::BodyId { node_id: expr.id }
+            }
+        }
+        _ => unsupported()
+    };
+
+    let src = MirSource::from_node(tcx, id);
+    tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| {
+        let cx = Cx::new(&infcx, src);
+        let mut mir = if let MirSource::Fn(id) = src {
+            // fetch the fully liberated fn signature (that is, all bound
+            // types/lifetimes replaced)
+            let fn_sig = cx.tables().liberated_fn_sigs[&id].clone();
+
+            let ty = tcx.item_type(tcx.hir.local_def_id(id));
+            let (abi, implicit_argument) = if let ty::TyClosure(..) = ty.sty {
+                (Abi::Rust, Some((closure_self_ty(tcx, id, body_id), None)))
+            } else {
+                (ty.fn_abi(), None)
+            };
+
+            let body = tcx.hir.body(body_id);
+            let explicit_arguments =
+                body.arguments
+                    .iter()
+                    .enumerate()
+                    .map(|(index, arg)| {
+                        (fn_sig.inputs()[index], Some(&*arg.pat))
+                    });
+
+            let arguments = implicit_argument.into_iter().chain(explicit_arguments);
+            build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body)
+        } else {
+            build::construct_const(cx, body_id)
+        };
+
+        // Convert the Mir to global types.
+        let mut globalizer = GlobalizeMir {
+            tcx: tcx,
+            span: mir.span
+        };
+        globalizer.visit_mir(&mut mir);
+        let mir = unsafe {
+            mem::transmute::<Mir, Mir<'tcx>>(mir)
+        };
+
+        pretty::dump_mir(tcx, "mir_map", &0, src, &mir);
+
+        tcx.alloc_mir(mir)
+    })
+}
+
 /// A pass to lift all the types and substitutions in a Mir
 /// to the global tcx. Sadly, we don't have a "folder" that
 /// can change 'tcx so we have to transmute afterwards.
@@ -79,68 +178,13 @@ struct BuildMir<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>
 }
 
-fn build<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                         body_id: hir::BodyId)
-                         -> (Mir<'tcx>, MirSource) {
-    let tcx = infcx.tcx.global_tcx();
-
-    let item_id = tcx.hir.body_owner(body_id);
-    let src = MirSource::from_node(tcx, item_id);
-    let cx = Cx::new(infcx, src);
-    if let MirSource::Fn(id) = src {
-        // fetch the fully liberated fn signature (that is, all bound
-        // types/lifetimes replaced)
-        let fn_sig = cx.tables().liberated_fn_sigs[&id].clone();
-
-        let ty = tcx.item_type(tcx.hir.local_def_id(id));
-        let (abi, implicit_argument) = if let ty::TyClosure(..) = ty.sty {
-            (Abi::Rust, Some((closure_self_ty(tcx, id, body_id), None)))
-        } else {
-            (ty.fn_abi(), None)
-        };
-
-        let body = tcx.hir.body(body_id);
-        let explicit_arguments =
-            body.arguments
-                .iter()
-                .enumerate()
-                .map(|(index, arg)| {
-                    (fn_sig.inputs()[index], Some(&*arg.pat))
-                });
-
-        let arguments = implicit_argument.into_iter().chain(explicit_arguments);
-        (build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body), src)
-    } else {
-        (build::construct_const(cx, body_id), src)
-    }
-}
-
 impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
         NestedVisitorMap::None
     }
 
     fn visit_nested_body(&mut self, body_id: hir::BodyId) {
-        self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| {
-            let (mut mir, src) = build(&infcx, body_id);
-
-            // Convert the Mir to global types.
-            let tcx = infcx.tcx.global_tcx();
-            let mut globalizer = GlobalizeMir {
-                tcx: tcx,
-                span: mir.span
-            };
-            globalizer.visit_mir(&mut mir);
-            let mir = unsafe {
-                mem::transmute::<Mir, Mir<'tcx>>(mir)
-            };
-
-            pretty::dump_mir(tcx, "mir_map", &0, src, &mir);
-
-            let mir = tcx.alloc_mir(mir);
-            let def_id = tcx.hir.local_def_id(src.item_id());
-            tcx.maps.mir.borrow_mut().insert(def_id, mir);
-        });
+        self.tcx.item_mir(self.tcx.hir.body_owner_def_id(body_id));
 
         let body = self.tcx.hir.body(body_id);
         self.visit_body(body);