Skip to content

Commit 374ea14

Browse files
committed
rustc_mir: expose MIR building through ty::maps::Provider.
1 parent b5c4244 commit 374ea14

File tree

2 files changed

+104
-59
lines changed

2 files changed

+104
-59
lines changed

src/librustc_driver/driver.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -872,9 +872,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
872872

873873
let index = stability::Index::new(&hir_map);
874874

875-
let local_providers = ty::maps::Providers::default();
876-
let mut extern_providers = ty::maps::Providers::default();
875+
let mut local_providers = ty::maps::Providers::default();
876+
mir::mir_map::provide(&mut local_providers);
877877

878+
let mut extern_providers = ty::maps::Providers::default();
878879
cstore::provide(&mut extern_providers);
879880

880881
TyCtxt::create_and_enter(sess,

src/librustc_mir/mir_map.rs

Lines changed: 101 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,25 @@
1717
//! - `#[rustc_mir(pretty="file.mir")]`
1818
1919
use build;
20+
use rustc::hir::def_id::DefId;
2021
use rustc::dep_graph::DepNode;
2122
use rustc::mir::Mir;
2223
use rustc::mir::transform::MirSource;
2324
use rustc::mir::visit::MutVisitor;
2425
use pretty;
2526
use hair::cx::Cx;
2627

27-
use rustc::infer::InferCtxt;
2828
use rustc::traits::Reveal;
2929
use rustc::ty::{self, Ty, TyCtxt};
30+
use rustc::ty::maps::Providers;
3031
use rustc::ty::subst::Substs;
3132
use rustc::hir;
3233
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
3334
use syntax::abi::Abi;
3435
use syntax::ast;
3536
use syntax_pos::Span;
3637

38+
use std::cell::RefCell;
3739
use std::mem;
3840

3941
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>) {
4244
}.as_deep_visitor());
4345
}
4446

47+
pub fn provide(providers: &mut Providers) {
48+
providers.mir = build_mir;
49+
}
50+
51+
fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
52+
-> &'tcx RefCell<Mir<'tcx>> {
53+
let id = tcx.hir.as_local_node_id(def_id).unwrap();
54+
let unsupported = || {
55+
span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id);
56+
};
57+
58+
// Figure out what primary body this item has.
59+
let body_id = match tcx.hir.get(id) {
60+
hir::map::NodeItem(item) => {
61+
match item.node {
62+
hir::ItemConst(_, body) |
63+
hir::ItemStatic(_, _, body) |
64+
hir::ItemFn(.., body) => body,
65+
_ => unsupported()
66+
}
67+
}
68+
hir::map::NodeTraitItem(item) => {
69+
match item.node {
70+
hir::TraitItemKind::Const(_, Some(body)) |
71+
hir::TraitItemKind::Method(_,
72+
hir::TraitMethod::Provided(body)) => body,
73+
_ => unsupported()
74+
}
75+
}
76+
hir::map::NodeImplItem(item) => {
77+
match item.node {
78+
hir::ImplItemKind::Const(_, body) |
79+
hir::ImplItemKind::Method(_, body) => body,
80+
_ => unsupported()
81+
}
82+
}
83+
hir::map::NodeExpr(expr) => {
84+
// FIXME(eddyb) Closures should have separate
85+
// function definition IDs and expression IDs.
86+
// Type-checking should not let closures get
87+
// this far in a constant position.
88+
// Assume that everything other than closures
89+
// is a constant "initializer" expression.
90+
match expr.node {
91+
hir::ExprClosure(_, _, body, _) => body,
92+
_ => hir::BodyId { node_id: expr.id }
93+
}
94+
}
95+
_ => unsupported()
96+
};
97+
98+
let src = MirSource::from_node(tcx, id);
99+
tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| {
100+
let cx = Cx::new(&infcx, src);
101+
let mut mir = if let MirSource::Fn(id) = src {
102+
// fetch the fully liberated fn signature (that is, all bound
103+
// types/lifetimes replaced)
104+
let fn_sig = cx.tables().liberated_fn_sigs[&id].clone();
105+
106+
let ty = tcx.item_type(tcx.hir.local_def_id(id));
107+
let (abi, implicit_argument) = if let ty::TyClosure(..) = ty.sty {
108+
(Abi::Rust, Some((closure_self_ty(tcx, id, body_id), None)))
109+
} else {
110+
(ty.fn_abi(), None)
111+
};
112+
113+
let body = tcx.hir.body(body_id);
114+
let explicit_arguments =
115+
body.arguments
116+
.iter()
117+
.enumerate()
118+
.map(|(index, arg)| {
119+
(fn_sig.inputs()[index], Some(&*arg.pat))
120+
});
121+
122+
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
123+
build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body)
124+
} else {
125+
build::construct_const(cx, body_id)
126+
};
127+
128+
// Convert the Mir to global types.
129+
let mut globalizer = GlobalizeMir {
130+
tcx: tcx,
131+
span: mir.span
132+
};
133+
globalizer.visit_mir(&mut mir);
134+
let mir = unsafe {
135+
mem::transmute::<Mir, Mir<'tcx>>(mir)
136+
};
137+
138+
pretty::dump_mir(tcx, "mir_map", &0, src, &mir);
139+
140+
tcx.alloc_mir(mir)
141+
})
142+
}
143+
45144
/// A pass to lift all the types and substitutions in a Mir
46145
/// to the global tcx. Sadly, we don't have a "folder" that
47146
/// can change 'tcx so we have to transmute afterwards.
@@ -79,68 +178,13 @@ struct BuildMir<'a, 'tcx: 'a> {
79178
tcx: TyCtxt<'a, 'tcx, 'tcx>
80179
}
81180

82-
fn build<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
83-
body_id: hir::BodyId)
84-
-> (Mir<'tcx>, MirSource) {
85-
let tcx = infcx.tcx.global_tcx();
86-
87-
let item_id = tcx.hir.body_owner(body_id);
88-
let src = MirSource::from_node(tcx, item_id);
89-
let cx = Cx::new(infcx, src);
90-
if let MirSource::Fn(id) = src {
91-
// fetch the fully liberated fn signature (that is, all bound
92-
// types/lifetimes replaced)
93-
let fn_sig = cx.tables().liberated_fn_sigs[&id].clone();
94-
95-
let ty = tcx.item_type(tcx.hir.local_def_id(id));
96-
let (abi, implicit_argument) = if let ty::TyClosure(..) = ty.sty {
97-
(Abi::Rust, Some((closure_self_ty(tcx, id, body_id), None)))
98-
} else {
99-
(ty.fn_abi(), None)
100-
};
101-
102-
let body = tcx.hir.body(body_id);
103-
let explicit_arguments =
104-
body.arguments
105-
.iter()
106-
.enumerate()
107-
.map(|(index, arg)| {
108-
(fn_sig.inputs()[index], Some(&*arg.pat))
109-
});
110-
111-
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
112-
(build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body), src)
113-
} else {
114-
(build::construct_const(cx, body_id), src)
115-
}
116-
}
117-
118181
impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
119182
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
120183
NestedVisitorMap::None
121184
}
122185

123186
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
124-
self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| {
125-
let (mut mir, src) = build(&infcx, body_id);
126-
127-
// Convert the Mir to global types.
128-
let tcx = infcx.tcx.global_tcx();
129-
let mut globalizer = GlobalizeMir {
130-
tcx: tcx,
131-
span: mir.span
132-
};
133-
globalizer.visit_mir(&mut mir);
134-
let mir = unsafe {
135-
mem::transmute::<Mir, Mir<'tcx>>(mir)
136-
};
137-
138-
pretty::dump_mir(tcx, "mir_map", &0, src, &mir);
139-
140-
let mir = tcx.alloc_mir(mir);
141-
let def_id = tcx.hir.local_def_id(src.item_id());
142-
tcx.maps.mir.borrow_mut().insert(def_id, mir);
143-
});
187+
self.tcx.item_mir(self.tcx.hir.body_owner_def_id(body_id));
144188

145189
let body = self.tcx.hir.body(body_id);
146190
self.visit_body(body);

0 commit comments

Comments
 (0)