Simplify BodyCache impl and fix all remaining type errors in librustc_mir (lifetime errors still exist)
This commit is contained in:
parent
38c0887c76
commit
fc6b58d0a8
63 changed files with 589 additions and 613 deletions
|
@ -23,17 +23,17 @@ macro_rules! arena_types {
|
|||
[] generics: rustc::ty::Generics,
|
||||
[] trait_def: rustc::ty::TraitDef,
|
||||
[] adt_def: rustc::ty::AdtDef,
|
||||
[] steal_mir: rustc::ty::steal::Steal<rustc::mir::Body<$tcx>>,
|
||||
[] mir: rustc::mir::Body<$tcx>,
|
||||
[] steal_mir: rustc::ty::steal::Steal<rustc::mir::BodyCache<$tcx>>,
|
||||
[] mir: rustc::mir::BodyCache<$tcx>,
|
||||
[] steal_promoted: rustc::ty::steal::Steal<
|
||||
rustc_index::vec::IndexVec<
|
||||
rustc::mir::Promoted,
|
||||
rustc::mir::Body<$tcx>
|
||||
rustc::mir::BodyCache<$tcx>
|
||||
>
|
||||
>,
|
||||
[] promoted: rustc_index::vec::IndexVec<
|
||||
rustc::mir::Promoted,
|
||||
rustc::mir::Body<$tcx>
|
||||
rustc::mir::BodyCache<$tcx>
|
||||
>,
|
||||
[] tables: rustc::ty::TypeckTables<$tcx>,
|
||||
[] const_allocs: rustc::mir::interpret::Allocation,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_index::vec::IndexVec;
|
||||
//use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
//use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
||||
//use crate::ich::StableHashingContext;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::mir::{BasicBlock, BasicBlockData, Body, LocalDecls, Location, Successors};
|
||||
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
|
||||
use rustc_data_structures::graph::dominators::{dominators, Dominators};
|
||||
|
@ -14,23 +14,23 @@ pub struct Cache {
|
|||
predecessors: Option<IndexVec<BasicBlock, Vec<BasicBlock>>>,
|
||||
}
|
||||
|
||||
//impl<'tcx, T> rustc_serialize::Encodable for Cache<'tcx, T> {
|
||||
// fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
// Encodable::encode(&(), s)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//impl<'tcx, T> rustc_serialize::Decodable for Cache<'tcx, T> {
|
||||
// fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
|
||||
// Decodable::decode(d).map(|_v: ()| Self::new())
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for Cache<'tcx, T> {
|
||||
// fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
|
||||
// // Do nothing.
|
||||
// }
|
||||
//}
|
||||
impl rustc_serialize::Encodable for Cache {
|
||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
Encodable::encode(&(), s)
|
||||
}
|
||||
}
|
||||
|
||||
impl rustc_serialize::Decodable for Cache {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
|
||||
Decodable::decode(d).map(|_v: ()| Self::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> HashStable<StableHashingContext<'a>> for Cache {
|
||||
fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! get_predecessors {
|
||||
(mut $self:ident, $block:expr, $body:expr) => {
|
||||
|
@ -98,13 +98,13 @@ impl Cache {
|
|||
|
||||
#[inline]
|
||||
/// This will recompute the predecessors cache if it is not available
|
||||
pub fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
|
||||
fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
|
||||
self.ensure_predecessors(body);
|
||||
self.predecessors.as_ref().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn predecessors_for(&mut self, bb: BasicBlock, body: &Body<'_>) -> &[BasicBlock] {
|
||||
fn predecessors_for(&mut self, bb: BasicBlock, body: &Body<'_>) -> &[BasicBlock] {
|
||||
&self.predecessors(body)[bb]
|
||||
}
|
||||
|
||||
|
@ -136,109 +136,58 @@ impl Cache {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct BodyCache<T> {
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct BodyCache<'tcx> {
|
||||
cache: Cache,
|
||||
body: T,
|
||||
body: Body<'tcx>,
|
||||
}
|
||||
|
||||
impl<T> BodyCache<T> {
|
||||
pub fn new(body: T) -> Self {
|
||||
impl BodyCache<'tcx> {
|
||||
pub fn new(body: Body<'tcx>) -> Self {
|
||||
Self {
|
||||
cache: Cache::new(),
|
||||
body
|
||||
body,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> BodyCache<&'a Body<'tcx>> {
|
||||
#[inline]
|
||||
pub fn predecessors_for(&mut self, bb: BasicBlock) -> &[BasicBlock] {
|
||||
self.cache.predecessors_for(bb, self.body)
|
||||
impl BodyCache<'tcx> {
|
||||
pub fn ensure_predecessors(&mut self) {
|
||||
self.cache.ensure_predecessors(&self.body);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn body(&self) -> &'a Body<'tcx> {
|
||||
self.body
|
||||
pub fn predecessors(&mut self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
|
||||
self.cache.predecessors(&self.body)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_only(mut self) -> ReadOnlyBodyCache<'a, 'tcx> {
|
||||
self.cache.ensure_predecessors(self.body);
|
||||
pub fn read_only(&self) -> ReadOnlyBodyCache<'_, '_> {
|
||||
assert!(self.cache.predecessors.is_some(), "");
|
||||
ReadOnlyBodyCache {
|
||||
cache: self.cache,
|
||||
body: self.body,
|
||||
cache: &self.cache,
|
||||
body: &self.body,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
|
||||
&self.body.basic_blocks
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Deref for BodyCache<&'a Body<'tcx>> {
|
||||
type Target = Body<'tcx>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Index<BasicBlock> for BodyCache<&'a Body<'tcx>> {
|
||||
type Output = BasicBlockData<'tcx>;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
|
||||
&self.body[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> BodyCache<&'a mut Body<'tcx>> {
|
||||
#[inline]
|
||||
pub fn body(&self) -> &Body<'tcx> {
|
||||
self.body
|
||||
&self.body
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn body_mut(&mut self) -> &mut Body<'tcx> {
|
||||
self.body
|
||||
&mut self.body
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_only(mut self) -> ReadOnlyBodyCache<'a, 'tcx> {
|
||||
self.cache.ensure_predecessors(self.body);
|
||||
ReadOnlyBodyCache {
|
||||
cache: self.cache,
|
||||
body: self.body,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
|
||||
&self.body.basic_blocks
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
|
||||
self.cache.basic_blocks_mut(&mut self.body)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Deref for BodyCache<&'a mut Body<'tcx>> {
|
||||
type Target = Body<'tcx>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.body
|
||||
pub fn basic_blocks_and_local_decls_mut(
|
||||
&mut self
|
||||
) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
|
||||
self.cache.basic_blocks_and_local_decls_mut(&mut self.body)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> DerefMut for BodyCache<&'a mut Body<'tcx>> {
|
||||
fn deref_mut(&mut self) -> &mut Body<'tcx> {
|
||||
self.body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Index<BasicBlock> for BodyCache<&'a mut Body<'tcx>> {
|
||||
impl<'tcx> Index<BasicBlock> for BodyCache<'tcx> {
|
||||
type Output = BasicBlockData<'tcx>;
|
||||
|
||||
#[inline]
|
||||
|
@ -247,15 +196,29 @@ impl<'a, 'tcx> Index<BasicBlock> for BodyCache<&'a mut Body<'tcx>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> IndexMut<BasicBlock> for BodyCache<&'a mut Body<'tcx>> {
|
||||
impl<'tcx> IndexMut<BasicBlock> for BodyCache<'tcx> {
|
||||
fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output {
|
||||
self.cache.invalidate_predecessors();
|
||||
&mut self.body.basic_blocks[index]
|
||||
&mut self.basic_blocks_mut()[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Deref for BodyCache<'tcx> {
|
||||
type Target = Body<'tcx>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DerefMut for BodyCache<'tcx> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.body
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ReadOnlyBodyCache<'a, 'tcx> {
|
||||
cache: Cache,
|
||||
cache: &'a Cache,
|
||||
body: &'a Body<'tcx>,
|
||||
}
|
||||
|
||||
|
@ -289,13 +252,6 @@ impl ReadOnlyBodyCache<'a, 'tcx> {
|
|||
pub fn dominators(&self) -> Dominators<BasicBlock> {
|
||||
dominators(self)
|
||||
}
|
||||
|
||||
pub fn to_owned(self) -> BodyCache<&'a Body<'tcx>> {
|
||||
BodyCache {
|
||||
cache: self.cache,
|
||||
body: self.body,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl graph::DirectedGraph for ReadOnlyBodyCache<'a, 'tcx> {
|
||||
|
@ -358,4 +314,20 @@ impl Index<BasicBlock> for ReadOnlyBodyCache<'a, 'tcx> {
|
|||
fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
|
||||
&self.body[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! {
|
||||
Cache,
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct BodyCache<'tcx> {
|
||||
cache,
|
||||
body,
|
||||
});
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for BodyCache<'tcx> {
|
||||
cache,
|
||||
body
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ pub struct Body<'tcx> {
|
|||
pub yield_ty: Option<Ty<'tcx>>,
|
||||
|
||||
/// Generator drop glue.
|
||||
pub generator_drop: Option<Box<Body<'tcx>>>,
|
||||
pub generator_drop: Option<Box<BodyCache<'tcx>>>,
|
||||
|
||||
/// The layout of a generator. Produced by the state transformation.
|
||||
pub generator_layout: Option<GeneratorLayout<'tcx>>,
|
||||
|
@ -2600,7 +2600,7 @@ impl Location {
|
|||
pub fn is_predecessor_of<'tcx>(
|
||||
&self,
|
||||
other: Location,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>
|
||||
) -> bool {
|
||||
// If we are in the same block as the other location and are an earlier statement
|
||||
// then we are a predecessor of `other`.
|
||||
|
|
|
@ -67,10 +67,10 @@ use syntax_pos::Span;
|
|||
|
||||
macro_rules! body_cache_type {
|
||||
(mut $a:lifetime, $tcx:lifetime) => {
|
||||
&mut BodyCache<& $a mut Body<$tcx>>
|
||||
&mut BodyCache<$tcx>
|
||||
};
|
||||
($a:lifetime, $tcx:lifetime) => {
|
||||
&ReadOnlyBodyCache<$a, $tcx>
|
||||
ReadOnlyBodyCache<$a, $tcx>
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -106,42 +106,46 @@ rustc_queries! {
|
|||
|
||||
/// Fetch the MIR for a given `DefId` right after it's built - this includes
|
||||
/// unreachable code.
|
||||
query mir_built(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {}
|
||||
query mir_built(_: DefId) -> &'tcx Steal<mir::BodyCache<'tcx>> {}
|
||||
|
||||
/// Fetch the MIR for a given `DefId` up till the point where it is
|
||||
/// ready for const evaluation.
|
||||
///
|
||||
/// See the README for the `mir` module for details.
|
||||
query mir_const(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {
|
||||
query mir_const(_: DefId) -> &'tcx Steal<mir::BodyCache<'tcx>> {
|
||||
no_hash
|
||||
}
|
||||
|
||||
query mir_validated(_: DefId) ->
|
||||
(
|
||||
&'tcx Steal<mir::Body<'tcx>>,
|
||||
&'tcx Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>>
|
||||
&'tcx Steal<mir::BodyCache<'tcx>>,
|
||||
&'tcx Steal<IndexVec<mir::Promoted, mir::BodyCache<'tcx>>>
|
||||
) {
|
||||
no_hash
|
||||
}
|
||||
|
||||
/// MIR after our optimization passes have run. This is MIR that is ready
|
||||
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
|
||||
query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
|
||||
query optimized_mir(key: DefId) -> &'tcx mir::BodyCache<'tcx> {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
load_cached(tcx, id) {
|
||||
let mir: Option<crate::mir::Body<'tcx>> = tcx.queries.on_disk_cache
|
||||
.try_load_query_result(tcx, id);
|
||||
mir.map(|x| &*tcx.arena.alloc(x))
|
||||
let mir: Option<crate::mir::BodyCache<'tcx>>
|
||||
= tcx.queries.on_disk_cache.try_load_query_result(tcx, id);
|
||||
mir.map(|x| {
|
||||
let cache = tcx.arena.alloc(x);
|
||||
cache.ensure_predecessors();
|
||||
&*cache
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> {
|
||||
query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::BodyCache<'tcx>> {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
load_cached(tcx, id) {
|
||||
let promoted: Option<
|
||||
rustc_index::vec::IndexVec<
|
||||
crate::mir::Promoted,
|
||||
crate::mir::Body<'tcx>
|
||||
crate::mir::BodyCache<'tcx>
|
||||
>> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id);
|
||||
promoted.map(|p| &*tcx.arena.alloc(p))
|
||||
}
|
||||
|
@ -502,7 +506,7 @@ rustc_queries! {
|
|||
/// in the case of closures, this will be redirected to the enclosing function.
|
||||
query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {}
|
||||
|
||||
query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> {
|
||||
query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyCache<'tcx> {
|
||||
no_force
|
||||
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::middle::cstore::EncodedMetadata;
|
|||
use crate::middle::lang_items;
|
||||
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
||||
use crate::middle::stability;
|
||||
use crate::mir::{Body, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted};
|
||||
use crate::mir::{BodyCache, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted};
|
||||
use crate::mir::interpret::{ConstValue, Allocation, Scalar};
|
||||
use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst};
|
||||
use crate::ty::ReprOptions;
|
||||
|
@ -1083,17 +1083,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
&self.hir_map
|
||||
}
|
||||
|
||||
pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal<Body<'tcx>> {
|
||||
self.arena.alloc(Steal::new(mir))
|
||||
pub fn alloc_steal_mir(self, mir_cache: BodyCache<'tcx>) -> &'tcx Steal<BodyCache<'tcx>> {
|
||||
self.arena.alloc(Steal::new(mir_cache))
|
||||
}
|
||||
|
||||
pub fn alloc_steal_promoted(self, promoted: IndexVec<Promoted, Body<'tcx>>) ->
|
||||
&'tcx Steal<IndexVec<Promoted, Body<'tcx>>> {
|
||||
pub fn alloc_steal_promoted(self, promoted: IndexVec<Promoted, BodyCache<'tcx>>) ->
|
||||
&'tcx Steal<IndexVec<Promoted, BodyCache<'tcx>>> {
|
||||
self.arena.alloc(Steal::new(promoted))
|
||||
}
|
||||
|
||||
pub fn intern_promoted(self, promoted: IndexVec<Promoted, Body<'tcx>>) ->
|
||||
&'tcx IndexVec<Promoted, Body<'tcx>> {
|
||||
pub fn intern_promoted(self, promoted: IndexVec<Promoted, BodyCache<'tcx>>) ->
|
||||
&'tcx IndexVec<Promoted, BodyCache<'tcx>> {
|
||||
self.arena.alloc(promoted)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ use crate::infer::canonical::Canonical;
|
|||
use crate::middle::cstore::CrateStoreDyn;
|
||||
use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
|
||||
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
|
||||
use crate::mir::Body;
|
||||
use crate::mir::ReadOnlyBodyCache;
|
||||
use crate::mir::interpret::{GlobalId, ErrorHandled};
|
||||
use crate::mir::GeneratorLayout;
|
||||
use crate::session::CrateDisambiguator;
|
||||
|
@ -2985,10 +2985,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
/// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
|
||||
pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
|
||||
pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> ReadOnlyBodyCache<'tcx, 'tcx> {
|
||||
match instance {
|
||||
ty::InstanceDef::Item(did) => {
|
||||
self.optimized_mir(did)
|
||||
self.optimized_mir(did).read_only()
|
||||
}
|
||||
ty::InstanceDef::VtableShim(..) |
|
||||
ty::InstanceDef::ReifyShim(..) |
|
||||
|
@ -2998,7 +2998,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
ty::InstanceDef::ClosureOnceShim { .. } |
|
||||
ty::InstanceDef::DropGlue(..) |
|
||||
ty::InstanceDef::CloneShim(..) => {
|
||||
self.mir_shims(instance)
|
||||
self.mir_shims(instance).read_only()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3023,7 +3023,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'tcx> {
|
||||
self.optimized_mir(def_id).generator_layout.as_ref().unwrap()
|
||||
self.optimized_mir(def_id).body().generator_layout.as_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
|
||||
|
|
|
@ -31,7 +31,6 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
|||
use rustc::middle::cstore::EncodedMetadata;
|
||||
use rustc::middle::lang_items::StartFnLangItem;
|
||||
use rustc::middle::weak_lang_items;
|
||||
use rustc::mir::BodyCache;
|
||||
use rustc::mir::mono::{CodegenUnitNameBuilder, CodegenUnit, MonoItem};
|
||||
use rustc::ty::{self, Ty, TyCtxt, Instance};
|
||||
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
|
||||
|
@ -375,8 +374,6 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
let lldecl = cx.get_fn(instance);
|
||||
|
||||
let mir = cx.tcx().instance_mir(instance.def);
|
||||
// TODO(nashenas88) move this into instance_mir before merging PR
|
||||
let mir = BodyCache::new(mir);
|
||||
mir::codegen_mir::<Bx>(cx, lldecl, mir, instance, sig);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ use syntax_pos::DUMMY_SP;
|
|||
use super::FunctionCx;
|
||||
use crate::traits::*;
|
||||
|
||||
pub fn non_ssa_locals<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
fx: &FunctionCx<'a, 'b, 'tcx, Bx>
|
||||
pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
fx: &FunctionCx<'a, 'tcx, Bx>
|
||||
) -> BitSet<mir::Local> {
|
||||
let mut analyzer = LocalAnalyzer::new(fx);
|
||||
|
||||
|
@ -56,8 +56,8 @@ pub fn non_ssa_locals<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
analyzer.non_ssa_locals
|
||||
}
|
||||
|
||||
struct LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
||||
fx: &'mir FunctionCx<'a, 'b, 'tcx, Bx>,
|
||||
struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
||||
fx: &'mir FunctionCx<'a, 'tcx, Bx>,
|
||||
dominators: Dominators<mir::BasicBlock>,
|
||||
non_ssa_locals: BitSet<mir::Local>,
|
||||
// The location of the first visited direct assignment to each
|
||||
|
@ -65,8 +65,8 @@ struct LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
|||
first_assignment: IndexVec<mir::Local, Location>,
|
||||
}
|
||||
|
||||
impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> {
|
||||
fn new(fx: &'mir FunctionCx<'a, 'b, 'tcx, Bx>) -> Self {
|
||||
impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
|
||||
fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self {
|
||||
let invalid_location =
|
||||
mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location();
|
||||
let dominators = fx.mir.dominators();
|
||||
|
@ -232,8 +232,8 @@ impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, '
|
|||
|
||||
}
|
||||
|
||||
impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
||||
for LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx>
|
||||
impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
||||
for LocalAnalyzer<'mir, 'a, 'tcx, Bx>
|
||||
{
|
||||
fn visit_assign(&mut self,
|
||||
place: &mir::Place<'tcx>,
|
||||
|
|
|
@ -33,19 +33,19 @@ struct TerminatorCodegenHelper<'a, 'tcx> {
|
|||
impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
|
||||
/// Returns the associated funclet from `FunctionCx::funclets` for the
|
||||
/// `funclet_bb` member if it is not `None`.
|
||||
fn funclet<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
&self,
|
||||
fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>,
|
||||
) -> Option<&'d Bx::Funclet> {
|
||||
fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
|
||||
) -> Option<&'c Bx::Funclet> {
|
||||
match self.funclet_bb {
|
||||
Some(funcl) => fx.funclets[funcl].as_ref(),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn lltarget<'b, 'c, 'd, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
&self,
|
||||
fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>,
|
||||
fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
|
||||
target: mir::BasicBlock
|
||||
) -> (Bx::BasicBlock, bool) {
|
||||
let span = self.terminator.source_info.span;
|
||||
|
@ -63,9 +63,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
|
|||
}
|
||||
|
||||
/// Create a basic block.
|
||||
fn llblock<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
&self,
|
||||
fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>,
|
||||
fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
|
||||
target: mir::BasicBlock
|
||||
) -> Bx::BasicBlock {
|
||||
let (lltarget, is_cleanupret) = self.lltarget(fx, target);
|
||||
|
@ -83,9 +83,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn funclet_br<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
&self,
|
||||
fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>,
|
||||
fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
|
||||
bx: &mut Bx,
|
||||
target: mir::BasicBlock,
|
||||
) {
|
||||
|
@ -101,9 +101,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
|
|||
|
||||
/// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional
|
||||
/// return destination `destination` and the cleanup function `cleanup`.
|
||||
fn do_call<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>(
|
||||
&self,
|
||||
fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>,
|
||||
fx: &'c mut FunctionCx<'b, 'tcx, Bx>,
|
||||
bx: &mut Bx,
|
||||
fn_abi: FnAbi<'tcx, Ty<'tcx>>,
|
||||
fn_ptr: Bx::Value,
|
||||
|
@ -153,7 +153,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
|
|||
// a loop.
|
||||
fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>(
|
||||
&self,
|
||||
mir: &mir::ReadOnlyBodyCache<'_, 'tcx>,
|
||||
mir: mir::ReadOnlyBodyCache<'_, 'tcx>,
|
||||
bx: &mut Bx,
|
||||
targets: &[mir::BasicBlock],
|
||||
) {
|
||||
|
@ -171,7 +171,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
|
|||
}
|
||||
|
||||
/// Codegen implementations for some terminator variants.
|
||||
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
/// Generates code for a `Resume` terminator.
|
||||
fn codegen_resume_terminator<'c>(
|
||||
&mut self,
|
||||
|
@ -216,7 +216,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
let lltrue = helper.llblock(self, targets[0]);
|
||||
let llfalse = helper.llblock(self, targets[1]);
|
||||
if switch_ty == bx.tcx().types.bool {
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, targets.as_slice());
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice());
|
||||
// Don't generate trivial icmps when switching on bool
|
||||
if let [0] = values[..] {
|
||||
bx.cond_br(discr.immediate(), llfalse, lltrue);
|
||||
|
@ -230,11 +230,11 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
);
|
||||
let llval = bx.const_uint_big(switch_llty, values[0]);
|
||||
let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval);
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, targets.as_slice());
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice());
|
||||
bx.cond_br(cmp, lltrue, llfalse);
|
||||
}
|
||||
} else {
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, targets.as_slice());
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice());
|
||||
let (otherwise, targets) = targets.split_last().unwrap();
|
||||
bx.switch(
|
||||
discr.immediate(),
|
||||
|
@ -330,7 +330,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
|
||||
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
|
||||
// we don't actually need to drop anything.
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
|
||||
helper.funclet_br(self, &mut bx, target);
|
||||
return
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
FnAbi::of_instance(&bx, drop_fn))
|
||||
}
|
||||
};
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
|
||||
helper.do_call(self, &mut bx, fn_ty, drop_fn, args,
|
||||
Some((ReturnDest::Nothing, target)),
|
||||
unwind);
|
||||
|
@ -397,7 +397,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
|
||||
// Don't codegen the panic block if success if known.
|
||||
if const_cond == Some(expected) {
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
|
||||
helper.funclet_br(self, &mut bx, target);
|
||||
return;
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
// Create the failure block and the conditional branch to it.
|
||||
let lltarget = helper.llblock(self, target);
|
||||
let panic_block = self.new_block("panic");
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
|
||||
if expected {
|
||||
bx.cond_br(cond, lltarget, panic_block.llbb());
|
||||
} else {
|
||||
|
@ -493,7 +493,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
if let Some(destination_ref) = destination.as_ref() {
|
||||
let &(ref dest, target) = destination_ref;
|
||||
self.codegen_transmute(&mut bx, &args[0], dest);
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
|
||||
helper.funclet_br(self, &mut bx, target);
|
||||
} else {
|
||||
// If we are trying to transmute to an uninhabited type,
|
||||
|
@ -521,7 +521,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
Some(ty::InstanceDef::DropGlue(_, None)) => {
|
||||
// Empty drop glue; a no-op.
|
||||
let &(_, target) = destination.as_ref().unwrap();
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
|
||||
helper.funclet_br(self, &mut bx, target);
|
||||
return;
|
||||
}
|
||||
|
@ -553,7 +553,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
let llfn = bx.get_fn_addr(instance);
|
||||
|
||||
if let Some((_, target)) = destination.as_ref() {
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[*target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[*target]);
|
||||
}
|
||||
// Codegen the actual panic invoke/call.
|
||||
helper.do_call(
|
||||
|
@ -568,7 +568,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
} else {
|
||||
// a NOP
|
||||
let target = destination.as_ref().unwrap().1;
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
|
||||
helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1)
|
||||
}
|
||||
return;
|
||||
|
@ -682,7 +682,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
if let Some((_, target)) = *destination {
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
|
||||
helper.funclet_br(self, &mut bx, target);
|
||||
} else {
|
||||
bx.unreachable();
|
||||
|
@ -776,7 +776,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
};
|
||||
|
||||
if let Some((_, target)) = destination.as_ref() {
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[*target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[*target]);
|
||||
}
|
||||
helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs,
|
||||
destination.as_ref().map(|&(_, target)| (ret_dest, target)),
|
||||
|
@ -784,13 +784,13 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn codegen_block(
|
||||
&mut self,
|
||||
bb: mir::BasicBlock,
|
||||
) {
|
||||
let mut bx = self.build_block(bb);
|
||||
let data = &self.mir[bb];
|
||||
let data = &self.mir.body()[bb];
|
||||
|
||||
debug!("codegen_block({:?}={:?})", bb, data);
|
||||
|
||||
|
@ -827,7 +827,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
mir::TerminatorKind::Goto { target } => {
|
||||
helper.maybe_sideeffect(&self.mir, &mut bx, &[target]);
|
||||
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
|
||||
helper.funclet_br(self, &mut bx, target);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::mir::operand::OperandRef;
|
|||
|
||||
use super::FunctionCx;
|
||||
|
||||
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn eval_mir_constant_to_operand(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rustc::ty::{self, Ty, TypeFoldable, Instance};
|
||||
use rustc::ty::layout::{TyLayout, HasTyCtxt, FnAbiExt};
|
||||
use rustc::mir::{self, Body, BodyCache};
|
||||
use rustc::mir::{self, Body, ReadOnlyBodyCache};
|
||||
use rustc_target::abi::call::{FnAbi, PassMode};
|
||||
use crate::base;
|
||||
use crate::traits::*;
|
||||
|
@ -18,10 +18,10 @@ use rustc::mir::traversal;
|
|||
use self::operand::{OperandRef, OperandValue};
|
||||
|
||||
/// Master context for codegenning from MIR.
|
||||
pub struct FunctionCx<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
||||
pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
||||
instance: Instance<'tcx>,
|
||||
|
||||
mir: &'b mir::ReadOnlyBodyCache<'a, 'tcx>,
|
||||
mir: mir::ReadOnlyBodyCache<'a, 'tcx>,
|
||||
|
||||
debug_context: Option<FunctionDebugContext<Bx::DIScope>>,
|
||||
|
||||
|
@ -79,7 +79,7 @@ pub struct FunctionCx<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
|||
per_local_var_debug_info: Option<IndexVec<mir::Local, Vec<&'a mir::VarDebugInfo<'tcx>>>>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn monomorphize<T>(&self, value: &T) -> T
|
||||
where T: TypeFoldable<'tcx>
|
||||
{
|
||||
|
@ -122,7 +122,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> {
|
|||
pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
cx: &'a Bx::CodegenCx,
|
||||
llfn: Bx::Function,
|
||||
mut mir: BodyCache<&'a Body<'tcx>>,
|
||||
mir: ReadOnlyBodyCache<'a, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
sig: ty::FnSig<'tcx>,
|
||||
) {
|
||||
|
@ -157,10 +157,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs);
|
||||
let mir_body = mir.body();
|
||||
let readonly_mir = mir.read_only();
|
||||
let mut fx = FunctionCx {
|
||||
instance,
|
||||
mir: &readonly_mir,
|
||||
mir,
|
||||
llfn,
|
||||
fn_abi,
|
||||
cx,
|
||||
|
@ -319,9 +318,9 @@ fn create_funclets<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
/// Produces, for each argument, a `Value` pointing at the
|
||||
/// argument's value. As arguments are places, these are always
|
||||
/// indirect.
|
||||
fn arg_local_refs<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
fx: &FunctionCx<'a, 'b, 'tcx, Bx>,
|
||||
fx: &FunctionCx<'a, 'tcx, Bx>,
|
||||
memory_locals: &BitSet<mir::Local>,
|
||||
) -> Vec<LocalRef<'tcx, Bx::Value>> {
|
||||
let mut idx = 0;
|
||||
|
|
|
@ -377,7 +377,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
fn maybe_codegen_consume_direct(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
|
|
|
@ -435,7 +435,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn codegen_place(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
|
|
|
@ -18,7 +18,7 @@ use syntax::source_map::{DUMMY_SP, Span};
|
|||
|
||||
use std::{u128, i128};
|
||||
|
||||
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn codegen_rvalue(
|
||||
&mut self,
|
||||
mut bx: Bx,
|
||||
|
@ -695,7 +695,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn rvalue_creates_operand(
|
||||
&self,
|
||||
rvalue: &mir::Rvalue<'tcx>,
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::traits::*;
|
|||
|
||||
use rustc_error_codes::*;
|
||||
|
||||
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> {
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn codegen_statement(
|
||||
&mut self,
|
||||
mut bx: Bx,
|
||||
|
|
|
@ -18,12 +18,11 @@ use rustc_data_structures::fx::FxHashMap;
|
|||
use rustc_data_structures::svh::Svh;
|
||||
use rustc::dep_graph::{self, DepNodeIndex};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::mir::{self, interpret};
|
||||
use rustc::mir::{self, BodyCache, interpret, Promoted};
|
||||
use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState};
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::codec::TyDecoder;
|
||||
use rustc::mir::{Body, Promoted};
|
||||
use rustc::util::common::record_time;
|
||||
use rustc::util::captures::Captures;
|
||||
|
||||
|
@ -1080,7 +1079,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
self.root.per_def.mir.get(self, id).is_some()
|
||||
}
|
||||
|
||||
fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
|
||||
fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> BodyCache<'tcx> {
|
||||
self.root.per_def.mir.get(self, id)
|
||||
.filter(|_| !self.is_proc_macro(id))
|
||||
.unwrap_or_else(|| {
|
||||
|
@ -1093,7 +1092,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
id: DefIndex,
|
||||
) -> IndexVec<Promoted, Body<'tcx>> {
|
||||
) -> IndexVec<Promoted, BodyCache<'tcx>> {
|
||||
self.root.per_def.promoted_mir.get(self, id)
|
||||
.filter(|_| !self.is_proc_macro(id))
|
||||
.unwrap_or_else(|| {
|
||||
|
|
|
@ -276,8 +276,8 @@ define_per_def_tables! {
|
|||
// Also, as an optimization, a missing entry indicates an empty `&[]`.
|
||||
inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
|
||||
super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
|
||||
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
|
||||
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
|
||||
mir: Table<DefIndex, Lazy!(mir::BodyCache<'tcx>)>,
|
||||
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::BodyCache<'tcx>>)>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
|
|
|
@ -90,7 +90,7 @@ crate enum LocalsStateAtExit {
|
|||
impl LocalsStateAtExit {
|
||||
fn build(
|
||||
locals_are_invalidated_at_exit: bool,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
move_data: &MoveData<'tcx>
|
||||
) -> Self {
|
||||
struct HasStorageDead(BitSet<Local>);
|
||||
|
@ -123,7 +123,7 @@ impl LocalsStateAtExit {
|
|||
impl<'tcx> BorrowSet<'tcx> {
|
||||
pub fn build(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
locals_are_invalidated_at_exit: bool,
|
||||
move_data: &MoveData<'tcx>,
|
||||
) -> Self {
|
||||
|
@ -139,7 +139,7 @@ impl<'tcx> BorrowSet<'tcx> {
|
|||
LocalsStateAtExit::build(locals_are_invalidated_at_exit, body_cache, move_data),
|
||||
};
|
||||
|
||||
for (block, block_data) in traversal::preorder(body_cache) {
|
||||
for (block, block_data) in traversal::preorder(&body_cache) {
|
||||
visitor.visit_basic_block_data(block, block_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> {
|
|||
fn do_mir_borrowck<'a, 'tcx>(
|
||||
infcx: &InferCtxt<'a, 'tcx>,
|
||||
input_body: &Body<'tcx>,
|
||||
input_promoted: &IndexVec<Promoted, Body<'tcx>>,
|
||||
input_promoted: &IndexVec<Promoted, BodyCache<'tcx>>,
|
||||
def_id: DefId,
|
||||
) -> BorrowCheckResult<'tcx> {
|
||||
debug!("do_mir_borrowck(def_id = {:?})", def_id);
|
||||
|
@ -162,14 +162,13 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
// requires first making our own copy of the MIR. This copy will
|
||||
// be modified (in place) to contain non-lexical lifetimes. It
|
||||
// will have a lifetime tied to the inference context.
|
||||
let mut body: Body<'tcx> = input_body.clone();
|
||||
let body: Body<'tcx> = input_body.clone();
|
||||
let mut promoted = input_promoted.clone();
|
||||
let mut promoted_cache: IndexVec<Promoted, BodyCache<&mut Body<'tcx>>> = input_promoted.clone().iter_mut().map(|body| BodyCache::new(body)).collect();
|
||||
let mut body_cache = BodyCache::new(&mut body);
|
||||
let mut body_cache = BodyCache::new(body);
|
||||
let free_regions =
|
||||
nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted_cache);
|
||||
let body_cache = BodyCache::new(&body).read_only(); // no further changes
|
||||
let promoted: IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>> = promoted_cache.into_iter().map(|body_cache| body_cache.read_only()).collect();
|
||||
nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted);
|
||||
let body_cache = body_cache.read_only(); // no further changes
|
||||
let promoted: IndexVec<_, _> = promoted.iter().map(|body_cache| body_cache.read_only()).collect();
|
||||
|
||||
let location_table = &LocationTable::new(&body_cache);
|
||||
|
||||
|
@ -198,14 +197,14 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
|
||||
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure();
|
||||
let borrow_set = Rc::new(BorrowSet::build(
|
||||
tcx, &body_cache, locals_are_invalidated_at_exit, &mdpe.move_data));
|
||||
tcx, body_cache, locals_are_invalidated_at_exit, &mdpe.move_data));
|
||||
|
||||
// If we are in non-lexical mode, compute the non-lexical lifetimes.
|
||||
let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions(
|
||||
infcx,
|
||||
def_id,
|
||||
free_regions,
|
||||
&body_cache,
|
||||
body_cache,
|
||||
&promoted,
|
||||
&local_names,
|
||||
&upvars,
|
||||
|
@ -1338,7 +1337,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
_ => bug!("temporary initialized in arguments"),
|
||||
};
|
||||
|
||||
let bbd = &self.body_cache[loc.block];
|
||||
let bbd = &self.body_cache.body()[loc.block];
|
||||
let stmt = &bbd.statements[loc.statement_index];
|
||||
debug!("temporary assigned in: stmt={:?}", stmt);
|
||||
|
||||
|
@ -1860,7 +1859,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if def.is_union() {
|
||||
if this.move_data.path_map[mpi].iter().any(|moi| {
|
||||
this.move_data.moves[*moi].source.is_predecessor_of(
|
||||
location, &this.body_cache,
|
||||
location, this.body_cache,
|
||||
)
|
||||
}) {
|
||||
return;
|
||||
|
|
|
@ -377,7 +377,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
},
|
||||
))) => Some(suggest_ampmut(
|
||||
self.infcx.tcx,
|
||||
&self.body_cache,
|
||||
self.body_cache,
|
||||
*local,
|
||||
local_decl,
|
||||
opt_ty_info,
|
||||
|
@ -529,7 +529,7 @@ fn suggest_ampmut_self<'tcx>(
|
|||
// by trying (3.), then (2.) and finally falling back on (1.).
|
||||
fn suggest_ampmut<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
local: Local,
|
||||
local_decl: &mir::LocalDecl<'tcx>,
|
||||
opt_ty_info: Option<Span>,
|
||||
|
|
|
@ -22,7 +22,7 @@ pub(super) fn generate_invalidates<'tcx>(
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
location_table: &LocationTable,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
if all_facts.is_none() {
|
||||
|
@ -41,7 +41,7 @@ pub(super) fn generate_invalidates<'tcx>(
|
|||
body: body_cache.body(),
|
||||
dominators,
|
||||
};
|
||||
ig.visit_body(&body_cache);
|
||||
ig.visit_body(body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,8 +55,8 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
|
|||
infcx: &InferCtxt<'cx, 'tcx>,
|
||||
def_id: DefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_cache: &mut BodyCache<&mut Body<'tcx>>,
|
||||
promoted: &mut IndexVec<Promoted, BodyCache<&mut Body<'tcx>>>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
promoted: &mut IndexVec<Promoted, BodyCache<'tcx>>,
|
||||
) -> UniversalRegions<'tcx> {
|
||||
debug!("replace_regions_in_mir(def_id={:?})", def_id);
|
||||
|
||||
|
@ -158,7 +158,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
|||
infcx: &InferCtxt<'cx, 'tcx>,
|
||||
def_id: DefId,
|
||||
universal_regions: UniversalRegions<'tcx>,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
promoted_cache: &IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>>,
|
||||
local_names: &IndexVec<Local, Option<Symbol>>,
|
||||
upvars: &[Upvar],
|
||||
|
@ -181,7 +181,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
|||
|
||||
let universal_regions = Rc::new(universal_regions);
|
||||
|
||||
let elements = &Rc::new(RegionValueElements::new(body_cache));
|
||||
let elements = &Rc::new(RegionValueElements::new(body_cache.body()));
|
||||
|
||||
// Run the MIR type-checker.
|
||||
let MirTypeckResults {
|
||||
|
@ -206,7 +206,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
|||
all_facts
|
||||
.universal_region
|
||||
.extend(universal_regions.universal_regions());
|
||||
populate_polonius_move_facts(all_facts, move_data, location_table, body_cache);
|
||||
populate_polonius_move_facts(all_facts, move_data, location_table, body_cache.body());
|
||||
}
|
||||
|
||||
// Create the region inference context, taking ownership of the
|
||||
|
@ -230,7 +230,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
|||
&mut liveness_constraints,
|
||||
&mut all_facts,
|
||||
location_table,
|
||||
body_cache,
|
||||
body_cache.body(),
|
||||
borrow_set,
|
||||
);
|
||||
|
||||
|
@ -239,7 +239,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
|||
universal_regions,
|
||||
placeholder_indices,
|
||||
universal_region_relations,
|
||||
body_cache,
|
||||
body_cache.body(),
|
||||
outlives_constraints,
|
||||
member_constraints,
|
||||
closure_bounds_mapping,
|
||||
|
@ -284,21 +284,21 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
|||
|
||||
// Solve the region constraints.
|
||||
let closure_region_requirements =
|
||||
regioncx.solve(infcx, body_cache, local_names, upvars, def_id, errors_buffer);
|
||||
regioncx.solve(infcx, body_cache.body(), local_names, upvars, def_id, errors_buffer);
|
||||
|
||||
// Dump MIR results into a file, if that is enabled. This let us
|
||||
// write unit-tests, as well as helping with debugging.
|
||||
dump_mir_results(
|
||||
infcx,
|
||||
MirSource::item(def_id),
|
||||
body_cache,
|
||||
body_cache.body(),
|
||||
®ioncx,
|
||||
&closure_region_requirements,
|
||||
);
|
||||
|
||||
// We also have a `#[rustc_nll]` annotation that causes us to dump
|
||||
// information
|
||||
dump_annotation(infcx, body_cache, def_id, ®ioncx, &closure_region_requirements, errors_buffer);
|
||||
dump_annotation(infcx, body_cache.body(), def_id, ®ioncx, &closure_region_requirements, errors_buffer);
|
||||
|
||||
(regioncx, polonius_output, closure_region_requirements)
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ impl RegionValueElements {
|
|||
/// Pushes all predecessors of `index` onto `stack`.
|
||||
crate fn push_predecessors(
|
||||
&self,
|
||||
body_cache: &ReadOnlyBodyCache<'_, '_>,
|
||||
body_cache: ReadOnlyBodyCache<'_, '_>,
|
||||
index: PointIndex,
|
||||
stack: &mut Vec<PointIndex>,
|
||||
) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rustc::ty::subst::SubstsRef;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::mir::{Body, BodyCache, Location, PlaceElem, Promoted};
|
||||
use rustc::mir::{BodyCache, Location, PlaceElem, Promoted};
|
||||
use rustc::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
||||
use rustc_index::vec::IndexVec;
|
||||
|
@ -9,8 +9,8 @@ use rustc_index::vec::IndexVec;
|
|||
/// inference variables, returning the number of variables created.
|
||||
pub fn renumber_mir<'tcx>(
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
body_cache: &mut BodyCache<&mut Body<'tcx>>,
|
||||
promoted: &mut IndexVec<Promoted, BodyCache<&mut Body<'tcx>>>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
promoted: &mut IndexVec<Promoted, BodyCache<'tcx>>,
|
||||
) {
|
||||
debug!("renumber_mir()");
|
||||
debug!("renumber_mir: body.arg_count={:?}", body_cache.arg_count);
|
||||
|
|
|
@ -60,7 +60,7 @@ impl LocalUseMap {
|
|||
crate fn build(
|
||||
live_locals: &Vec<Local>,
|
||||
elements: &RegionValueElements,
|
||||
body_cache: &ReadOnlyBodyCache<'_, '_>,
|
||||
body_cache: ReadOnlyBodyCache<'_, '_>,
|
||||
) -> Self {
|
||||
let nones = IndexVec::from_elem_n(None, body_cache.local_decls.len());
|
||||
let mut local_use_map = LocalUseMap {
|
||||
|
|
|
@ -28,7 +28,7 @@ mod trace;
|
|||
/// performed before
|
||||
pub(super) fn generate<'tcx>(
|
||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
elements: &Rc<RegionValueElements>,
|
||||
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
|
@ -48,7 +48,7 @@ pub(super) fn generate<'tcx>(
|
|||
let mut drop_used = Vec::new();
|
||||
polonius::populate_access_facts(
|
||||
typeck,
|
||||
&body_cache,
|
||||
body_cache,
|
||||
location_table,
|
||||
move_data,
|
||||
&mut drop_used,
|
||||
|
|
|
@ -97,7 +97,7 @@ fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty
|
|||
|
||||
pub(super) fn populate_access_facts(
|
||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
location_table: &LocationTable,
|
||||
move_data: &MoveData<'_>,
|
||||
drop_used: &mut Vec<(Local, Location)>,
|
||||
|
|
|
@ -32,7 +32,7 @@ use std::rc::Rc;
|
|||
/// this respects `#[may_dangle]` annotations).
|
||||
pub(super) fn trace(
|
||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
elements: &Rc<RegionValueElements>,
|
||||
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
|
@ -41,7 +41,7 @@ pub(super) fn trace(
|
|||
) {
|
||||
debug!("trace()");
|
||||
|
||||
let local_use_map = &LocalUseMap::build(&live_locals, elements, &body_cache);
|
||||
let local_use_map = &LocalUseMap::build(&live_locals, elements, body_cache);
|
||||
|
||||
let cx = LivenessContext {
|
||||
typeck,
|
||||
|
@ -71,7 +71,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
|
|||
elements: &'me RegionValueElements,
|
||||
|
||||
/// MIR we are analyzing.
|
||||
body_cache: &'me ReadOnlyBodyCache<'me, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'me, 'tcx>,
|
||||
|
||||
/// Mapping to/from the various indices used for initialization tracking.
|
||||
move_data: &'me MoveData<'tcx>,
|
||||
|
@ -211,7 +211,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
|||
}
|
||||
|
||||
if self.use_live_at.insert(p) {
|
||||
self.cx.elements.push_predecessors(&self.cx.body_cache, p, &mut self.stack)
|
||||
self.cx.elements.push_predecessors(self.cx.body_cache, p, &mut self.stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ mod relate_tys;
|
|||
pub(crate) fn type_check<'tcx>(
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
promoted_cache: &IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>>,
|
||||
mir_def_id: DefId,
|
||||
universal_regions: &Rc<UniversalRegions<'tcx>>,
|
||||
|
@ -168,7 +168,7 @@ pub(crate) fn type_check<'tcx>(
|
|||
&mut borrowck_context,
|
||||
&universal_region_relations,
|
||||
|mut cx| {
|
||||
cx.equate_inputs_and_outputs(body_cache, universal_regions, &normalized_inputs_and_output);
|
||||
cx.equate_inputs_and_outputs(body_cache.body(), universal_regions, &normalized_inputs_and_output);
|
||||
liveness::generate(&mut cx, body_cache, elements, flow_inits, move_data, location_table);
|
||||
|
||||
translate_outlives_facts(cx.borrowck_context);
|
||||
|
@ -185,7 +185,7 @@ fn type_check_internal<'a, 'tcx, R>(
|
|||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
mir_def_id: DefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_cache: &ReadOnlyBodyCache<'a, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'a, 'tcx>,
|
||||
promoted_cache: &'a IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>>,
|
||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
|
@ -195,7 +195,7 @@ fn type_check_internal<'a, 'tcx, R>(
|
|||
) -> R where {
|
||||
let mut checker = TypeChecker::new(
|
||||
infcx,
|
||||
body_cache,
|
||||
body_cache.body(),
|
||||
mir_def_id,
|
||||
param_env,
|
||||
region_bound_pairs,
|
||||
|
@ -204,14 +204,14 @@ fn type_check_internal<'a, 'tcx, R>(
|
|||
universal_region_relations,
|
||||
);
|
||||
let errors_reported = {
|
||||
let mut verifier = TypeVerifier::new(&mut checker, body_cache, promoted_cache);
|
||||
let mut verifier = TypeVerifier::new(&mut checker, body_cache.body(), promoted_cache);
|
||||
verifier.visit_body(body_cache);
|
||||
verifier.errors_reported
|
||||
};
|
||||
|
||||
if !errors_reported {
|
||||
// if verifier failed, don't do further checks to avoid ICEs
|
||||
checker.typeck_mir(body_cache);
|
||||
checker.typeck_mir(body_cache.body());
|
||||
}
|
||||
|
||||
extra(&mut checker)
|
||||
|
@ -385,7 +385,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_body(&mut self, body_cache: &ReadOnlyBodyCache<'_, 'tcx>) {
|
||||
fn visit_body(&mut self, body_cache: ReadOnlyBodyCache<'_, 'tcx>) {
|
||||
self.sanitize_type(&"return type", body_cache.return_ty());
|
||||
for local_decl in &body_cache.local_decls {
|
||||
self.sanitize_type(local_decl, local_decl.ty);
|
||||
|
@ -464,7 +464,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
match kind {
|
||||
StaticKind::Promoted(promoted, _) => {
|
||||
if !self.errors_reported {
|
||||
let promoted_body_cache = &self.promoted_cache[*promoted];
|
||||
let promoted_body_cache = self.promoted_cache[*promoted];
|
||||
self.sanitize_promoted(promoted_body_cache, location);
|
||||
|
||||
let promoted_ty = promoted_body_cache.return_ty();
|
||||
|
@ -535,7 +535,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
place_ty
|
||||
}
|
||||
|
||||
fn sanitize_promoted(&mut self, promoted_body_cache: &ReadOnlyBodyCache<'b, 'tcx>, location: Location) {
|
||||
fn sanitize_promoted(&mut self, promoted_body_cache: ReadOnlyBodyCache<'b, 'tcx>, location: Location) {
|
||||
// Determine the constraints from the promoted MIR by running the type
|
||||
// checker on the promoted MIR, then transfer the constraints back to
|
||||
// the main MIR, changing the locations to the provided location.
|
||||
|
|
|
@ -32,7 +32,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
never_initialized_mut_locals: &mut never_initialized_mut_locals,
|
||||
mbcx: self,
|
||||
};
|
||||
visitor.visit_body(&visitor.mbcx.body_cache);
|
||||
visitor.visit_body(visitor.mbcx.body_cache);
|
||||
}
|
||||
|
||||
// Take the union of the existed `used_mut` set with those variables we've found were
|
||||
|
|
|
@ -24,7 +24,7 @@ use syntax_pos::Span;
|
|||
use super::lints;
|
||||
|
||||
/// Construct the MIR for a given `DefId`.
|
||||
pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
|
||||
pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyCache<'_> {
|
||||
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
|
||||
|
||||
// Figure out what primary body this item has.
|
||||
|
@ -196,7 +196,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
|
|||
|
||||
lints::check(tcx, &body, def_id);
|
||||
|
||||
body
|
||||
BodyCache::new(body)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -354,7 +354,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
}
|
||||
// This is a const fn. Call it.
|
||||
Ok(Some(match ecx.load_mir(instance.def, None) {
|
||||
Ok(body) => body,
|
||||
Ok(body_cache) => body_cache.body(),
|
||||
Err(err) => {
|
||||
if let err_unsup!(NoMirFor(ref path)) = err.kind {
|
||||
return Err(
|
||||
|
@ -697,7 +697,7 @@ pub fn const_eval_raw_provider<'tcx>(
|
|||
|
||||
let res = ecx.load_mir(cid.instance.def, cid.promoted);
|
||||
res.and_then(
|
||||
|body| eval_body_using_ecx(&mut ecx, cid, body)
|
||||
|body_cache| eval_body_using_ecx(&mut ecx, cid, body_cache.body())
|
||||
).and_then(|place| {
|
||||
Ok(RawConst {
|
||||
alloc_id: place.ptr.assert_ptr().alloc_id,
|
||||
|
|
|
@ -75,19 +75,19 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
|
|||
/// Dataflow analysis that determines whether each local requires storage at a
|
||||
/// given location; i.e. whether its storage can go away without being observed.
|
||||
pub struct RequiresStorage<'mir, 'tcx> {
|
||||
body_cache: &'mir ReadOnlyBodyCache<'mir, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'mir, 'tcx>,
|
||||
borrowed_locals:
|
||||
RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
|
||||
pub fn new(
|
||||
body_cache: &'mir ReadOnlyBodyCache<'mir, 'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'mir, 'tcx>,
|
||||
borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>,
|
||||
) -> Self {
|
||||
RequiresStorage {
|
||||
body_cache,
|
||||
borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body_cache)),
|
||||
borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body_cache.body())),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> {
|
|||
sets,
|
||||
borrowed_locals: &self.borrowed_locals,
|
||||
};
|
||||
visitor.visit_location(&self.body_cache, loc);
|
||||
visitor.visit_location(self.body_cache, loc);
|
||||
}
|
||||
|
||||
/// Gen locals that are newly borrowed. This includes borrowing any part of
|
||||
|
|
|
@ -292,7 +292,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
&self,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
promoted: Option<mir::Promoted>,
|
||||
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
|
||||
) -> InterpResult<'tcx, mir::ReadOnlyBodyCache<'tcx, 'tcx>> {
|
||||
// do not continue if typeck errors occurred (can only occur in local crate)
|
||||
let did = instance.def_id();
|
||||
if did.is_local()
|
||||
|
@ -303,11 +303,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
trace!("load mir(instance={:?}, promoted={:?})", instance, promoted);
|
||||
if let Some(promoted) = promoted {
|
||||
return Ok(&self.tcx.promoted_mir(did)[promoted]);
|
||||
return Ok(self.tcx.promoted_mir(did)[promoted].read_only());
|
||||
}
|
||||
match instance {
|
||||
ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) {
|
||||
Ok(self.tcx.optimized_mir(did))
|
||||
Ok(self.tcx.optimized_mir(did).read_only())
|
||||
} else {
|
||||
throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id)))
|
||||
},
|
||||
|
|
|
@ -186,7 +186,7 @@ use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance};
|
|||
use rustc::ty::print::obsolete::DefPathBasedNames;
|
||||
use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
|
||||
use rustc::session::config::EntryFnType;
|
||||
use rustc::mir::{self, BodyCache, Location, PlaceBase, Static, StaticKind};
|
||||
use rustc::mir::{self, Location, PlaceBase, Static, StaticKind};
|
||||
use rustc::mir::visit::Visitor as MirVisitor;
|
||||
use rustc::mir::mono::{MonoItem, InstantiationMode};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled};
|
||||
|
@ -1248,15 +1248,15 @@ fn collect_neighbours<'tcx>(
|
|||
output: &mut Vec<MonoItem<'tcx>>,
|
||||
) {
|
||||
debug!("collect_neighbours: {:?}", instance.def_id());
|
||||
let body = tcx.instance_mir(instance.def);
|
||||
let body_cache = BodyCache::new(body).read_only();
|
||||
let body_cache = tcx.instance_mir(instance.def);
|
||||
let body = body_cache.body();
|
||||
|
||||
MirNeighborCollector {
|
||||
tcx,
|
||||
body: &body,
|
||||
output,
|
||||
param_substs: instance.substs,
|
||||
}.visit_body(&body_cache);
|
||||
}.visit_body(body_cache);
|
||||
}
|
||||
|
||||
fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String {
|
||||
|
|
|
@ -26,7 +26,7 @@ pub fn provide(providers: &mut Providers<'_>) {
|
|||
providers.mir_shims = make_shim;
|
||||
}
|
||||
|
||||
fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
|
||||
fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx BodyCache<'tcx> {
|
||||
debug!("make_shim({:?})", instance);
|
||||
|
||||
let mut result = match instance {
|
||||
|
@ -113,7 +113,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
|
|||
bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
|
||||
}
|
||||
};
|
||||
debug!("make_shim({:?}) = untransformed {:?}", instance, result);
|
||||
debug!("make_shim({:?}) = untransformed {:?}", instance, result.body());
|
||||
|
||||
run_passes(tcx, &mut result, instance, None, MirPhase::Const, &[
|
||||
&add_moves_for_packed_drops::AddMovesForPackedDrops,
|
||||
|
@ -123,7 +123,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
|
|||
&add_call_guards::CriticalCallEdges,
|
||||
]);
|
||||
|
||||
debug!("make_shim({:?}) = {:?}", instance, result);
|
||||
debug!("make_shim({:?}) = {:?}", instance, result.body());
|
||||
|
||||
tcx.arena.alloc(result)
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span)
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>) -> Body<'tcx> {
|
||||
fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>) -> BodyCache<'tcx> {
|
||||
debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
|
||||
|
||||
// Check if this is a generator, if so, return the drop glue for it
|
||||
|
@ -202,7 +202,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
|||
sig.inputs().len(),
|
||||
span);
|
||||
|
||||
let mut body_cache = BodyCache::new(&mut body);
|
||||
let mut body_cache = BodyCache::new(body);
|
||||
|
||||
if let Some(..) = ty {
|
||||
// The first argument (index 0), but add 1 for the return value.
|
||||
|
@ -238,8 +238,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
|||
patch.apply(&mut body_cache);
|
||||
}
|
||||
|
||||
// TODO(pfaia) return owning body cache...
|
||||
body
|
||||
body_cache
|
||||
}
|
||||
|
||||
fn new_body<'tcx>(
|
||||
|
@ -317,7 +316,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
|
|||
}
|
||||
|
||||
/// Builds a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
|
||||
fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
|
||||
fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> BodyCache<'tcx> {
|
||||
debug!("build_clone_shim(def_id={:?})", def_id);
|
||||
|
||||
let param_env = tcx.param_env(def_id);
|
||||
|
@ -346,7 +345,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
|
|||
}
|
||||
};
|
||||
|
||||
builder.into_mir()
|
||||
BodyCache::new(builder.into_mir())
|
||||
}
|
||||
|
||||
struct CloneShimBuilder<'tcx> {
|
||||
|
@ -707,7 +706,7 @@ fn build_call_shim<'tcx>(
|
|||
rcvr_adjustment: Adjustment,
|
||||
call_kind: CallKind,
|
||||
untuple_args: Option<&[Ty<'tcx>]>,
|
||||
) -> Body<'tcx> {
|
||||
) -> BodyCache<'tcx> {
|
||||
debug!("build_call_shim(def_id={:?}, rcvr_adjustment={:?}, \
|
||||
call_kind={:?}, untuple_args={:?})",
|
||||
def_id, rcvr_adjustment, call_kind, untuple_args);
|
||||
|
@ -842,10 +841,10 @@ fn build_call_shim<'tcx>(
|
|||
if let Abi::RustCall = sig.abi {
|
||||
body.spread_arg = Some(Local::new(sig.inputs().len()));
|
||||
}
|
||||
body
|
||||
BodyCache::new(body)
|
||||
}
|
||||
|
||||
pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> {
|
||||
pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyCache<'_> {
|
||||
debug_assert!(tcx.is_constructor(ctor_id));
|
||||
|
||||
let span = tcx.hir().span_if_local(ctor_id)
|
||||
|
@ -929,5 +928,5 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> {
|
|||
|_, _| Ok(()),
|
||||
);
|
||||
|
||||
tcx.arena.alloc(body)
|
||||
tcx.arena.alloc(BodyCache::new(body))
|
||||
}
|
||||
|
|
|
@ -31,22 +31,22 @@ pub use self::AddCallGuards::*;
|
|||
*/
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for AddCallGuards {
|
||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
self.add_call_guards(body);
|
||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
self.add_call_guards(body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
impl AddCallGuards {
|
||||
pub fn add_call_guards(&self, body: &mut Body<'_>) {
|
||||
pub fn add_call_guards(&self, body_cache: &mut BodyCache<'_>) {
|
||||
let pred_count: IndexVec<_, _> =
|
||||
body.predecessors().iter().map(|ps| ps.len()).collect();
|
||||
body_cache.predecessors().iter().map(|ps| ps.len()).collect();
|
||||
|
||||
// We need a place to store the new blocks generated
|
||||
let mut new_blocks = Vec::new();
|
||||
|
||||
let cur_len = body.basic_blocks().len();
|
||||
let cur_len = body_cache.basic_blocks().len();
|
||||
|
||||
for block in body.basic_blocks_mut() {
|
||||
for block in body_cache.basic_blocks_mut() {
|
||||
match block.terminator {
|
||||
Some(Terminator {
|
||||
kind: TerminatorKind::Call {
|
||||
|
@ -78,6 +78,6 @@ impl AddCallGuards {
|
|||
|
||||
debug!("Broke {} N edges", new_blocks.len());
|
||||
|
||||
body.basic_blocks_mut().extend(new_blocks);
|
||||
body_cache.basic_blocks_mut().extend(new_blocks);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,15 +40,15 @@ use crate::util;
|
|||
pub struct AddMovesForPackedDrops;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span);
|
||||
add_moves_for_packed_drops(tcx, body, src.def_id());
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body_cache.span);
|
||||
add_moves_for_packed_drops(tcx, body_cache, src.def_id());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, def_id: DefId) {
|
||||
let patch = add_moves_for_packed_drops_patch(tcx, body, def_id);
|
||||
patch.apply(body);
|
||||
pub fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>, def_id: DefId) {
|
||||
let patch = add_moves_for_packed_drops_patch(tcx, body_cache, def_id);
|
||||
patch.apply(body_cache);
|
||||
}
|
||||
|
||||
fn add_moves_for_packed_drops_patch<'tcx>(
|
||||
|
|
|
@ -59,12 +59,12 @@ fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool {
|
|||
}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for AddRetag {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
if !tcx.sess.opts.debugging_opts.mir_emit_retag {
|
||||
return;
|
||||
}
|
||||
let (span, arg_count) = (body.span, body.arg_count);
|
||||
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
|
||||
let (span, arg_count) = (body_cache.span, body_cache.arg_count);
|
||||
let (basic_blocks, local_decls) = body_cache.basic_blocks_and_local_decls_mut();
|
||||
let needs_retag = |place: &Place<'tcx>| {
|
||||
// FIXME: Instead of giving up for unstable places, we should introduce
|
||||
// a temporary and retag on that.
|
||||
|
|
|
@ -528,7 +528,7 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult
|
|||
hir::BodyOwnerKind::Static(_) => (true, false),
|
||||
};
|
||||
let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env);
|
||||
checker.visit_body(body);
|
||||
checker.visit_body(body.read_only());
|
||||
|
||||
check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks);
|
||||
UnsafetyCheckResult {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
//! [`FakeRead`]: rustc::mir::StatementKind::FakeRead
|
||||
//! [`Nop`]: rustc::mir::StatementKind::Nop
|
||||
|
||||
use rustc::mir::{BorrowKind, Rvalue, Location, Body};
|
||||
use rustc::mir::{BodyCache, BorrowKind, Rvalue, Location};
|
||||
use rustc::mir::{Statement, StatementKind};
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
use rustc::ty::TyCtxt;
|
||||
|
@ -29,9 +29,9 @@ pub struct DeleteNonCodegenStatements<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
let mut delete = DeleteNonCodegenStatements { tcx };
|
||||
delete.visit_body(body);
|
||||
delete.visit_body(body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,10 @@ use std::cell::Cell;
|
|||
use rustc::hir::def::DefKind;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir::{
|
||||
AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local, UnOp,
|
||||
StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo,
|
||||
BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, RETURN_PLACE,
|
||||
AggregateKind, Constant, Location, Place, PlaceBase, Body, BodyCache, Operand, Local, UnOp,
|
||||
Rvalue. StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate,
|
||||
SourceInfo, BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, ReadOnlyBodyCache,
|
||||
RETURN_PLACE
|
||||
};
|
||||
use rustc::mir::visit::{
|
||||
Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
|
||||
|
@ -41,7 +42,7 @@ const MAX_ALLOC_LIMIT: u64 = 1024;
|
|||
pub struct ConstProp;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
// will be evaluated by miri and produce its errors there
|
||||
if source.promoted.is_some() {
|
||||
return;
|
||||
|
@ -76,15 +77,15 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
|||
|
||||
let dummy_body =
|
||||
&Body::new(
|
||||
body.basic_blocks().clone(),
|
||||
body.source_scopes.clone(),
|
||||
body.local_decls.clone(),
|
||||
body_cache.basic_blocks().clone(),
|
||||
body_cache.source_scopes.clone(),
|
||||
body_cache.local_decls.clone(),
|
||||
Default::default(),
|
||||
body.arg_count,
|
||||
body_cache.arg_count,
|
||||
Default::default(),
|
||||
tcx.def_span(source.def_id()),
|
||||
Default::default(),
|
||||
body.generator_kind,
|
||||
body_cache.generator_kind,
|
||||
);
|
||||
|
||||
// FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold
|
||||
|
@ -92,12 +93,12 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
|||
// That would require an uniform one-def no-mutation analysis
|
||||
// and RPO (or recursing when needing the value of a local).
|
||||
let mut optimization_finder = ConstPropagator::new(
|
||||
body,
|
||||
body_cache.read_only(),
|
||||
dummy_body,
|
||||
tcx,
|
||||
source
|
||||
);
|
||||
optimization_finder.visit_body(body);
|
||||
optimization_finder.visit_body(body_cache);
|
||||
|
||||
trace!("ConstProp done for {:?}", source.def_id());
|
||||
}
|
||||
|
@ -284,7 +285,7 @@ impl<'mir, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> {
|
|||
|
||||
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
fn new(
|
||||
body: &Body<'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'mir, 'tcx>,
|
||||
dummy_body: &'mir Body<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
source: MirSource<'tcx>,
|
||||
|
@ -293,7 +294,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
let param_env = tcx.param_env(def_id);
|
||||
let span = tcx.def_span(def_id);
|
||||
let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine, ());
|
||||
let can_const_prop = CanConstProp::check(body);
|
||||
let can_const_prop = CanConstProp::check(body_cache);
|
||||
|
||||
let substs = &InternalSubsts::identity_for_item(tcx, def_id);
|
||||
|
||||
|
@ -325,9 +326,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
can_const_prop,
|
||||
// FIXME(eddyb) avoid cloning these two fields more than once,
|
||||
// by accessing them through `ecx` instead.
|
||||
source_scopes: body.source_scopes.clone(),
|
||||
source_scopes: body_cache.source_scopes.clone(),
|
||||
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
|
||||
local_decls: body.local_decls.clone(),
|
||||
local_decls: body_cache.local_decls.clone(),
|
||||
ret: ret.map(Into::into),
|
||||
}
|
||||
}
|
||||
|
@ -678,10 +679,10 @@ struct CanConstProp {
|
|||
|
||||
impl CanConstProp {
|
||||
/// returns true if `local` can be propagated
|
||||
fn check(body: &Body<'_>) -> IndexVec<Local, bool> {
|
||||
fn check(body_cache: ReadOnlyBodyCache<'_, '_>) -> IndexVec<Local, bool> {
|
||||
let mut cpv = CanConstProp {
|
||||
can_const_prop: IndexVec::from_elem(true, &body.local_decls),
|
||||
found_assignment: IndexVec::from_elem(false, &body.local_decls),
|
||||
can_const_prop: IndexVec::from_elem(true, &body_cache.local_decls),
|
||||
found_assignment: IndexVec::from_elem(false, &body_cache.local_decls),
|
||||
};
|
||||
for (local, val) in cpv.can_const_prop.iter_enumerated_mut() {
|
||||
// cannot use args at all
|
||||
|
@ -689,14 +690,14 @@ impl CanConstProp {
|
|||
// lint for x != y
|
||||
// FIXME(oli-obk): lint variables until they are used in a condition
|
||||
// FIXME(oli-obk): lint if return value is constant
|
||||
let local_kind = body.local_kind(local);
|
||||
let local_kind = body_cache.local_kind(local);
|
||||
*val = local_kind == LocalKind::Temp || local_kind == LocalKind::ReturnPointer;
|
||||
|
||||
if !*val {
|
||||
trace!("local {:?} can't be propagated because it's not a temporary", local);
|
||||
}
|
||||
}
|
||||
cpv.visit_body(body);
|
||||
cpv.visit_body(body_cache);
|
||||
cpv.can_const_prop
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
//! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
|
||||
//! future.
|
||||
|
||||
use rustc::mir::{Constant, Local, LocalKind, Location, Place, Body, Operand, Rvalue, StatementKind};
|
||||
use rustc::mir::{
|
||||
Constant, Local, LocalKind, Location, Place, Body, BodyCache, Operand, Rvalue,
|
||||
StatementKind
|
||||
};
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
use rustc::ty::TyCtxt;
|
||||
use crate::transform::{MirPass, MirSource};
|
||||
|
@ -28,23 +31,23 @@ use crate::util::def_use::DefUseAnalysis;
|
|||
pub struct CopyPropagation;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for CopyPropagation {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
// We only run when the MIR optimization level is > 1.
|
||||
// This avoids a slow pass, and messing up debug info.
|
||||
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut def_use_analysis = DefUseAnalysis::new(body);
|
||||
let mut def_use_analysis = DefUseAnalysis::new(body_cache);
|
||||
loop {
|
||||
def_use_analysis.analyze(body);
|
||||
def_use_analysis.analyze(body_cache.read_only());
|
||||
|
||||
if eliminate_self_assignments(body, &def_use_analysis) {
|
||||
def_use_analysis.analyze(body);
|
||||
if eliminate_self_assignments(body_cache, &def_use_analysis) {
|
||||
def_use_analysis.analyze(body_cache.read_only());
|
||||
}
|
||||
|
||||
let mut changed = false;
|
||||
for dest_local in body.local_decls.indices() {
|
||||
for dest_local in body_cache.local_decls.indices() {
|
||||
debug!("considering destination local: {:?}", dest_local);
|
||||
|
||||
let action;
|
||||
|
@ -71,7 +74,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation {
|
|||
}
|
||||
// Conservatively gives up if the dest is an argument,
|
||||
// because there may be uses of the original argument value.
|
||||
if body.local_kind(dest_local) == LocalKind::Arg {
|
||||
if body_cache.local_kind(dest_local) == LocalKind::Arg {
|
||||
debug!(" Can't copy-propagate local: dest {:?} (argument)",
|
||||
dest_local);
|
||||
continue;
|
||||
|
@ -79,7 +82,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation {
|
|||
let dest_place_def = dest_use_info.defs_not_including_drop().next().unwrap();
|
||||
location = dest_place_def.location;
|
||||
|
||||
let basic_block = &body[location.block];
|
||||
let basic_block = &body_cache[location.block];
|
||||
let statement_index = location.statement_index;
|
||||
let statement = match basic_block.statements.get(statement_index) {
|
||||
Some(statement) => statement,
|
||||
|
@ -97,7 +100,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation {
|
|||
let maybe_action = match operand {
|
||||
Operand::Copy(ref src_place) |
|
||||
Operand::Move(ref src_place) => {
|
||||
Action::local_copy(&body, &def_use_analysis, src_place)
|
||||
Action::local_copy(&body_cache, &def_use_analysis, src_place)
|
||||
}
|
||||
Operand::Constant(ref src_constant) => {
|
||||
Action::constant(src_constant)
|
||||
|
@ -127,7 +130,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation {
|
|||
}
|
||||
|
||||
changed =
|
||||
action.perform(body, &def_use_analysis, dest_local, location, tcx) || changed;
|
||||
action.perform(body_cache, &def_use_analysis, dest_local, location, tcx) || changed;
|
||||
// FIXME(pcwalton): Update the use-def chains to delete the instructions instead of
|
||||
// regenerating the chains.
|
||||
break
|
||||
|
@ -242,7 +245,7 @@ impl<'tcx> Action<'tcx> {
|
|||
}
|
||||
|
||||
fn perform(self,
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
def_use_analysis: &DefUseAnalysis,
|
||||
dest_local: Local,
|
||||
location: Location,
|
||||
|
@ -260,21 +263,21 @@ impl<'tcx> Action<'tcx> {
|
|||
src_local);
|
||||
for place_use in &def_use_analysis.local_info(dest_local).defs_and_uses {
|
||||
if place_use.context.is_storage_marker() {
|
||||
body.make_statement_nop(place_use.location)
|
||||
body_cache.make_statement_nop(place_use.location)
|
||||
}
|
||||
}
|
||||
for place_use in &def_use_analysis.local_info(src_local).defs_and_uses {
|
||||
if place_use.context.is_storage_marker() {
|
||||
body.make_statement_nop(place_use.location)
|
||||
body_cache.make_statement_nop(place_use.location)
|
||||
}
|
||||
}
|
||||
|
||||
// Replace all uses of the destination local with the source local.
|
||||
def_use_analysis.replace_all_defs_and_uses_with(dest_local, body, src_local, tcx);
|
||||
def_use_analysis.replace_all_defs_and_uses_with(dest_local, body_cache, src_local, tcx);
|
||||
|
||||
// Finally, zap the now-useless assignment instruction.
|
||||
debug!(" Deleting assignment");
|
||||
body.make_statement_nop(location);
|
||||
body_cache.make_statement_nop(location);
|
||||
|
||||
true
|
||||
}
|
||||
|
@ -288,7 +291,7 @@ impl<'tcx> Action<'tcx> {
|
|||
let dest_local_info = def_use_analysis.local_info(dest_local);
|
||||
for place_use in &dest_local_info.defs_and_uses {
|
||||
if place_use.context.is_storage_marker() {
|
||||
body.make_statement_nop(place_use.location)
|
||||
body_cache.make_statement_nop(place_use.location)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,7 +300,7 @@ impl<'tcx> Action<'tcx> {
|
|||
src_constant,
|
||||
tcx);
|
||||
for dest_place_use in &dest_local_info.defs_and_uses {
|
||||
visitor.visit_location(body, dest_place_use.location)
|
||||
visitor.visit_location(body_cache, dest_place_use.location)
|
||||
}
|
||||
|
||||
// Zap the assignment instruction if we eliminated all the uses. We won't have been
|
||||
|
@ -308,7 +311,7 @@ impl<'tcx> Action<'tcx> {
|
|||
debug!(" {} of {} use(s) replaced; deleting assignment",
|
||||
visitor.uses_replaced,
|
||||
use_count);
|
||||
body.make_statement_nop(location);
|
||||
body_cache.make_statement_nop(location);
|
||||
true
|
||||
} else if visitor.uses_replaced == 0 {
|
||||
debug!(" No uses replaced; not deleting assignment");
|
||||
|
|
|
@ -6,8 +6,8 @@ use crate::util::expand_aggregate;
|
|||
pub struct Deaggregator;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for Deaggregator {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
let (basic_blocks, local_decls) = body_cache.basic_blocks_and_local_decls_mut();
|
||||
let local_decls = &*local_decls;
|
||||
for bb in basic_blocks {
|
||||
bb.expand_statements(|stmt| {
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::fmt;
|
|||
use std::fs::File;
|
||||
use std::io;
|
||||
|
||||
use rustc::mir::Body;
|
||||
use rustc::mir::{Body, BodyCache};
|
||||
use rustc::session::config::{OutputFilenames, OutputType};
|
||||
use rustc::ty::TyCtxt;
|
||||
use crate::transform::{MirPass, MirSource};
|
||||
|
@ -18,7 +18,7 @@ impl<'tcx> MirPass<'tcx> for Marker {
|
|||
Cow::Borrowed(self.0)
|
||||
}
|
||||
|
||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body_cache: &mut BodyCache<'tcx>) {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,17 +21,17 @@ use syntax_pos::Span;
|
|||
pub struct ElaborateDrops;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for ElaborateDrops {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
debug!("elaborate_drops({:?} @ {:?})", src, body.span);
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
debug!("elaborate_drops({:?} @ {:?})", src, body_cache.span);
|
||||
|
||||
let def_id = src.def_id();
|
||||
let param_env = tcx.param_env(src.def_id()).with_reveal_all();
|
||||
let move_data = match MoveData::gather_moves(body, tcx) {
|
||||
let move_data = match MoveData::gather_moves(body_cache, tcx) {
|
||||
Ok(move_data) => move_data,
|
||||
Err(_) => bug!("No `move_errors` should be allowed in MIR borrowck"),
|
||||
};
|
||||
let elaborate_patch = {
|
||||
let body = &*body;
|
||||
let body = &*body_cache;
|
||||
let env = MoveDataParamEnv {
|
||||
move_data,
|
||||
param_env,
|
||||
|
@ -56,7 +56,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
|
|||
patch: MirPatch::new(body),
|
||||
}.elaborate()
|
||||
};
|
||||
elaborate_patch.apply(body);
|
||||
elaborate_patch.apply(body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> {
|
|||
pub struct EraseRegions;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for EraseRegions {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
EraseRegionsVisitor::new(tcx).visit_body(body);
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
EraseRegionsVisitor::new(tcx).visit_body(body_cache);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -378,9 +378,9 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
|
|||
fn make_generator_state_argument_indirect<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
) {
|
||||
let gen_ty = body.local_decls.raw[1].ty;
|
||||
let gen_ty = body_cache.local_decls.raw[1].ty;
|
||||
|
||||
let region = ty::ReFree(ty::FreeRegion {
|
||||
scope: def_id,
|
||||
|
@ -395,14 +395,14 @@ fn make_generator_state_argument_indirect<'tcx>(
|
|||
});
|
||||
|
||||
// Replace the by value generator argument
|
||||
body.local_decls.raw[1].ty = ref_gen_ty;
|
||||
body_cache.local_decls.raw[1].ty = ref_gen_ty;
|
||||
|
||||
// Add a deref to accesses of the generator state
|
||||
DerefArgVisitor { tcx }.visit_body(body);
|
||||
DerefArgVisitor { tcx }.visit_body(body_cache);
|
||||
}
|
||||
|
||||
fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
let ref_gen_ty = body.local_decls.raw[1].ty;
|
||||
fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
let ref_gen_ty = body_cache.local_decls.raw[1].ty;
|
||||
|
||||
let pin_did = tcx.lang_items().pin_type().unwrap();
|
||||
let pin_adt_ref = tcx.adt_def(pin_did);
|
||||
|
@ -410,18 +410,18 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
|
|||
let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs);
|
||||
|
||||
// Replace the by ref generator argument
|
||||
body.local_decls.raw[1].ty = pin_ref_gen_ty;
|
||||
body_cache.local_decls.raw[1].ty = pin_ref_gen_ty;
|
||||
|
||||
// Add the Pin field access to accesses of the generator state
|
||||
PinArgVisitor { ref_gen_ty, tcx }.visit_body(body);
|
||||
PinArgVisitor { ref_gen_ty, tcx }.visit_body(body_cache);
|
||||
}
|
||||
|
||||
fn replace_result_variable<'tcx>(
|
||||
ret_ty: Ty<'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Local {
|
||||
let source_info = source_info(body);
|
||||
let source_info = source_info(body_cache);
|
||||
let new_ret = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: ret_ty,
|
||||
|
@ -431,15 +431,15 @@ fn replace_result_variable<'tcx>(
|
|||
is_block_tail: None,
|
||||
local_info: LocalInfo::Other
|
||||
};
|
||||
let new_ret_local = Local::new(body.local_decls.len());
|
||||
body.local_decls.push(new_ret);
|
||||
body.local_decls.swap(RETURN_PLACE, new_ret_local);
|
||||
let new_ret_local = Local::new(body_cache.local_decls.len());
|
||||
body_cache.local_decls.push(new_ret);
|
||||
body_cache.local_decls.swap(RETURN_PLACE, new_ret_local);
|
||||
|
||||
RenameLocalVisitor {
|
||||
from: RETURN_PLACE,
|
||||
to: new_ret_local,
|
||||
tcx,
|
||||
}.visit_body(body);
|
||||
}.visit_body(body_cache);
|
||||
|
||||
new_ret_local
|
||||
}
|
||||
|
@ -481,12 +481,13 @@ struct LivenessInfo {
|
|||
|
||||
fn locals_live_across_suspend_points(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
body_cache: ReadOnlyBodyCache<'_, 'tcx>,
|
||||
source: MirSource<'tcx>,
|
||||
movable: bool,
|
||||
) -> LivenessInfo {
|
||||
let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
|
||||
let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len());
|
||||
let def_id = source.def_id();
|
||||
let body = body_cache.body();
|
||||
|
||||
// Calculate when MIR locals have live storage. This gives us an upper bound of their
|
||||
// lifetimes.
|
||||
|
@ -498,8 +499,8 @@ fn locals_live_across_suspend_points(
|
|||
|
||||
// Find the MIR locals which do not use StorageLive/StorageDead statements.
|
||||
// The storage of these locals are always live.
|
||||
let mut ignored = StorageIgnored(BitSet::new_filled(body.local_decls.len()));
|
||||
ignored.visit_body(body);
|
||||
let mut ignored = StorageIgnored(BitSet::new_filled(body_cache.local_decls.len()));
|
||||
ignored.visit_body(body_cache);
|
||||
|
||||
// Calculate the MIR locals which have been previously
|
||||
// borrowed (even if they are still active).
|
||||
|
@ -511,16 +512,16 @@ fn locals_live_across_suspend_points(
|
|||
|
||||
// Calculate the MIR locals that we actually need to keep storage around
|
||||
// for.
|
||||
let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_results);
|
||||
let requires_storage_analysis = RequiresStorage::new(body_cache, &borrowed_locals_results);
|
||||
let requires_storage_results =
|
||||
do_dataflow(tcx, body, def_id, &[], &dead_unwinds, requires_storage_analysis,
|
||||
|bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
|
||||
let mut requires_storage_cursor = DataflowResultsCursor::new(&requires_storage_results, body);
|
||||
|
||||
// Calculate the liveness of MIR locals ignoring borrows.
|
||||
let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len());
|
||||
let mut live_locals = liveness::LiveVarSet::new_empty(body_cache.local_decls.len());
|
||||
let mut liveness = liveness::liveness_of_locals(
|
||||
body,
|
||||
body_cache,
|
||||
);
|
||||
liveness::dump_mir(
|
||||
tcx,
|
||||
|
@ -533,7 +534,7 @@ fn locals_live_across_suspend_points(
|
|||
let mut storage_liveness_map = FxHashMap::default();
|
||||
let mut live_locals_at_suspension_points = Vec::new();
|
||||
|
||||
for (block, data) in body.basic_blocks().iter_enumerated() {
|
||||
for (block, data) in body_cache.basic_blocks().iter_enumerated() {
|
||||
if let TerminatorKind::Yield { .. } = data.terminator().kind {
|
||||
let loc = Location {
|
||||
block: block,
|
||||
|
@ -749,7 +750,7 @@ fn compute_layout<'tcx>(
|
|||
upvars: &Vec<Ty<'tcx>>,
|
||||
interior: Ty<'tcx>,
|
||||
movable: bool,
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
) -> (
|
||||
FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
|
||||
GeneratorLayout<'tcx>,
|
||||
|
@ -758,7 +759,7 @@ fn compute_layout<'tcx>(
|
|||
// Use a liveness analysis to compute locals which are live across a suspension point
|
||||
let LivenessInfo {
|
||||
live_locals, live_locals_at_suspension_points, storage_conflicts, storage_liveness
|
||||
} = locals_live_across_suspend_points(tcx, body, source, movable);
|
||||
} = locals_live_across_suspend_points(tcx, body_cache.read_only(), source, movable);
|
||||
|
||||
// Erase regions from the types passed in from typeck so we can compare them with
|
||||
// MIR types
|
||||
|
@ -768,7 +769,7 @@ fn compute_layout<'tcx>(
|
|||
_ => bug!(),
|
||||
};
|
||||
|
||||
for (local, decl) in body.local_decls.iter_enumerated() {
|
||||
for (local, decl) in body_cache.local_decls.iter_enumerated() {
|
||||
// Ignore locals which are internal or not live
|
||||
if !live_locals.contains(local) || decl.internal {
|
||||
continue;
|
||||
|
@ -777,7 +778,7 @@ fn compute_layout<'tcx>(
|
|||
// Sanity check that typeck knows about the type of locals which are
|
||||
// live across a suspension point
|
||||
if !allowed.contains(&decl.ty) && !allowed_upvars.contains(&decl.ty) {
|
||||
span_bug!(body.span,
|
||||
span_bug!(body_cache.span,
|
||||
"Broken MIR: generator contains type {} in MIR, \
|
||||
but typeck only knows about {}",
|
||||
decl.ty,
|
||||
|
@ -790,7 +791,7 @@ fn compute_layout<'tcx>(
|
|||
let mut tys = IndexVec::<GeneratorSavedLocal, _>::new();
|
||||
for (idx, local) in live_locals.iter().enumerate() {
|
||||
locals.push(local);
|
||||
tys.push(body.local_decls[local].ty);
|
||||
tys.push(body_cache.local_decls[local].ty);
|
||||
debug!("generator saved local {:?} => {:?}", GeneratorSavedLocal::from(idx), local);
|
||||
}
|
||||
|
||||
|
@ -828,13 +829,13 @@ fn compute_layout<'tcx>(
|
|||
}
|
||||
|
||||
fn insert_switch<'tcx>(
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
cases: Vec<(usize, BasicBlock)>,
|
||||
transform: &TransformVisitor<'tcx>,
|
||||
default: TerminatorKind<'tcx>,
|
||||
) {
|
||||
let default_block = insert_term_block(body, default);
|
||||
let (assign, discr) = transform.get_discr(body);
|
||||
let default_block = insert_term_block(body_cache, default);
|
||||
let (assign, discr) = transform.get_discr(body_cache);
|
||||
let switch = TerminatorKind::SwitchInt {
|
||||
discr: Operand::Move(discr),
|
||||
switch_ty: transform.discr_ty,
|
||||
|
@ -842,8 +843,8 @@ fn insert_switch<'tcx>(
|
|||
targets: cases.iter().map(|&(_, d)| d).chain(iter::once(default_block)).collect(),
|
||||
};
|
||||
|
||||
let source_info = source_info(body);
|
||||
body.basic_blocks_mut().raw.insert(0, BasicBlockData {
|
||||
let source_info = source_info(body_cache);
|
||||
body_cache.basic_blocks_mut().raw.insert(0, BasicBlockData {
|
||||
statements: vec![assign],
|
||||
terminator: Some(Terminator {
|
||||
source_info,
|
||||
|
@ -852,14 +853,14 @@ fn insert_switch<'tcx>(
|
|||
is_cleanup: false,
|
||||
});
|
||||
|
||||
let blocks = body.basic_blocks_mut().iter_mut();
|
||||
let blocks = body_cache.basic_blocks_mut().iter_mut();
|
||||
|
||||
for target in blocks.flat_map(|b| b.terminator_mut().successors_mut()) {
|
||||
*target = BasicBlock::new(target.index() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut Body<'tcx>) {
|
||||
fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body_cache: &mut BodyCache<'tcx>) {
|
||||
use crate::util::elaborate_drops::{elaborate_drop, Unwind};
|
||||
use crate::util::patch::MirPatch;
|
||||
use crate::shim::DropShimElaborator;
|
||||
|
@ -872,13 +873,13 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut
|
|||
let gen = self_arg();
|
||||
|
||||
let mut elaborator = DropShimElaborator {
|
||||
body: body,
|
||||
patch: MirPatch::new(body),
|
||||
body: body_cache,
|
||||
patch: MirPatch::new(body_cache),
|
||||
tcx,
|
||||
param_env
|
||||
};
|
||||
|
||||
for (block, block_data) in body.basic_blocks().iter_enumerated() {
|
||||
for (block, block_data) in body_cache.basic_blocks().iter_enumerated() {
|
||||
let (target, unwind, source_info) = match block_data.terminator() {
|
||||
Terminator {
|
||||
source_info,
|
||||
|
@ -915,7 +916,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut
|
|||
block,
|
||||
);
|
||||
}
|
||||
elaborator.patch.apply(body);
|
||||
elaborator.patch.apply(body_cache);
|
||||
}
|
||||
|
||||
fn create_generator_drop_shim<'tcx>(
|
||||
|
@ -924,23 +925,23 @@ fn create_generator_drop_shim<'tcx>(
|
|||
def_id: DefId,
|
||||
source: MirSource<'tcx>,
|
||||
gen_ty: Ty<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
drop_clean: BasicBlock,
|
||||
) -> Body<'tcx> {
|
||||
let mut body = body.clone();
|
||||
) -> BodyCache<'tcx> {
|
||||
let mut body_cache = body_cache.clone();
|
||||
|
||||
let source_info = source_info(&body);
|
||||
let source_info = source_info(body_cache.body());
|
||||
|
||||
let mut cases = create_cases(&mut body, transform, |point| point.drop);
|
||||
let mut cases = create_cases(&mut body_cache, transform, |point| point.drop);
|
||||
|
||||
cases.insert(0, (UNRESUMED, drop_clean));
|
||||
|
||||
// The returned state and the poisoned state fall through to the default
|
||||
// case which is just to return
|
||||
|
||||
insert_switch(&mut body, cases, &transform, TerminatorKind::Return);
|
||||
insert_switch(&mut body_cache, cases, &transform, TerminatorKind::Return);
|
||||
|
||||
for block in body.basic_blocks_mut() {
|
||||
for block in body_cache.basic_blocks_mut() {
|
||||
let kind = &mut block.terminator_mut().kind;
|
||||
if let TerminatorKind::GeneratorDrop = *kind {
|
||||
*kind = TerminatorKind::Return;
|
||||
|
@ -948,7 +949,7 @@ fn create_generator_drop_shim<'tcx>(
|
|||
}
|
||||
|
||||
// Replace the return variable
|
||||
body.local_decls[RETURN_PLACE] = LocalDecl {
|
||||
body_cache.local_decls[RETURN_PLACE] = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: tcx.mk_unit(),
|
||||
user_ty: UserTypeProjections::none(),
|
||||
|
@ -958,10 +959,10 @@ fn create_generator_drop_shim<'tcx>(
|
|||
local_info: LocalInfo::Other
|
||||
};
|
||||
|
||||
make_generator_state_argument_indirect(tcx, def_id, &mut body);
|
||||
make_generator_state_argument_indirect(tcx, def_id, &mut body_cache);
|
||||
|
||||
// Change the generator argument from &mut to *mut
|
||||
body.local_decls[self_arg()] = LocalDecl {
|
||||
body_cache.local_decls[self_arg()] = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: tcx.mk_ptr(ty::TypeAndMut {
|
||||
ty: gen_ty,
|
||||
|
@ -975,27 +976,27 @@ fn create_generator_drop_shim<'tcx>(
|
|||
};
|
||||
if tcx.sess.opts.debugging_opts.mir_emit_retag {
|
||||
// Alias tracking must know we changed the type
|
||||
body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
|
||||
body_cache.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
|
||||
source_info,
|
||||
kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())),
|
||||
})
|
||||
}
|
||||
|
||||
no_landing_pads(tcx, &mut body);
|
||||
no_landing_pads(tcx, &mut body_cache);
|
||||
|
||||
// Make sure we remove dead blocks to remove
|
||||
// unrelated code from the resume part of the function
|
||||
simplify::remove_dead_blocks(&mut body);
|
||||
simplify::remove_dead_blocks(&mut body_cache);
|
||||
|
||||
dump_mir(tcx, None, "generator_drop", &0, source, &mut body, |_, _| Ok(()) );
|
||||
dump_mir(tcx, None, "generator_drop", &0, source, &mut body_cache, |_, _| Ok(()) );
|
||||
|
||||
body
|
||||
body_cache
|
||||
}
|
||||
|
||||
fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
|
||||
let term_block = BasicBlock::new(body.basic_blocks().len());
|
||||
let source_info = source_info(body);
|
||||
body.basic_blocks_mut().push(BasicBlockData {
|
||||
fn insert_term_block<'tcx>(body_cache: &mut BodyCache<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
|
||||
let term_block = BasicBlock::new(body_cache.basic_blocks().len());
|
||||
let source_info = source_info(body_cache);
|
||||
body_cache.basic_blocks_mut().push(BasicBlockData {
|
||||
statements: Vec::new(),
|
||||
terminator: Some(Terminator {
|
||||
source_info,
|
||||
|
@ -1008,13 +1009,13 @@ fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) ->
|
|||
|
||||
fn insert_panic_block<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
message: AssertMessage<'tcx>,
|
||||
) -> BasicBlock {
|
||||
let assert_block = BasicBlock::new(body.basic_blocks().len());
|
||||
let assert_block = BasicBlock::new(body_cache.basic_blocks().len());
|
||||
let term = TerminatorKind::Assert {
|
||||
cond: Operand::Constant(box Constant {
|
||||
span: body.span,
|
||||
span: body_cache.span,
|
||||
user_ty: None,
|
||||
literal: ty::Const::from_bool(tcx, false),
|
||||
}),
|
||||
|
@ -1024,8 +1025,8 @@ fn insert_panic_block<'tcx>(
|
|||
cleanup: None,
|
||||
};
|
||||
|
||||
let source_info = source_info(body);
|
||||
body.basic_blocks_mut().push(BasicBlockData {
|
||||
let source_info = source_info(body_cache);
|
||||
body_cache.basic_blocks_mut().push(BasicBlockData {
|
||||
statements: Vec::new(),
|
||||
terminator: Some(Terminator {
|
||||
source_info,
|
||||
|
@ -1042,10 +1043,10 @@ fn create_generator_resume_function<'tcx>(
|
|||
transform: TransformVisitor<'tcx>,
|
||||
def_id: DefId,
|
||||
source: MirSource<'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
) {
|
||||
// Poison the generator when it unwinds
|
||||
for block in body.basic_blocks_mut() {
|
||||
for block in body_cache.basic_blocks_mut() {
|
||||
let source_info = block.terminator().source_info;
|
||||
if let &TerminatorKind::Resume = &block.terminator().kind {
|
||||
block.statements.push(
|
||||
|
@ -1053,7 +1054,7 @@ fn create_generator_resume_function<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
let mut cases = create_cases(body, &transform, |point| Some(point.resume));
|
||||
let mut cases = create_cases(body_cache, &transform, |point| Some(point.resume));
|
||||
|
||||
use rustc::mir::interpret::PanicInfo::{
|
||||
ResumedAfterPanic,
|
||||
|
@ -1067,25 +1068,25 @@ fn create_generator_resume_function<'tcx>(
|
|||
let generator_kind = body.generator_kind.unwrap();
|
||||
cases.insert(1, (RETURNED, insert_panic_block(
|
||||
tcx,
|
||||
body,
|
||||
body_cache,
|
||||
ResumedAfterReturn(generator_kind))));
|
||||
cases.insert(2, (POISONED, insert_panic_block(
|
||||
tcx,
|
||||
body,
|
||||
body_cache,
|
||||
ResumedAfterPanic(generator_kind))));
|
||||
|
||||
insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
|
||||
insert_switch(body_cache, cases, &transform, TerminatorKind::Unreachable);
|
||||
|
||||
make_generator_state_argument_indirect(tcx, def_id, body);
|
||||
make_generator_state_argument_pinned(tcx, body);
|
||||
make_generator_state_argument_indirect(tcx, def_id, body_cache);
|
||||
make_generator_state_argument_pinned(tcx, body_cache);
|
||||
|
||||
no_landing_pads(tcx, body);
|
||||
no_landing_pads(tcx, body_cache);
|
||||
|
||||
// Make sure we remove dead blocks to remove
|
||||
// unrelated code from the drop part of the function
|
||||
simplify::remove_dead_blocks(body);
|
||||
simplify::remove_dead_blocks(body_cache);
|
||||
|
||||
dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(()) );
|
||||
dump_mir(tcx, None, "generator_resume", &0, source, body_cache, |_, _| Ok(()) );
|
||||
}
|
||||
|
||||
fn source_info(body: &Body<'_>) -> SourceInfo {
|
||||
|
@ -1095,18 +1096,18 @@ fn source_info(body: &Body<'_>) -> SourceInfo {
|
|||
}
|
||||
}
|
||||
|
||||
fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
|
||||
let return_block = insert_term_block(body, TerminatorKind::Return);
|
||||
fn insert_clean_drop(body_cache: &mut BodyCache<'_>) -> BasicBlock {
|
||||
let return_block = insert_term_block(body_cache, TerminatorKind::Return);
|
||||
|
||||
// Create a block to destroy an unresumed generators. This can only destroy upvars.
|
||||
let drop_clean = BasicBlock::new(body.basic_blocks().len());
|
||||
let drop_clean = BasicBlock::new(body_cache.basic_blocks().len());
|
||||
let term = TerminatorKind::Drop {
|
||||
location: Place::from(self_arg()),
|
||||
target: return_block,
|
||||
unwind: None,
|
||||
};
|
||||
let source_info = source_info(body);
|
||||
body.basic_blocks_mut().push(BasicBlockData {
|
||||
let source_info = source_info(body_cache);
|
||||
body_cache.basic_blocks_mut().push(BasicBlockData {
|
||||
statements: Vec::new(),
|
||||
terminator: Some(Terminator {
|
||||
source_info,
|
||||
|
@ -1119,23 +1120,23 @@ fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
|
|||
}
|
||||
|
||||
fn create_cases<'tcx, F>(
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
transform: &TransformVisitor<'tcx>,
|
||||
target: F,
|
||||
) -> Vec<(usize, BasicBlock)>
|
||||
where
|
||||
F: Fn(&SuspensionPoint) -> Option<BasicBlock>,
|
||||
{
|
||||
let source_info = source_info(body);
|
||||
let source_info = source_info(body_cache);
|
||||
|
||||
transform.suspension_points.iter().filter_map(|point| {
|
||||
// Find the target for this suspension point, if applicable
|
||||
target(point).map(|target| {
|
||||
let block = BasicBlock::new(body.basic_blocks().len());
|
||||
let block = BasicBlock::new(body_cache.basic_blocks().len());
|
||||
let mut statements = Vec::new();
|
||||
|
||||
// Create StorageLive instructions for locals with live storage
|
||||
for i in 0..(body.local_decls.len()) {
|
||||
for i in 0..(body_cache.local_decls.len()) {
|
||||
let l = Local::new(i);
|
||||
if point.storage_liveness.contains(l) && !transform.remap.contains_key(&l) {
|
||||
statements.push(Statement {
|
||||
|
@ -1146,7 +1147,7 @@ where
|
|||
}
|
||||
|
||||
// Then jump to the real target
|
||||
body.basic_blocks_mut().push(BasicBlockData {
|
||||
body_cache.basic_blocks_mut().push(BasicBlockData {
|
||||
statements,
|
||||
terminator: Some(Terminator {
|
||||
source_info,
|
||||
|
@ -1163,20 +1164,20 @@ where
|
|||
}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for StateTransform {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
let yield_ty = if let Some(yield_ty) = body.yield_ty {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
let yield_ty = if let Some(yield_ty) = body_cache.yield_ty {
|
||||
yield_ty
|
||||
} else {
|
||||
// This only applies to generators
|
||||
return
|
||||
};
|
||||
|
||||
assert!(body.generator_drop.is_none());
|
||||
assert!(body_cache.generator_drop.is_none());
|
||||
|
||||
let def_id = source.def_id();
|
||||
|
||||
// The first argument is the generator type passed by value
|
||||
let gen_ty = body.local_decls.raw[1].ty;
|
||||
let gen_ty = body_cache.local_decls.raw[1].ty;
|
||||
|
||||
// Get the interior types and substs which typeck computed
|
||||
let (upvars, interior, discr_ty, movable) = match gen_ty.kind {
|
||||
|
@ -1195,13 +1196,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
|||
let state_adt_ref = tcx.adt_def(state_did);
|
||||
let state_substs = tcx.intern_substs(&[
|
||||
yield_ty.into(),
|
||||
body.return_ty().into(),
|
||||
body_cache.return_ty().into(),
|
||||
]);
|
||||
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
|
||||
|
||||
// We rename RETURN_PLACE which has type mir.return_ty to new_ret_local
|
||||
// RETURN_PLACE then is a fresh unused local with type ret_ty.
|
||||
let new_ret_local = replace_result_variable(ret_ty, body, tcx);
|
||||
let new_ret_local = replace_result_variable(ret_ty, body_cache, tcx);
|
||||
|
||||
// Extract locals which are live across suspension point into `layout`
|
||||
// `remap` gives a mapping from local indices onto generator struct indices
|
||||
|
@ -1212,7 +1213,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
|||
&upvars,
|
||||
interior,
|
||||
movable,
|
||||
body);
|
||||
body_cache);
|
||||
|
||||
// Run the transformation which converts Places from Local to generator struct
|
||||
// accesses for locals in `remap`.
|
||||
|
@ -1228,40 +1229,40 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
|||
new_ret_local,
|
||||
discr_ty,
|
||||
};
|
||||
transform.visit_body(body);
|
||||
transform.visit_body(body_cache);
|
||||
|
||||
// Update our MIR struct to reflect the changed we've made
|
||||
body.yield_ty = None;
|
||||
body.arg_count = 1;
|
||||
body.spread_arg = None;
|
||||
body.generator_layout = Some(layout);
|
||||
body_cache.yield_ty = None;
|
||||
body_cache.arg_count = 1;
|
||||
body_cache.spread_arg = None;
|
||||
body_cache.generator_layout = Some(layout);
|
||||
|
||||
// Insert `drop(generator_struct)` which is used to drop upvars for generators in
|
||||
// the unresumed state.
|
||||
// This is expanded to a drop ladder in `elaborate_generator_drops`.
|
||||
let drop_clean = insert_clean_drop(body);
|
||||
let drop_clean = insert_clean_drop(body_cache);
|
||||
|
||||
dump_mir(tcx, None, "generator_pre-elab", &0, source, body, |_, _| Ok(()) );
|
||||
dump_mir(tcx, None, "generator_pre-elab", &0, source, body_cache, |_, _| Ok(()) );
|
||||
|
||||
// Expand `drop(generator_struct)` to a drop ladder which destroys upvars.
|
||||
// If any upvars are moved out of, drop elaboration will handle upvar destruction.
|
||||
// However we need to also elaborate the code generated by `insert_clean_drop`.
|
||||
elaborate_generator_drops(tcx, def_id, body);
|
||||
elaborate_generator_drops(tcx, def_id, body_cache);
|
||||
|
||||
dump_mir(tcx, None, "generator_post-transform", &0, source, body, |_, _| Ok(()) );
|
||||
dump_mir(tcx, None, "generator_post-transform", &0, source, body_cache, |_, _| Ok(()) );
|
||||
|
||||
// Create a copy of our MIR and use it to create the drop shim for the generator
|
||||
let drop_shim = create_generator_drop_shim(tcx,
|
||||
&transform,
|
||||
def_id,
|
||||
source,
|
||||
gen_ty,
|
||||
&body,
|
||||
drop_clean);
|
||||
&transform,
|
||||
def_id,
|
||||
source,
|
||||
gen_ty,
|
||||
body_cache,
|
||||
drop_clean);
|
||||
|
||||
body.generator_drop = Some(box drop_shim);
|
||||
body_cache.generator_drop = Some(box drop_shim);
|
||||
|
||||
// Create the Generator::resume function
|
||||
create_generator_resume_function(tcx, transform, def_id, source, body);
|
||||
create_generator_resume_function(tcx, transform, def_id, source, body_cache);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,9 +38,9 @@ struct CallSite<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for Inline {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
|
||||
Inliner { tcx, source }.run_pass(body);
|
||||
Inliner { tcx, source }.run_pass(body_cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ struct Inliner<'tcx> {
|
|||
}
|
||||
|
||||
impl Inliner<'tcx> {
|
||||
fn run_pass(&self, caller_body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, caller_body_cache: &mut BodyCache<'tcx>) {
|
||||
// Keep a queue of callsites to try inlining on. We take
|
||||
// advantage of the fact that queries detect cycles here to
|
||||
// allow us to try and fetch the fully optimized MIR of a
|
||||
|
@ -73,11 +73,11 @@ impl Inliner<'tcx> {
|
|||
if self.tcx.hir().body_owner_kind(id).is_fn_or_closure()
|
||||
&& self.source.promoted.is_none()
|
||||
{
|
||||
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() {
|
||||
for (bb, bb_data) in caller_body_cache.basic_blocks().iter_enumerated() {
|
||||
if let Some(callsite) = self.get_valid_function_call(bb,
|
||||
bb_data,
|
||||
caller_body,
|
||||
param_env) {
|
||||
bb_data,
|
||||
caller_body_cache,
|
||||
param_env) {
|
||||
callsites.push_back(callsite);
|
||||
}
|
||||
}
|
||||
|
@ -127,19 +127,19 @@ impl Inliner<'tcx> {
|
|||
continue;
|
||||
};
|
||||
|
||||
let start = caller_body.basic_blocks().len();
|
||||
let start = caller_body_cache.basic_blocks().len();
|
||||
debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body);
|
||||
if !self.inline_call(callsite, caller_body, callee_body) {
|
||||
if !self.inline_call(callsite, caller_body_cache, callee_body) {
|
||||
debug!("attempting to inline callsite {:?} - failure", callsite);
|
||||
continue;
|
||||
}
|
||||
debug!("attempting to inline callsite {:?} - success", callsite);
|
||||
|
||||
// Add callsites from inlined function
|
||||
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated().skip(start) {
|
||||
for (bb, bb_data) in caller_body_cache.basic_blocks().iter_enumerated().skip(start) {
|
||||
if let Some(new_callsite) = self.get_valid_function_call(bb,
|
||||
bb_data,
|
||||
caller_body,
|
||||
caller_body_cache,
|
||||
param_env) {
|
||||
// Don't inline the same function multiple times.
|
||||
if callsite.callee != new_callsite.callee {
|
||||
|
@ -160,8 +160,8 @@ impl Inliner<'tcx> {
|
|||
// Simplify if we inlined anything.
|
||||
if changed {
|
||||
debug!("running simplify cfg on {:?}", self.source);
|
||||
CfgSimplifier::new(caller_body).simplify();
|
||||
remove_dead_blocks(caller_body);
|
||||
CfgSimplifier::new(caller_body_cache).simplify();
|
||||
remove_dead_blocks(caller_body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,23 +377,23 @@ impl Inliner<'tcx> {
|
|||
|
||||
fn inline_call(&self,
|
||||
callsite: CallSite<'tcx>,
|
||||
caller_body: &mut Body<'tcx>,
|
||||
mut callee_body: Body<'tcx>) -> bool {
|
||||
caller_body: &mut BodyCache<'tcx>,
|
||||
mut callee_body_cache: BodyCache<'tcx>) -> bool {
|
||||
let terminator = caller_body[callsite.bb].terminator.take().unwrap();
|
||||
match terminator.kind {
|
||||
// FIXME: Handle inlining of diverging calls
|
||||
TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
|
||||
debug!("inlined {:?} into {:?}", callsite.callee, self.source);
|
||||
|
||||
let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len());
|
||||
let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len());
|
||||
let mut local_map = IndexVec::with_capacity(callee_body_cache.local_decls.len());
|
||||
let mut scope_map = IndexVec::with_capacity(callee_body_cache.source_scopes.len());
|
||||
|
||||
for mut scope in callee_body.source_scopes.iter().cloned() {
|
||||
for mut scope in callee_body_cache.source_scopes.iter().cloned() {
|
||||
if scope.parent_scope.is_none() {
|
||||
scope.parent_scope = Some(callsite.location.scope);
|
||||
// FIXME(eddyb) is this really needed?
|
||||
// (also note that it's always overwritten below)
|
||||
scope.span = callee_body.span;
|
||||
scope.span = callee_body_cache.span;
|
||||
}
|
||||
|
||||
// FIXME(eddyb) this doesn't seem right at all.
|
||||
|
@ -405,8 +405,8 @@ impl Inliner<'tcx> {
|
|||
scope_map.push(idx);
|
||||
}
|
||||
|
||||
for loc in callee_body.vars_and_temps_iter() {
|
||||
let mut local = callee_body.local_decls[loc].clone();
|
||||
for loc in callee_body_cache.vars_and_temps_iter() {
|
||||
let mut local = callee_body_cache.local_decls[loc].clone();
|
||||
|
||||
local.source_info.scope =
|
||||
scope_map[local.source_info.scope];
|
||||
|
@ -445,7 +445,7 @@ impl Inliner<'tcx> {
|
|||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||
destination.0);
|
||||
|
||||
let ty = dest.ty(caller_body, self.tcx);
|
||||
let ty = dest.ty(caller_body.body(), self.tcx);
|
||||
|
||||
let temp = LocalDecl::new_temp(ty, callsite.location.span);
|
||||
|
||||
|
@ -486,7 +486,7 @@ impl Inliner<'tcx> {
|
|||
caller_body.var_debug_info.push(var_debug_info);
|
||||
}
|
||||
|
||||
for (bb, mut block) in callee_body.basic_blocks_mut().drain_enumerated(..) {
|
||||
for (bb, mut block) in callee_body_cache.basic_blocks_mut().drain_enumerated(..) {
|
||||
integrator.visit_basic_block_data(bb, &mut block);
|
||||
caller_body.basic_blocks_mut().push(block);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
//! Performs various peephole optimizations.
|
||||
|
||||
use rustc::mir::{
|
||||
Constant, Location, Place, PlaceBase, PlaceRef, Body, Operand, ProjectionElem, Rvalue, Local
|
||||
Constant, Location, Place, PlaceBase, PlaceRef, Body, BodyCache, Operand, ProjectionElem,
|
||||
Rvalue, Local
|
||||
};
|
||||
use rustc::mir::visit::{MutVisitor, Visitor};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
|
@ -13,7 +14,7 @@ use crate::transform::{MirPass, MirSource};
|
|||
pub struct InstCombine;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for InstCombine {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
// We only run when optimizing MIR (at any level).
|
||||
if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
|
||||
return
|
||||
|
@ -23,13 +24,13 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
|
|||
// read-only so that we can do global analyses on the MIR in the process (e.g.
|
||||
// `Place::ty()`).
|
||||
let optimizations = {
|
||||
let mut optimization_finder = OptimizationFinder::new(body, tcx);
|
||||
optimization_finder.visit_body(body);
|
||||
let mut optimization_finder = OptimizationFinder::new(body_cache, tcx);
|
||||
optimization_finder.visit_body(body_cache.read_only());
|
||||
optimization_finder.optimizations
|
||||
};
|
||||
|
||||
// Then carry out those optimizations.
|
||||
MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body);
|
||||
MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{build, shim};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc::mir::{Body, MirPhase, Promoted, ConstQualifs};
|
||||
use rustc::mir::{BodyCache, MirPhase, Promoted, ConstQualifs};
|
||||
use rustc::ty::{TyCtxt, InstanceDef, TypeFoldable};
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::steal::Steal;
|
||||
|
@ -97,7 +97,7 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet {
|
|||
tcx.arena.alloc(set)
|
||||
}
|
||||
|
||||
fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<Body<'_>> {
|
||||
fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyCache<'_>> {
|
||||
let mir = build::mir_build(tcx, def_id);
|
||||
tcx.alloc_steal_mir(mir)
|
||||
}
|
||||
|
@ -144,12 +144,12 @@ pub trait MirPass<'tcx> {
|
|||
default_name::<Self>()
|
||||
}
|
||||
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>);
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>);
|
||||
}
|
||||
|
||||
pub fn run_passes(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
body: &mut BodyCache<'tcx>,
|
||||
instance: InstanceDef<'tcx>,
|
||||
promoted: Option<Promoted>,
|
||||
mir_phase: MirPhase,
|
||||
|
@ -220,47 +220,47 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs {
|
|||
validator.qualifs_in_return_place().into()
|
||||
}
|
||||
|
||||
fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<Body<'_>> {
|
||||
fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyCache<'_>> {
|
||||
// Unsafety check uses the raw mir, so make sure it is run
|
||||
let _ = tcx.unsafety_check_result(def_id);
|
||||
|
||||
let mut body = tcx.mir_built(def_id).steal();
|
||||
run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Const, &[
|
||||
let mut body_cache = tcx.mir_built(def_id).steal();
|
||||
run_passes(tcx, &mut body_cache, InstanceDef::Item(def_id), None, MirPhase::Const, &[
|
||||
// What we need to do constant evaluation.
|
||||
&simplify::SimplifyCfg::new("initial"),
|
||||
&rustc_peek::SanityCheck,
|
||||
&uniform_array_move_out::UniformArrayMoveOut,
|
||||
]);
|
||||
tcx.alloc_steal_mir(body)
|
||||
tcx.alloc_steal_mir(body_cache)
|
||||
}
|
||||
|
||||
fn mir_validated(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
) -> (&'tcx Steal<Body<'tcx>>, &'tcx Steal<IndexVec<Promoted, Body<'tcx>>>) {
|
||||
) -> (&'tcx Steal<BodyCache<'tcx>>, &'tcx Steal<IndexVec<Promoted, BodyCache<'tcx>>>) {
|
||||
// Ensure that we compute the `mir_const_qualif` for constants at
|
||||
// this point, before we steal the mir-const result.
|
||||
let _ = tcx.mir_const_qualif(def_id);
|
||||
|
||||
let mut body = tcx.mir_const(def_id).steal();
|
||||
let mut body_cache = tcx.mir_const(def_id).steal();
|
||||
let promote_pass = promote_consts::PromoteTemps::default();
|
||||
run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Validated, &[
|
||||
run_passes(tcx, &mut body_cache, InstanceDef::Item(def_id), None, MirPhase::Validated, &[
|
||||
// What we need to run borrowck etc.
|
||||
&promote_pass,
|
||||
&simplify::SimplifyCfg::new("qualify-consts"),
|
||||
]);
|
||||
|
||||
let promoted = promote_pass.promoted_fragments.into_inner();
|
||||
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
|
||||
(tcx.alloc_steal_mir(body_cache), tcx.alloc_steal_promoted(promoted))
|
||||
}
|
||||
|
||||
fn run_optimization_passes<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
def_id: DefId,
|
||||
promoted: Option<Promoted>,
|
||||
) {
|
||||
run_passes(tcx, body, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[
|
||||
run_passes(tcx, body_cache, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[
|
||||
// Remove all things only needed by analysis
|
||||
&no_landing_pads::NoLandingPads::new(tcx),
|
||||
&simplify_branches::SimplifyBranches::new("initial"),
|
||||
|
@ -318,7 +318,7 @@ fn run_optimization_passes<'tcx>(
|
|||
]);
|
||||
}
|
||||
|
||||
fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> {
|
||||
fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> {
|
||||
if tcx.is_constructor(def_id) {
|
||||
// There's no reason to run all of the MIR passes on constructors when
|
||||
// we can just output the MIR we want directly. This also saves const
|
||||
|
@ -332,12 +332,12 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> {
|
|||
tcx.ensure().mir_borrowck(def_id);
|
||||
|
||||
let (body, _) = tcx.mir_validated(def_id);
|
||||
let mut body = body.steal();
|
||||
run_optimization_passes(tcx, &mut body, def_id, None);
|
||||
tcx.arena.alloc(body)
|
||||
let mut body_cache = body.steal();
|
||||
run_optimization_passes(tcx, &mut body_cache, def_id, None);
|
||||
tcx.arena.alloc(body_cache)
|
||||
}
|
||||
|
||||
fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
|
||||
fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec<Promoted, BodyCache<'tcx>> {
|
||||
if tcx.is_constructor(def_id) {
|
||||
return tcx.intern_promoted(IndexVec::new());
|
||||
}
|
||||
|
@ -346,8 +346,8 @@ fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec<Promot
|
|||
let (_, promoted) = tcx.mir_validated(def_id);
|
||||
let mut promoted = promoted.steal();
|
||||
|
||||
for (p, mut body) in promoted.iter_enumerated_mut() {
|
||||
run_optimization_passes(tcx, &mut body, def_id, Some(p));
|
||||
for (p, mut body_cache) in promoted.iter_enumerated_mut() {
|
||||
run_optimization_passes(tcx, &mut body_cache, def_id, Some(p));
|
||||
}
|
||||
|
||||
tcx.intern_promoted(promoted)
|
||||
|
|
|
@ -17,14 +17,14 @@ impl<'tcx> NoLandingPads<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
no_landing_pads(tcx, body)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
if tcx.sess.no_landing_pads() {
|
||||
NoLandingPads::new(tcx).visit_body(body);
|
||||
NoLandingPads::new(tcx).visit_body(body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -770,8 +770,8 @@ pub fn validate_candidates(
|
|||
|
||||
struct Promoter<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
source: &'a mut Body<'tcx>,
|
||||
promoted: Body<'tcx>,
|
||||
source_cache: &'a mut BodyCache<'tcx>,
|
||||
promoted_cache: BodyCache<'tcx>,
|
||||
temps: &'a mut IndexVec<Local, TempState>,
|
||||
|
||||
/// If true, all nested temps are also kept in the
|
||||
|
@ -781,8 +781,8 @@ struct Promoter<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
fn new_block(&mut self) -> BasicBlock {
|
||||
let span = self.promoted.span;
|
||||
self.promoted.basic_blocks_mut().push(BasicBlockData {
|
||||
let span = self.promoted_cache.span;
|
||||
self.promoted_cache.basic_blocks_mut().push(BasicBlockData {
|
||||
statements: vec![],
|
||||
terminator: Some(Terminator {
|
||||
source_info: SourceInfo {
|
||||
|
@ -796,8 +796,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) {
|
||||
let last = self.promoted.basic_blocks().last().unwrap();
|
||||
let data = &mut self.promoted[last];
|
||||
let last = self.promoted_cache.basic_blocks().last().unwrap();
|
||||
let data = &mut self.promoted_cache[last];
|
||||
data.statements.push(Statement {
|
||||
source_info: SourceInfo {
|
||||
span,
|
||||
|
@ -808,7 +808,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn is_temp_kind(&self, local: Local) -> bool {
|
||||
self.source.local_kind(local) == LocalKind::Temp
|
||||
self.source_cache.local_kind(local) == LocalKind::Temp
|
||||
}
|
||||
|
||||
/// Copies the initialization of this temp to the
|
||||
|
@ -823,7 +823,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
location
|
||||
}
|
||||
state => {
|
||||
span_bug!(self.promoted.span, "{:?} not promotable: {:?}",
|
||||
span_bug!(self.promoted_cache.span, "{:?} not promotable: {:?}",
|
||||
temp, state);
|
||||
}
|
||||
};
|
||||
|
@ -831,10 +831,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
self.temps[temp] = TempState::PromotedOut;
|
||||
}
|
||||
|
||||
let num_stmts = self.source[loc.block].statements.len();
|
||||
let new_temp = self.promoted.local_decls.push(
|
||||
LocalDecl::new_temp(self.source.local_decls[temp].ty,
|
||||
self.source.local_decls[temp].source_info.span));
|
||||
let num_stmts = self.source_cacje[loc.block].statements.len();
|
||||
let new_temp = self.promoted_cache.local_decls.push(
|
||||
LocalDecl::new_temp(self.source_cache.local_decls[temp].ty,
|
||||
self.source_cache.local_decls[temp].source_info.span));
|
||||
|
||||
debug!("promote({:?} @ {:?}/{:?}, {:?})",
|
||||
temp, loc, num_stmts, self.keep_original);
|
||||
|
@ -843,7 +843,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
// or duplicate it, depending on keep_original.
|
||||
if loc.statement_index < num_stmts {
|
||||
let (mut rvalue, source_info) = {
|
||||
let statement = &mut self.source[loc.block].statements[loc.statement_index];
|
||||
let statement = &mut self.source_cache[loc.block].statements[loc.statement_index];
|
||||
let rhs = match statement.kind {
|
||||
StatementKind::Assign(box(_, ref mut rhs)) => rhs,
|
||||
_ => {
|
||||
|
@ -864,9 +864,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
self.assign(new_temp, rvalue, source_info.span);
|
||||
} else {
|
||||
let terminator = if self.keep_original {
|
||||
self.source[loc.block].terminator().clone()
|
||||
self.source_cache[loc.block].terminator().clone()
|
||||
} else {
|
||||
let terminator = self.source[loc.block].terminator_mut();
|
||||
let terminator = self.source_cache[loc.block].terminator_mut();
|
||||
let target = match terminator.kind {
|
||||
TerminatorKind::Call { destination: Some((_, target)), .. } => target,
|
||||
ref kind => {
|
||||
|
@ -888,10 +888,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
self.visit_operand(arg, loc);
|
||||
}
|
||||
|
||||
let last = self.promoted.basic_blocks().last().unwrap();
|
||||
let last = self.promoted_cache.basic_blocks().last().unwrap();
|
||||
let new_target = self.new_block();
|
||||
|
||||
*self.promoted[last].terminator_mut() = Terminator {
|
||||
*self.promoted_cache[last].terminator_mut() = Terminator {
|
||||
kind: TerminatorKind::Call {
|
||||
func,
|
||||
args,
|
||||
|
@ -919,9 +919,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
def_id: DefId,
|
||||
candidate: Candidate,
|
||||
next_promoted_id: usize,
|
||||
) -> Option<Body<'tcx>> {
|
||||
) -> Option<BodyCache<'tcx>> {
|
||||
let mut operand = {
|
||||
let promoted = &mut self.promoted;
|
||||
let promoted = &mut self.promoted_cache;
|
||||
let promoted_id = Promoted::new(next_promoted_id);
|
||||
let tcx = self.tcx;
|
||||
let mut promoted_place = |ty, span| {
|
||||
|
@ -940,7 +940,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
projection: List::empty(),
|
||||
}
|
||||
};
|
||||
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
|
||||
let (blocks, local_decls) = self.source_cache.basic_blocks_and_local_decls_mut();
|
||||
match candidate {
|
||||
Candidate::Ref(loc) => {
|
||||
let ref mut statement = blocks[loc.block].statements[loc.statement_index];
|
||||
|
@ -1004,9 +1004,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
statement_index: usize::MAX
|
||||
});
|
||||
|
||||
let span = self.promoted.span;
|
||||
let span = self.promoted_cache.span;
|
||||
self.assign(RETURN_PLACE, Rvalue::Use(operand), span);
|
||||
Some(self.promoted)
|
||||
Some(self.promoted_cache)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1040,11 +1040,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
|
|||
|
||||
pub fn promote_candidates<'tcx>(
|
||||
def_id: DefId,
|
||||
body: &mut Body<'tcx>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mut temps: IndexVec<Local, TempState>,
|
||||
candidates: Vec<Candidate>,
|
||||
) -> IndexVec<Promoted, Body<'tcx>> {
|
||||
) -> IndexVec<Promoted, BodyCache<'tcx>> {
|
||||
// Visit candidates in reverse, in case they're nested.
|
||||
debug!("promote_candidates({:?})", candidates);
|
||||
|
||||
|
@ -1054,7 +1054,7 @@ pub fn promote_candidates<'tcx>(
|
|||
match candidate {
|
||||
Candidate::Repeat(Location { block, statement_index }) |
|
||||
Candidate::Ref(Location { block, statement_index }) => {
|
||||
match &body[block].statements[statement_index].kind {
|
||||
match &body_cache[block].statements[statement_index].kind {
|
||||
StatementKind::Assign(box(place, _)) => {
|
||||
if let Some(local) = place.as_local() {
|
||||
if temps[local] == TempState::PromotedOut {
|
||||
|
@ -1072,25 +1072,26 @@ pub fn promote_candidates<'tcx>(
|
|||
|
||||
// Declare return place local so that `mir::Body::new` doesn't complain.
|
||||
let initial_locals = iter::once(
|
||||
LocalDecl::new_return_place(tcx.types.never, body.span)
|
||||
LocalDecl::new_return_place(tcx.types.never, body_cache.span)
|
||||
).collect();
|
||||
|
||||
let promoter = Promoter {
|
||||
promoted: Body::new(
|
||||
promoted_cache: BodyCache::new(Body::new(
|
||||
IndexVec::new(),
|
||||
// FIXME: maybe try to filter this to avoid blowing up
|
||||
// memory usage?
|
||||
body.source_scopes.clone(),
|
||||
body_cache.source_scopes.clone(),
|
||||
body_cache.source_scope_local_data.clone(),
|
||||
initial_locals,
|
||||
IndexVec::new(),
|
||||
0,
|
||||
vec![],
|
||||
body.span,
|
||||
body_cache.span,
|
||||
vec![],
|
||||
body.generator_kind,
|
||||
),
|
||||
body_cache.generator_kind,
|
||||
)),
|
||||
tcx,
|
||||
source: body,
|
||||
source_cache: body_cache,
|
||||
temps: &mut temps,
|
||||
keep_original: false
|
||||
};
|
||||
|
@ -1103,7 +1104,7 @@ pub fn promote_candidates<'tcx>(
|
|||
|
||||
// Eliminate assignments to, and drops of promoted temps.
|
||||
let promoted = |index: Local| temps[index] == TempState::PromotedOut;
|
||||
for block in body.basic_blocks_mut() {
|
||||
for block in body_cache.basic_blocks_mut() {
|
||||
block.statements.retain(|statement| {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box(place, _)) => {
|
||||
|
|
|
@ -9,18 +9,18 @@ use crate::util::patch::MirPatch;
|
|||
/// code for these.
|
||||
pub struct RemoveNoopLandingPads;
|
||||
|
||||
pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
if tcx.sess.no_landing_pads() {
|
||||
return
|
||||
}
|
||||
debug!("remove_noop_landing_pads({:?})", body);
|
||||
debug!("remove_noop_landing_pads({:?})", body_cache.body());
|
||||
|
||||
RemoveNoopLandingPads.remove_nop_landing_pads(body)
|
||||
RemoveNoopLandingPads.remove_nop_landing_pads(body_cache)
|
||||
}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
remove_noop_landing_pads(tcx, body);
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
remove_noop_landing_pads(tcx, body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,26 +84,26 @@ impl RemoveNoopLandingPads {
|
|||
}
|
||||
}
|
||||
|
||||
fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
|
||||
fn remove_nop_landing_pads(&self, body_cache: &mut BodyCache<'_>) {
|
||||
// make sure there's a single resume block
|
||||
let resume_block = {
|
||||
let patch = MirPatch::new(body);
|
||||
let patch = MirPatch::new(body_cache);
|
||||
let resume_block = patch.resume_block();
|
||||
patch.apply(body);
|
||||
patch.apply(body_cache);
|
||||
resume_block
|
||||
};
|
||||
debug!("remove_noop_landing_pads: resume block is {:?}", resume_block);
|
||||
|
||||
let mut jumps_folded = 0;
|
||||
let mut landing_pads_removed = 0;
|
||||
let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks().len());
|
||||
let mut nop_landing_pads = BitSet::new_empty(body_cache.basic_blocks().len());
|
||||
|
||||
// This is a post-order traversal, so that if A post-dominates B
|
||||
// then A will be visited before B.
|
||||
let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect();
|
||||
let postorder: Vec<_> = traversal::postorder(body_cache).map(|(bb, _)| bb).collect();
|
||||
for bb in postorder {
|
||||
debug!(" processing {:?}", bb);
|
||||
for target in body[bb].terminator_mut().successors_mut() {
|
||||
for target in body_cache[bb].terminator_mut().successors_mut() {
|
||||
if *target != resume_block && nop_landing_pads.contains(*target) {
|
||||
debug!(" folding noop jump to {:?} to resume block", target);
|
||||
*target = resume_block;
|
||||
|
@ -111,7 +111,7 @@ impl RemoveNoopLandingPads {
|
|||
}
|
||||
}
|
||||
|
||||
match body[bb].terminator_mut().unwind_mut() {
|
||||
match body_cache[bb].terminator_mut().unwind_mut() {
|
||||
Some(unwind) => {
|
||||
if *unwind == Some(resume_block) {
|
||||
debug!(" removing noop landing pad");
|
||||
|
@ -123,7 +123,7 @@ impl RemoveNoopLandingPads {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads);
|
||||
let is_nop_landing_pad = self.is_nop_landing_pad(bb, body_cache, &nop_landing_pads);
|
||||
if is_nop_landing_pad {
|
||||
nop_landing_pads.insert(bb);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use syntax_pos::Span;
|
|||
|
||||
use rustc::ty::{self, TyCtxt, Ty};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir::{self, Body, Location, Local};
|
||||
use rustc::mir::{self, Body, BodyCache, Location, Local};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use crate::transform::{MirPass, MirSource};
|
||||
|
||||
|
@ -26,7 +26,7 @@ use crate::dataflow::has_rustc_mir_with;
|
|||
pub struct SanityCheck;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for SanityCheck {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
let def_id = src.def_id();
|
||||
if !tcx.has_attr(def_id, sym::rustc_mir) {
|
||||
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
|
||||
|
@ -37,37 +37,37 @@ impl<'tcx> MirPass<'tcx> for SanityCheck {
|
|||
|
||||
let attributes = tcx.get_attrs(def_id);
|
||||
let param_env = tcx.param_env(def_id);
|
||||
let move_data = MoveData::gather_moves(body, tcx).unwrap();
|
||||
let move_data = MoveData::gather_moves(body_cache, tcx).unwrap();
|
||||
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
|
||||
let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
|
||||
let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len());
|
||||
let flow_inits =
|
||||
do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds,
|
||||
MaybeInitializedPlaces::new(tcx, body, &mdpe),
|
||||
do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds,
|
||||
MaybeInitializedPlaces::new(tcx, body_cache, &mdpe),
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
|
||||
let flow_uninits =
|
||||
do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds,
|
||||
MaybeUninitializedPlaces::new(tcx, body, &mdpe),
|
||||
do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds,
|
||||
MaybeUninitializedPlaces::new(tcx, body_cache, &mdpe),
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
|
||||
let flow_def_inits =
|
||||
do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds,
|
||||
DefinitelyInitializedPlaces::new(tcx, body, &mdpe),
|
||||
do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds,
|
||||
DefinitelyInitializedPlaces::new(tcx, body_cache, &mdpe),
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
|
||||
let flow_indirectly_mut =
|
||||
do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds,
|
||||
IndirectlyMutableLocals::new(tcx, body, param_env),
|
||||
do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds,
|
||||
IndirectlyMutableLocals::new(tcx, body_cache, param_env),
|
||||
|_, i| DebugFormatted::new(&i));
|
||||
|
||||
if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_init).is_some() {
|
||||
sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_inits);
|
||||
sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_inits);
|
||||
}
|
||||
if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_uninit).is_some() {
|
||||
sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_uninits);
|
||||
sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_uninits);
|
||||
}
|
||||
if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() {
|
||||
sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_def_inits);
|
||||
sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_def_inits);
|
||||
}
|
||||
if has_rustc_mir_with(&attributes, sym::rustc_peek_indirectly_mutable).is_some() {
|
||||
sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_indirectly_mut);
|
||||
sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_indirectly_mut);
|
||||
}
|
||||
if has_rustc_mir_with(&attributes, sym::stop_after_dataflow).is_some() {
|
||||
tcx.sess.fatal("stop_after_dataflow ended compilation");
|
||||
|
|
|
@ -43,12 +43,12 @@ impl SimplifyCfg {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn simplify_cfg(body: &mut Body<'_>) {
|
||||
CfgSimplifier::new(body).simplify();
|
||||
remove_dead_blocks(body);
|
||||
pub fn simplify_cfg(body_cache: &mut BodyCache<'_>) {
|
||||
CfgSimplifier::new(body_cache).simplify();
|
||||
remove_dead_blocks(body_cache);
|
||||
|
||||
// FIXME: Should probably be moved into some kind of pass manager
|
||||
body.basic_blocks_mut().raw.shrink_to_fit();
|
||||
body_cache.basic_blocks_mut().raw.shrink_to_fit();
|
||||
}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for SimplifyCfg {
|
||||
|
@ -56,9 +56,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg {
|
|||
Cow::Borrowed(&self.label)
|
||||
}
|
||||
|
||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body);
|
||||
simplify_cfg(body);
|
||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body_cache.body());
|
||||
simplify_cfg(body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,14 +68,14 @@ pub struct CfgSimplifier<'a, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
|
||||
pub fn new(body: &'a mut Body<'tcx>) -> Self {
|
||||
let mut pred_count = IndexVec::from_elem(0u32, body.basic_blocks());
|
||||
pub fn new(body_cache: &'a mut BodyCache<'tcx>) -> Self {
|
||||
let mut pred_count = IndexVec::from_elem(0u32, body_cache.basic_blocks());
|
||||
|
||||
// we can't use mir.predecessors() here because that counts
|
||||
// dead blocks, which we don't want to.
|
||||
pred_count[START_BLOCK] = 1;
|
||||
|
||||
for (_, data) in traversal::preorder(body) {
|
||||
for (_, data) in traversal::preorder(body_cache) {
|
||||
if let Some(ref term) = data.terminator {
|
||||
for &tgt in term.successors() {
|
||||
pred_count[tgt] += 1;
|
||||
|
@ -83,7 +83,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let basic_blocks = body.basic_blocks_mut();
|
||||
let basic_blocks = body_cache.basic_blocks_mut();
|
||||
|
||||
CfgSimplifier {
|
||||
basic_blocks,
|
||||
|
@ -260,13 +260,13 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn remove_dead_blocks(body: &mut Body<'_>) {
|
||||
let mut seen = BitSet::new_empty(body.basic_blocks().len());
|
||||
for (bb, _) in traversal::preorder(body) {
|
||||
pub fn remove_dead_blocks(body_cache: &mut BodyCache<'_>) {
|
||||
let mut seen = BitSet::new_empty(body_cache.basic_blocks().len());
|
||||
for (bb, _) in traversal::preorder(body_cache.body()) {
|
||||
seen.insert(bb.index());
|
||||
}
|
||||
|
||||
let basic_blocks = body.basic_blocks_mut();
|
||||
let basic_blocks = body_cache.basic_blocks_mut();
|
||||
|
||||
let num_blocks = basic_blocks.len();
|
||||
let mut replacements : Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
|
||||
|
@ -293,27 +293,27 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) {
|
|||
pub struct SimplifyLocals;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for SimplifyLocals {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
trace!("running SimplifyLocals on {:?}", source);
|
||||
let locals = {
|
||||
let mut marker = DeclMarker {
|
||||
locals: BitSet::new_empty(body.local_decls.len()),
|
||||
body,
|
||||
locals: BitSet::new_empty(body_cache.local_decls.len()),
|
||||
body: body_cache,
|
||||
};
|
||||
marker.visit_body(body);
|
||||
marker.visit_body(body_cache.read_only());
|
||||
// Return pointer and arguments are always live
|
||||
marker.locals.insert(RETURN_PLACE);
|
||||
for arg in body.args_iter() {
|
||||
for arg in body_cache.args_iter() {
|
||||
marker.locals.insert(arg);
|
||||
}
|
||||
|
||||
marker.locals
|
||||
};
|
||||
|
||||
let map = make_local_map(&mut body.local_decls, locals);
|
||||
let map = make_local_map(&mut body_cache.local_decls, locals);
|
||||
// Update references to all vars and tmps now
|
||||
LocalUpdater { map, tcx }.visit_body(body);
|
||||
body.local_decls.shrink_to_fit();
|
||||
LocalUpdater { map, tcx }.visit_body(body_cache);
|
||||
body_cache.local_decls.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches {
|
|||
Cow::Borrowed(&self.label)
|
||||
}
|
||||
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
let param_env = tcx.param_env(src.def_id());
|
||||
for block in body.basic_blocks_mut() {
|
||||
for block in body_cache.basic_blocks_mut() {
|
||||
let terminator = block.terminator_mut();
|
||||
terminator.kind = match terminator.kind {
|
||||
TerminatorKind::SwitchInt {
|
||||
|
|
|
@ -37,14 +37,14 @@ use crate::util::patch::MirPatch;
|
|||
pub struct UniformArrayMoveOut;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
let mut patch = MirPatch::new(body);
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
let mut patch = MirPatch::new(body_cache);
|
||||
let param_env = tcx.param_env(src.def_id());
|
||||
{
|
||||
let mut visitor = UniformArrayMoveOutVisitor{body, patch: &mut patch, tcx, param_env};
|
||||
visitor.visit_body(body);
|
||||
let mut visitor = UniformArrayMoveOutVisitor{ body: body_cache, patch: &mut patch, tcx, param_env};
|
||||
visitor.visit_body(body_cache.read_only());
|
||||
}
|
||||
patch.apply(body);
|
||||
patch.apply(body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,18 +184,18 @@ pub struct RestoreSubsliceArrayMoveOut<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||
let mut patch = MirPatch::new(body);
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) {
|
||||
let mut patch = MirPatch::new(body_cache);
|
||||
let param_env = tcx.param_env(src.def_id());
|
||||
{
|
||||
let mut visitor = RestoreDataCollector {
|
||||
locals_use: IndexVec::from_elem(LocalUse::new(), &body.local_decls),
|
||||
locals_use: IndexVec::from_elem(LocalUse::new(), &body_cache.local_decls),
|
||||
candidates: vec![],
|
||||
};
|
||||
visitor.visit_body(body);
|
||||
visitor.visit_body(body_cache.read_only());
|
||||
|
||||
for candidate in &visitor.candidates {
|
||||
let statement = &body[candidate.block].statements[candidate.statement_index];
|
||||
let statement = &body_cache[candidate.block].statements[candidate.statement_index];
|
||||
if let StatementKind::Assign(box(ref dst_place, ref rval)) = statement.kind {
|
||||
if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = *rval {
|
||||
let items : Vec<_> = items.iter().map(|item| {
|
||||
|
@ -203,7 +203,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> {
|
|||
if let Some(local) = place.as_local() {
|
||||
let local_use = &visitor.locals_use[local];
|
||||
let opt_index_and_place =
|
||||
Self::try_get_item_source(local_use, body);
|
||||
Self::try_get_item_source(local_use, body_cache);
|
||||
// each local should be used twice:
|
||||
// in assign and in aggregate statements
|
||||
if local_use.use_count == 2 && opt_index_and_place.is_some() {
|
||||
|
@ -218,7 +218,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> {
|
|||
let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
|
||||
let opt_size = opt_src_place.and_then(|src_place| {
|
||||
let src_ty =
|
||||
Place::ty_from(src_place.base, src_place.projection, body, tcx).ty;
|
||||
Place::ty_from(src_place.base, src_place.projection, body_cache.body(), tcx).ty;
|
||||
if let ty::Array(_, ref size_o) = src_ty.kind {
|
||||
size_o.try_eval_usize(tcx, param_env)
|
||||
} else {
|
||||
|
@ -232,7 +232,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
patch.apply(body);
|
||||
patch.apply(body_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ crate trait FindAssignments {
|
|||
impl<'a, 'tcx> FindAssignments for ReadOnlyBodyCache<'a, 'tcx>{
|
||||
fn find_assignments(&self, local: Local) -> Vec<Location>{
|
||||
let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]};
|
||||
visitor.visit_body(self);
|
||||
visitor.visit_body(*self);
|
||||
visitor.locations
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ impl DefUseAnalysis {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn analyze(&mut self, body_cache: &ReadOnlyBodyCache<'_, '_>) {
|
||||
pub fn analyze(&mut self, body_cache: ReadOnlyBodyCache<'_, '_>) {
|
||||
self.clear();
|
||||
|
||||
let mut finder = DefUseFinder {
|
||||
|
@ -55,7 +55,7 @@ impl DefUseAnalysis {
|
|||
fn mutate_defs_and_uses(
|
||||
&self,
|
||||
local: Local,
|
||||
body_cache: &mut BodyCache<&mut Body<'tcx>>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
new_local: Local,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) {
|
||||
|
@ -73,7 +73,7 @@ impl DefUseAnalysis {
|
|||
// FIXME(pcwalton): this should update the def-use chains.
|
||||
pub fn replace_all_defs_and_uses_with(&self,
|
||||
local: Local,
|
||||
body_cache: &mut BodyCache<&mut Body<'tcx>>,
|
||||
body_cache: &mut BodyCache<'tcx>,
|
||||
new_local: Local,
|
||||
tcx: TyCtxt<'tcx>) {
|
||||
self.mutate_defs_and_uses(local, body_cache, new_local, tcx)
|
||||
|
|
|
@ -57,7 +57,7 @@ pub struct LivenessResult {
|
|||
/// Computes which local variables are live within the given function
|
||||
/// `mir`, including drops.
|
||||
pub fn liveness_of_locals(
|
||||
body_cache: &ReadOnlyBodyCache<'_, '_>,
|
||||
body_cache: ReadOnlyBodyCache<'_, '_>,
|
||||
) -> LivenessResult {
|
||||
let num_live_vars = body_cache.local_decls.len();
|
||||
|
||||
|
@ -84,7 +84,7 @@ pub fn liveness_of_locals(
|
|||
// order when cycles are present, but the overhead of computing the reverse CFG may outweigh
|
||||
// any benefits. Benchmark this and find out.
|
||||
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body_cache.basic_blocks().len());
|
||||
for (bb, _) in traversal::postorder(body_cache) {
|
||||
for (bb, _) in traversal::postorder(body_cache.body()) {
|
||||
dirty_queue.insert(bb);
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ impl<'tcx> MirPatch<'tcx> {
|
|||
self.make_nop.push(loc);
|
||||
}
|
||||
|
||||
pub fn apply(self, body_cache: &mut BodyCache<&'_ mut Body<'tcx>>) {
|
||||
pub fn apply(self, body_cache: &mut BodyCache<'tcx>) {
|
||||
debug!("MirPatch: make nops at: {:?}", self.make_nop);
|
||||
for loc in self.make_nop {
|
||||
body_cache.make_statement_nop(loc);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue