move build_mir into build directory
This commit is contained in:
parent
c2cfdbbdf9
commit
69c8f9dd25
3 changed files with 219 additions and 226 deletions
|
|
@ -8,22 +8,223 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use build;
|
||||
use hair::cx::Cx;
|
||||
use hair::Pattern;
|
||||
|
||||
use rustc::middle::region::{CodeExtent, CodeExtentData};
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::mir::*;
|
||||
use rustc::util::nodemap::NodeMap;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::region::{CodeExtent, CodeExtentData};
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::steal::Steal;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::util::nodemap::NodeMap;
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use shim;
|
||||
use std::mem;
|
||||
use std::u32;
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::symbol::keywords;
|
||||
use syntax_pos::Span;
|
||||
use util as mir_util;
|
||||
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<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);
|
||||
};
|
||||
|
||||
use std::u32;
|
||||
// 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 }
|
||||
}
|
||||
}
|
||||
hir::map::NodeVariant(variant) =>
|
||||
return create_constructor_shim(tcx, id, &variant.node.data),
|
||||
hir::map::NodeStructCtor(ctor) =>
|
||||
return create_constructor_shim(tcx, id, ctor),
|
||||
_ => unsupported()
|
||||
};
|
||||
|
||||
let src = MirSource::from_node(tcx, id);
|
||||
tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
|
||||
let cx = Cx::new(&infcx, src);
|
||||
let mut mir = if cx.tables().tainted_by_errors {
|
||||
build::construct_error(cx, body_id)
|
||||
} else 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.type_of(tcx.hir.local_def_id(id));
|
||||
let mut abi = fn_sig.abi;
|
||||
let implicit_argument = if let ty::TyClosure(..) = ty.sty {
|
||||
// HACK(eddyb) Avoid having RustCall on closures,
|
||||
// as it adds unnecessary (and wrong) auto-tupling.
|
||||
abi = Abi::Rust;
|
||||
Some((closure_self_ty(tcx, id, body_id), None))
|
||||
} else {
|
||||
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)
|
||||
};
|
||||
|
||||
mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
|
||||
|
||||
tcx.alloc_steal_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.
|
||||
struct GlobalizeMir<'a, 'gcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
||||
span: Span
|
||||
}
|
||||
|
||||
impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
|
||||
fn visit_ty(&mut self, ty: &mut Ty<'tcx>) {
|
||||
if let Some(lifted) = self.tcx.lift(ty) {
|
||||
*ty = lifted;
|
||||
} else {
|
||||
span_bug!(self.span,
|
||||
"found type `{:?}` with inference types/regions in MIR",
|
||||
ty);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>) {
|
||||
if let Some(lifted) = self.tcx.lift(substs) {
|
||||
*substs = lifted;
|
||||
} else {
|
||||
span_bug!(self.span,
|
||||
"found substs `{:?}` with inference types/regions in MIR",
|
||||
substs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ctor_id: ast::NodeId,
|
||||
v: &'tcx hir::VariantData)
|
||||
-> &'tcx Steal<Mir<'tcx>>
|
||||
{
|
||||
let span = tcx.hir.span(ctor_id);
|
||||
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
|
||||
let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
|
||||
tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
|
||||
let (mut mir, src) =
|
||||
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
|
||||
|
||||
// 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)
|
||||
};
|
||||
|
||||
mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
|
||||
|
||||
tcx.alloc_steal_mir(mir)
|
||||
})
|
||||
} else {
|
||||
span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
|
||||
|
||||
fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
closure_expr_id: ast::NodeId,
|
||||
body_id: hir::BodyId)
|
||||
-> Ty<'tcx> {
|
||||
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
|
||||
|
||||
let region = ty::ReFree(ty::FreeRegion {
|
||||
scope: Some(tcx.item_extent(body_id.node_id)),
|
||||
bound_region: ty::BoundRegion::BrEnv,
|
||||
});
|
||||
let region = tcx.mk_region(region);
|
||||
|
||||
match tcx.closure_kind(tcx.hir.local_def_id(closure_expr_id)) {
|
||||
ty::ClosureKind::Fn =>
|
||||
tcx.mk_ref(region,
|
||||
ty::TypeAndMut { ty: closure_ty,
|
||||
mutbl: hir::MutImmutable }),
|
||||
ty::ClosureKind::FnMut =>
|
||||
tcx.mk_ref(region,
|
||||
ty::TypeAndMut { ty: closure_ty,
|
||||
mutbl: hir::MutMutable }),
|
||||
ty::ClosureKind::FnOnce =>
|
||||
closure_ty
|
||||
}
|
||||
}
|
||||
|
||||
struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
hir: Cx<'a, 'gcx, 'tcx>,
|
||||
|
|
@ -121,13 +322,13 @@ macro_rules! unpack {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
/// the main entry point for building MIR for a function
|
||||
|
||||
pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
fn_id: ast::NodeId,
|
||||
arguments: A,
|
||||
abi: Abi,
|
||||
return_ty: Ty<'gcx>,
|
||||
body: &'gcx hir::Body)
|
||||
-> Mir<'tcx>
|
||||
fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
fn_id: ast::NodeId,
|
||||
arguments: A,
|
||||
abi: Abi,
|
||||
return_ty: Ty<'gcx>,
|
||||
body: &'gcx hir::Body)
|
||||
-> Mir<'tcx>
|
||||
where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
|
||||
{
|
||||
let arguments: Vec<_> = arguments.collect();
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ use rustc::middle::region::RegionMaps;
|
|||
use rustc::infer::InferCtxt;
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use syntax::symbol::{Symbol, InternedString};
|
||||
use syntax::symbol::Symbol;
|
||||
use rustc::hir;
|
||||
use rustc_const_math::{ConstInt, ConstUsize};
|
||||
use std::rc::Rc;
|
||||
|
|
@ -103,10 +103,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||
self.tcx.mk_nil()
|
||||
}
|
||||
|
||||
pub fn str_literal(&mut self, value: InternedString) -> Literal<'tcx> {
|
||||
Literal::Value { value: ConstVal::Str(value) }
|
||||
}
|
||||
|
||||
pub fn true_literal(&mut self) -> Literal<'tcx> {
|
||||
Literal::Value { value: ConstVal::Bool(true) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,31 +16,20 @@
|
|||
//! - `#[rustc_mir(graphviz="file.gv")]`
|
||||
//! - `#[rustc_mir(pretty="file.mir")]`
|
||||
|
||||
use build;
|
||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc::mir::Mir;
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
use shim;
|
||||
use hair::cx::Cx;
|
||||
use util as mir_util;
|
||||
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::steal::Steal;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::util::nodemap::DefIdSet;
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
use build::mir_build;
|
||||
*providers = Providers {
|
||||
mir_build,
|
||||
mir_keys,
|
||||
|
|
@ -86,196 +75,3 @@ fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum)
|
|||
|
||||
Rc::new(set)
|
||||
}
|
||||
|
||||
fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<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 }
|
||||
}
|
||||
}
|
||||
hir::map::NodeVariant(variant) =>
|
||||
return create_constructor_shim(tcx, id, &variant.node.data),
|
||||
hir::map::NodeStructCtor(ctor) =>
|
||||
return create_constructor_shim(tcx, id, ctor),
|
||||
_ => unsupported()
|
||||
};
|
||||
|
||||
let src = MirSource::from_node(tcx, id);
|
||||
tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
|
||||
let cx = Cx::new(&infcx, src);
|
||||
let mut mir = if cx.tables().tainted_by_errors {
|
||||
build::construct_error(cx, body_id)
|
||||
} else 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.type_of(tcx.hir.local_def_id(id));
|
||||
let mut abi = fn_sig.abi;
|
||||
let implicit_argument = if let ty::TyClosure(..) = ty.sty {
|
||||
// HACK(eddyb) Avoid having RustCall on closures,
|
||||
// as it adds unnecessary (and wrong) auto-tupling.
|
||||
abi = Abi::Rust;
|
||||
Some((closure_self_ty(tcx, id, body_id), None))
|
||||
} else {
|
||||
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)
|
||||
};
|
||||
|
||||
mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
|
||||
|
||||
tcx.alloc_steal_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.
|
||||
struct GlobalizeMir<'a, 'gcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
||||
span: Span
|
||||
}
|
||||
|
||||
impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
|
||||
fn visit_ty(&mut self, ty: &mut Ty<'tcx>) {
|
||||
if let Some(lifted) = self.tcx.lift(ty) {
|
||||
*ty = lifted;
|
||||
} else {
|
||||
span_bug!(self.span,
|
||||
"found type `{:?}` with inference types/regions in MIR",
|
||||
ty);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>) {
|
||||
if let Some(lifted) = self.tcx.lift(substs) {
|
||||
*substs = lifted;
|
||||
} else {
|
||||
span_bug!(self.span,
|
||||
"found substs `{:?}` with inference types/regions in MIR",
|
||||
substs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ctor_id: ast::NodeId,
|
||||
v: &'tcx hir::VariantData)
|
||||
-> &'tcx Steal<Mir<'tcx>>
|
||||
{
|
||||
let span = tcx.hir.span(ctor_id);
|
||||
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
|
||||
let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
|
||||
tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
|
||||
let (mut mir, src) =
|
||||
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
|
||||
|
||||
// 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)
|
||||
};
|
||||
|
||||
mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
|
||||
|
||||
tcx.alloc_steal_mir(mir)
|
||||
})
|
||||
} else {
|
||||
span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
|
||||
|
||||
fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
closure_expr_id: ast::NodeId,
|
||||
body_id: hir::BodyId)
|
||||
-> Ty<'tcx> {
|
||||
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
|
||||
|
||||
let region = ty::ReFree(ty::FreeRegion {
|
||||
scope: Some(tcx.item_extent(body_id.node_id)),
|
||||
bound_region: ty::BoundRegion::BrEnv,
|
||||
});
|
||||
let region = tcx.mk_region(region);
|
||||
|
||||
match tcx.closure_kind(tcx.hir.local_def_id(closure_expr_id)) {
|
||||
ty::ClosureKind::Fn =>
|
||||
tcx.mk_ref(region,
|
||||
ty::TypeAndMut { ty: closure_ty,
|
||||
mutbl: hir::MutImmutable }),
|
||||
ty::ClosureKind::FnMut =>
|
||||
tcx.mk_ref(region,
|
||||
ty::TypeAndMut { ty: closure_ty,
|
||||
mutbl: hir::MutMutable }),
|
||||
ty::ClosureKind::FnOnce =>
|
||||
closure_ty
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue