From: Niko Matsakis Date: Tue, 2 May 2017 18:56:26 +0000 (-0400) Subject: move `build_mir` into `build` directory X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=69c8f9dd254982b3bf0908839bb7dc173b6cbaaa;p=rust.git move `build_mir` into `build` directory --- diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 94c53611e74..f5f6c307b15 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -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::hir; +use rustc::hir::def_id::DefId; use rustc::middle::region::{CodeExtent, CodeExtentData}; -use rustc::ty::{self, Ty}; 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::hir; +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> { + 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_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> +{ + 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_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, Option<&'gcx hir::Pat>)> { let arguments: Vec<_> = arguments.collect(); diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 3e9bcb3e186..ee8547e5dd6 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -26,7 +26,7 @@ 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 @@ pub fn unit_ty(&mut self) -> Ty<'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) } } diff --git a/src/librustc_mir/queries.rs b/src/librustc_mir/queries.rs index b4d752d2894..aef637fed5e 100644 --- a/src/librustc_mir/queries.rs +++ b/src/librustc_mir/queries.rs @@ -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 nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> { Rc::new(set) } - -fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { - 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_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> -{ - 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_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 - } -}